diff options
Diffstat (limited to 'cpp/src')
1010 files changed, 0 insertions, 151913 deletions
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt deleted file mode 100644 index 0fe2d7e4d0..0000000000 --- a/cpp/src/CMakeLists.txt +++ /dev/null @@ -1,1305 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Option to require building optional plugins -foreach (r ${REQUIRE}) - set(${r}_force ON) - message(STATUS "Forcing ${r} to ${${r}_force}") -endforeach(r) - -include(CheckFunctionExists) -include(CheckIncludeFileCXX) -include(CheckIncludeFiles) -include(CheckIncludeFileCXX) -include(CheckLibraryExists) -include(CheckSymbolExists) -include(FindBoost) -include(FindDoxygen) - -#set (CMAKE_VERBOSE_MAKEFILE ON) # for debugging - -# -# Set up installation of .pdb files if the compiler is Visual Studio -# -# Sample: install_pdb (qpidcommon ${QPID_COMPONENT_COMMON}) -# -MACRO (install_pdb theLibrary theComponent) - if (MSVC) - get_target_property(library_dll ${theLibrary} LOCATION) - string(REPLACE .dll .pdb library_pdb ${library_dll}) - string(REPLACE $(OutDir) \${CMAKE_INSTALL_CONFIG_NAME} library_pdb ${library_pdb}) - string(REPLACE .pdb d.pdb libraryd_pdb ${library_pdb}) - #message(STATUS "_pdb: ${library_pdb}, ${libraryd_pdb}") - install (PROGRAMS - ${library_pdb} - DESTINATION ${QPID_INSTALL_LIBDIR}/ReleasePDB - COMPONENT ${theComponent} - OPTIONAL - CONFIGURATIONS Release|MinSizeRel) - install (PROGRAMS - ${library_pdb} - DESTINATION ${QPID_INSTALL_LIBDIR}/ReleasePDB - COMPONENT ${theComponent} - CONFIGURATIONS RelWithDebInfo) - install (PROGRAMS - ${libraryd_pdb} - DESTINATION ${QPID_INSTALL_LIBDIR}/DebugPDB - COMPONENT ${theComponent} - CONFIGURATIONS Debug) - endif (MSVC) -ENDMACRO (install_pdb) - -# -# inherit_value - if the symbol is undefined then set it to the given value. -# Set flag to indicate this symbol was defined here. -# -MACRO (inherit_value theSymbol theValue) - if (NOT DEFINED ${theSymbol}) - set (${theSymbol} ${theValue}) - # message ("Set symbol '${theSymbol}' to value '${theValue}'") - set (${theSymbol}_inherited = "true") - endif (NOT DEFINED ${theSymbol}) -ENDMACRO (inherit_value) - -# -# If compiler is Visual Studio then create a "version resource" for the project. -# Use this call to override CPACK and file global settings but not file per-project settings. -# Two groups of four version numbers specify "file" and "product" versions separately. -# -# Sample: add_msvc_version_full (qmfengine library dll 1 0 0 1 1 0 0 1) -# -MACRO (add_msvc_version_full verProject verProjectType verProjectFileExt verFN1 verFN2 verFN3 verFN4 verPN1 verPN2 verPN3 verPN4) - if (MSVC) - # Create project-specific version strings - inherit_value ("winver_${verProject}_FileVersionBinary" "${verFN1},${verFN2},${verFN3},${verFN4}") - inherit_value ("winver_${verProject}_ProductVersionBinary" "${verPN1},${verPN2},${verPN3},${verPN4}") - inherit_value ("winver_${verProject}_FileVersionString" "${verFN1}, ${verFN2}, ${verFN3}, ${verFN4}") - inherit_value ("winver_${verProject}_ProductVersionString" "${verPN1}, ${verPN2}, ${verPN3}, ${verPN4}") - inherit_value ("winver_${verProject}_FileDescription" "${winver_PACKAGE_NAME}-${verProject} ${verProjectType}") - inherit_value ("winver_${verProject}_LegalCopyright" "${winver_LEGAL_COPYRIGHT}") - inherit_value ("winver_${verProject}_InternalName" "${verProject}") - inherit_value ("winver_${verProject}_OriginalFilename" "${verProject}.${verProjectFileExt}") - inherit_value ("winver_${verProject}_ProductName" "${winver_DESCRIPTION_SUMMARY}") - - # Create strings to be substituted into the template file - set ("winverFileVersionBinary" "${winver_${verProject}_FileVersionBinary}") - set ("winverProductVersionBinary" "${winver_${verProject}_ProductVersionBinary}") - set ("winverFileVersionString" "${winver_${verProject}_FileVersionString}") - set ("winverProductVersionString" "${winver_${verProject}_ProductVersionString}") - set ("winverFileDescription" "${winver_${verProject}_FileDescription}") - set ("winverLegalCopyright" "${winver_${verProject}_LegalCopyright}") - set ("winverInternalName" "${winver_${verProject}_InternalName}") - set ("winverOriginalFilename" "${winver_${verProject}_OriginalFilename}") - set ("winverProductName" "${winver_${verProject}_ProductName}") - - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/resources/template-resource.rc - ${CMAKE_CURRENT_BINARY_DIR}/windows/resources/${verProject}-resource.rc) - set (${verProject}_SOURCES - ${${verProject}_SOURCES} - ${CMAKE_CURRENT_BINARY_DIR}/windows/resources/${verProject}-resource.rc - ) - endif (MSVC) -ENDMACRO (add_msvc_version_full) - -# -# If compiler is Visual Studio then create a "version resource" for the project. -# Use this call to accept file override version settings or -# inherited CPACK_PACKAGE_VERSION version settings. -# -# Sample: add_msvc_version (qpidcommon library dll) -# -MACRO (add_msvc_version verProject verProjectType verProjectFileExt) - if (MSVC) - add_msvc_version_full (${verProject} - ${verProjectType} - ${verProjectFileExt} - ${winver_FILE_VERSION_N1} - ${winver_FILE_VERSION_N2} - ${winver_FILE_VERSION_N3} - ${winver_FILE_VERSION_N4} - ${winver_PRODUCT_VERSION_N1} - ${winver_PRODUCT_VERSION_N2} - ${winver_PRODUCT_VERSION_N3} - ${winver_PRODUCT_VERSION_N4}) - endif (MSVC) -ENDMACRO (add_msvc_version) - - -# -# Install optional windows version settings. Override variables are specified in a file. -# -include (./CMakeWinVersions.cmake OPTIONAL) - -# -# Inherit global windows version settings from CPACK settings. -# -inherit_value ("winver_PACKAGE_NAME" "${CPACK_PACKAGE_NAME}") -inherit_value ("winver_DESCRIPTION_SUMMARY" "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") -inherit_value ("winver_FILE_VERSION_N1" "${CPACK_PACKAGE_VERSION_MAJOR}") -inherit_value ("winver_FILE_VERSION_N2" "${CPACK_PACKAGE_VERSION_MINOR}") -inherit_value ("winver_FILE_VERSION_N3" "${CPACK_PACKAGE_VERSION_PATCH}") -inherit_value ("winver_FILE_VERSION_N4" "1") -inherit_value ("winver_PRODUCT_VERSION_N1" "${winver_FILE_VERSION_N1}") -inherit_value ("winver_PRODUCT_VERSION_N2" "${winver_FILE_VERSION_N2}") -inherit_value ("winver_PRODUCT_VERSION_N3" "${winver_FILE_VERSION_N3}") -inherit_value ("winver_PRODUCT_VERSION_N4" "${winver_FILE_VERSION_N4}") -inherit_value ("winver_LEGAL_COPYRIGHT" "") - - -# check if we generate source as part of the build -# - rubygen generates the amqp spec and clustering -# - managementgen generates the broker management code -# -# rubygen subdir is excluded from stable distributions -# If the main AMQP spec is present, then check if ruby and python are -# present, and if any sources have changed, forcing a re-gen of source code. - -set(AMQP_SPEC_DIR ${qpid-cpp_SOURCE_DIR}/../specs) -set(AMQP_SPEC ${AMQP_SPEC_DIR}/amqp.0-10-qpid-errata.xml) -if (EXISTS ${AMQP_SPEC}) - include(FindRuby) - include(FindPythonInterp) - if (NOT RUBY_EXECUTABLE) - message(FATAL_ERROR "Can't locate ruby, needed to generate source files.") - endif (NOT RUBY_EXECUTABLE) - if (NOT PYTHON_EXECUTABLE) - message(FATAL_ERROR "Can't locate python, needed to generate source files.") - endif (NOT PYTHON_EXECUTABLE) - - set(specs ${AMQP_SPEC} ${qpid-cpp_SOURCE_DIR}/xml/cluster.xml) - set(regen_amqp OFF) - set(rgen_dir ${qpid-cpp_SOURCE_DIR}/rubygen) - file(GLOB_RECURSE rgen_progs ${rgen_dir}/*.rb) - # If any of the specs, or any of the sources used to generate code, change - # then regenerate the sources. - foreach (spec_file ${specs} ${rgen_progs}) - if (${spec_file} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/rubygen.cmake) - set(regen_amqp ON) - endif (${spec_file} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/rubygen.cmake) - endforeach (spec_file ${specs}) - if (regen_amqp) - message(STATUS "Regenerating AMQP protocol sources") -execute_process(COMMAND ${RUBY_EXECUTABLE} -I ${rgen_dir} ${rgen_dir}/generate ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/../include ${specs} all rubygen.cmake - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - else (regen_amqp) - message(STATUS "No need to generate AMQP protocol sources") - endif (regen_amqp) - - set(mgmt_specs ${AMQP_SPEC_DIR}/management-schema.xml - ${CMAKE_CURRENT_SOURCE_DIR}/qpid/acl/management-schema.xml - ${CMAKE_CURRENT_SOURCE_DIR}/qpid/cluster/management-schema.xml) - set(mgen_dir ${qpid-cpp_SOURCE_DIR}/managementgen) - set(regen_mgmt OFF) - foreach (spec_file ${mgmt_specs}) - if (${spec_file} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/managementgen.cmake) - message(STATUS "${spec_file} is newer") - set(regen_mgmt ON) - endif (${spec_file} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/managementgen.cmake) - endforeach (spec_file ${mgmt_specs}) - if (regen_mgmt) - message(STATUS "Regenerating Qpid Management Framework sources") -execute_process(COMMAND ${PYTHON_EXECUTABLE} ${mgen_dir}/qmf-gen -c managementgen.cmake -b -q -o ${CMAKE_CURRENT_BINARY_DIR}/qmf ${mgmt_specs} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - else (regen_mgmt) - message(STATUS "No need to generate Qpid Management Framework sources") - endif (regen_mgmt) - - # Pull in the names of the generated files, i.e. ${rgen_framing_srcs} - include (${CMAKE_CURRENT_BINARY_DIR}/rubygen.cmake) - include (${CMAKE_CURRENT_BINARY_DIR}/managementgen.cmake) - -else (EXISTS ${AMQP_SPEC}) - message(STATUS "No AMQP spec... presume generated sources are included") - set(QPID_GENERATED_HEADERS_IN_SOURCE ON) - include (rubygen.cmake) - include (managementgen.cmake) -endif (EXISTS ${AMQP_SPEC}) - -find_program(HELP2MAN help2man DOC "Location of the help2man program") -option(GEN_MANPAGES "Use help2man to generate man pages" ON) -if (GEN_MANPAGES AND NOT HELP2MAN) - message(STATUS "Can't locate the help2man command; man pages will not be generated") - set (GEN_MANPAGES OFF) -endif (GEN_MANPAGES AND NOT HELP2MAN) - -# FindDoxygen module tries to locate doxygen and Graphviz dot -set (docs_default ON) -if (NOT DOXYGEN_EXECUTABLE) - set (docs_default OFF) -endif (NOT DOXYGEN_EXECUTABLE) -option(GEN_DOXYGEN "Use doxygen to generate user documentation" ${docs_default}) -if (GEN_DOXYGEN AND NOT DOXYGEN_EXECUTABLE) - message(STATUS "Can't locate the doxygen command; user documentation will not be generated") - set (GEN_DOXYGEN OFF) -endif (GEN_DOXYGEN AND NOT DOXYGEN_EXECUTABLE) - -find_program(VALGRIND valgrind DOC "Location of the valgrind program") -option(ENABLE_VALGRIND "Use valgrind to detect run-time problems" ON) -if (ENABLE_VALGRIND AND NOT VALGRIND) - message(STATUS "Can't locate the valgrind command; no run-time error detection") -endif (ENABLE_VALGRIND AND NOT VALGRIND) - -if (CMAKE_COMPILER_IS_GNUCXX) - set (COMPILER_FLAGS "") - # Warnings: Enable as many as possible, keep the code clean. Please - # do not disable warnings or remove -Werror without discussing on - # qpid-dev list. - # - # The following warnings are deliberately omitted, they warn on valid code. - # -Wunreachable-code -Wpadded -Winline - # -Wshadow - warns about boost headers. - set (WARNING_FLAGS - "-Werror -pedantic -Wall -Wextra -Wno-shadow -Wpointer-arith -Wcast-qual -Wcast-align -Wno-long-long -Wvolatile-register-var -Winvalid-pch -Wno-system-headers -Woverloaded-virtual") -endif (CMAKE_COMPILER_IS_GNUCXX) - -if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro) - set (COMPILER_FLAGS "-library=stlport4 -mt") - set (WARNING_FLAGS "+w2") -endif (CMAKE_CXX_COMPILER_ID STREQUAL SunPro) - -option(ENABLE_WARNINGS "Enable lots of compiler warnings (recommended)" ON) -if (NOT ENABLE_WARNINGS) - set (WARNING_FLAGS "") -endif (NOT ENABLE_WARNINGS) - -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS} ${WARNING_FLAGS}") - -# Expand a bit from the basic Find_Boost; be specific about what's needed. -# TODO: Not all these libs are needed everywhere: -# Linux only uses filesystem program_options unit_test_framework -# (which itself uses regex). -# Boost.system is sometimes needed; it's handled separately, below. -find_package(Boost 1.33 REQUIRED - COMPONENTS filesystem program_options date_time thread - regex unit_test_framework) -if(NOT Boost_FOUND) - message(FATAL_ERROR "Boost C++ libraries not found. Please install or try setting BOOST_ROOT") -endif(NOT Boost_FOUND) - -# Boost.system was introduced at Boost 1.35; it's needed secondarily by other -# Boost libs Qpid needs, so be sure it's there. -if (Boost_VERSION GREATER 103499) - find_package(Boost COMPONENTS system) - - # Allow for cmake pre 2.6 and boost post 1.35 - if (NOT Boost_SYSTEM_LIBRARY) - set(Boost_SYSTEM_LIBRARY boost_system) - endif (NOT Boost_SYSTEM_LIBRARY) -endif (Boost_VERSION GREATER 103499) - -# Versions of cmake pre 2.6 don't set the Boost_*_LIBRARY variables correctly -# these values are correct for Linux -if (NOT Boost_PROGRAM_OPTIONS_LIBRARY) - set(Boost_PROGRAM_OPTIONS_LIBRARY boost_program_options) -endif (NOT Boost_PROGRAM_OPTIONS_LIBRARY) - -if (NOT Boost_FILESYSTEM_LIBRARY) - set(Boost_FILESYSTEM_LIBRARY boost_filesystem) -endif (NOT Boost_FILESYSTEM_LIBRARY) - -if (NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY) - set(Boost_UNIT_TEST_FRAMEWORK_LIBRARY boost_unit_test_framework) -endif (NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY) - -if (NOT Boost_REGEX_LIBRARY) - set(Boost_REGEX_LIBRARY boost_regex) -endif (NOT Boost_REGEX_LIBRARY) - -# The Windows install also wants the Boost DLLs, libs and headers that the -# release is built with. The DLLs enable everything to run, and the headers -# and libs ensure that users building Qpid C++ client programs can compile -# (the C++ API still exposes Boost headers, but hopefully this will be fixed -# in the future). -# -# On Windows you can pick whether the static or dynamic versions of the libs -# are used; allow this choice to the user. Since we also install the Boost -# DLLs that are needed for the Windows package, none are needed for the -# static link case; else drop them into the install. Do this all first, since -# Boost on Windows can use automatic linking to pick up the correct -# Boost libs based on compile-time touching of the headers. Since we don't -# really need to add them to the link lines, set the names to blanks. -if (MSVC) - install (PROGRAMS - ${Boost_DATE_TIME_LIBRARY_DEBUG} ${Boost_DATE_TIME_LIBRARY_RELEASE} - ${Boost_FILESYSTEM_LIBRARY_DEBUG} ${Boost_FILESYSTEM_LIBRARY_RELEASE} - ${Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG} ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE} - ${Boost_REGEX_LIBRARY_DEBUG} ${Boost_REGEX_LIBRARY_RELEASE} - ${Boost_THREAD_LIBRARY_DEBUG} ${Boost_THREAD_LIBRARY_RELEASE} - DESTINATION ${QPID_INSTALL_LIBDIR}/boost - COMPONENT ${QPID_COMPONENT_COMMON}) - - if (NOT Boost_VERSION LESS 103500) - install (PROGRAMS - ${Boost_SYSTEM_LIBRARY_DEBUG} ${Boost_SYSTEM_LIBRARY_RELEASE} - DESTINATION ${QPID_INSTALL_LIBDIR}/boost - COMPONENT ${QPID_COMPONENT_COMMON}) - endif (NOT Boost_VERSION LESS 103500) - - option(QPID_LINK_BOOST_DYNAMIC "Link with dynamic Boost libs (OFF to link static)" ON) - if (QPID_LINK_BOOST_DYNAMIC) - add_definitions( /D BOOST_ALL_DYN_LINK) - string (REPLACE .lib .dll - _boost_date_time_debug ${Boost_DATE_TIME_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_date_time_release ${Boost_DATE_TIME_LIBRARY_RELEASE}) - string (REPLACE .lib .dll - _boost_filesystem_debug ${Boost_FILESYSTEM_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_filesystem_release ${Boost_FILESYSTEM_LIBRARY_RELEASE}) - string (REPLACE .lib .dll - _boost_program_options_debug ${Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_program_options_release ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE}) - string (REPLACE .lib .dll - _boost_regex_debug ${Boost_REGEX_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_regex_release ${Boost_REGEX_LIBRARY_RELEASE}) - string (REPLACE .lib .dll - _boost_thread_debug ${Boost_THREAD_LIBRARY_DEBUG}) - string (REPLACE .lib .dll - _boost_thread_release ${Boost_THREAD_LIBRARY_RELEASE}) - # Boost 1.35 added the system library, which gets indirectly linked in - # via other Boost libs. So, if building with Boost 1.35 or later, also - # include system in the Windows install package. - if (NOT Boost_VERSION LESS 103500) - string (REPLACE boost_thread boost_system - _boost_system_debug ${_boost_thread_debug}) - string (REPLACE boost_thread boost_system - _boost_system_release ${_boost_thread_release}) - endif (NOT Boost_VERSION LESS 103500) - install (PROGRAMS - ${_boost_date_time_debug} ${_boost_date_time_release} - ${_boost_filesystem_debug} ${_boost_filesystem_release} - ${_boost_program_options_debug} ${_boost_program_options_release} - ${_boost_regex_debug} ${_boost_regex_release} - ${_boost_system_debug} ${_boost_system_release} - ${_boost_thread_debug} ${_boost_thread_release} - DESTINATION ${QPID_INSTALL_LIBDIR}/boost - COMPONENT ${QPID_COMPONENT_COMMON}) - endif (QPID_LINK_BOOST_DYNAMIC) - - # Need the boost headers regardless of which way the libs go. Try to - # weed out what we don't need, else it's giant and unnecessary. - install (DIRECTORY ${Boost_INCLUDE_DIR}/boost - DESTINATION ${QPID_INSTALL_INCLUDEDIR} - COMPONENT ${QPID_COMPONENT_CLIENT_INCLUDE} - PATTERN "accumulators/*" EXCLUDE - PATTERN "algorithm/*" EXCLUDE - PATTERN "archive/*" EXCLUDE - PATTERN "asio*" EXCLUDE - PATTERN "bimap*" EXCLUDE - PATTERN "circular_buffer*" EXCLUDE - PATTERN "concept*" EXCLUDE - PATTERN "dynamic_bitset*" EXCLUDE - PATTERN "flyweight*" EXCLUDE - PATTERN "fusion/*" EXCLUDE - PATTERN "gil/*" EXCLUDE - PATTERN "graph/*" EXCLUDE - PATTERN "interprocess/*" EXCLUDE - PATTERN "lambda/*" EXCLUDE - PATTERN "logic/*" EXCLUDE - PATTERN "math*" EXCLUDE - PATTERN "mpi*" EXCLUDE - PATTERN "multi_*" EXCLUDE - PATTERN "numeric/*" EXCLUDE - PATTERN "pending/*" EXCLUDE - PATTERN "pool/*" EXCLUDE - PATTERN "property_map/*" EXCLUDE - PATTERN "proto/*" EXCLUDE - PATTERN "random*" EXCLUDE - PATTERN "signals*" EXCLUDE - PATTERN "spirit*" EXCLUDE - PATTERN "statechart/*" EXCLUDE - PATTERN "units/*" EXCLUDE - PATTERN "unordered*" EXCLUDE - PATTERN "wave*" EXCLUDE - PATTERN "xpressive/*" EXCLUDE) - - set(Boost_DATE_TIME_LIBRARY "") - set(Boost_THREAD_LIBRARY "") - set(Boost_PROGRAM_OPTIONS_LIBRARY "") - set(Boost_FILESYSTEM_LIBRARY "") - set(Boost_UNIT_TEST_FRAMEWORK_LIBRARY "") - set(Boost_REGEX_LIBRARY "") - include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/windows/resources ) -endif (MSVC) - -include_directories( ${Boost_INCLUDE_DIR} ) - -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../include ) -include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/../include ) - -link_directories( ${Boost_LIBRARY_DIRS} ) - -CHECK_LIBRARY_EXISTS (rt clock_gettime "" CLOCK_GETTIME_IN_RT) -if (NOT CLOCK_GETTIME_IN_RT) - CHECK_FUNCTION_EXISTS (clock_gettime QPID_HAS_CLOCK_GETTIME) -else (NOT CLOCK_GETTIME_IN_RT) - set(CMAKE_REQUIRED_LIBS ${CMAKE_REQUIRED_LIBS} rt) - set(QPID_HAS_CLOCK_GETTIME YES CACHE BOOL "Platform has clock_gettime") -endif (NOT CLOCK_GETTIME_IN_RT) - -# See if Cyrus SASL is desired and available -CHECK_LIBRARY_EXISTS (sasl2 sasl_checkpass "" HAVE_SASL) -CHECK_INCLUDE_FILES (sasl/sasl.h HAVE_SASL_H) - -set (sasl_default ${sasl_force}) -if (HAVE_SASL AND HAVE_SASL_H) - set (sasl_default ON) -endif (HAVE_SASL AND HAVE_SASL_H) - -option(BUILD_SASL "Build with Cyrus SASL support" ${sasl_default}) -if (BUILD_SASL) - if (NOT HAVE_SASL) - message(FATAL_ERROR "Cyrus SASL support requested but libsasl2 not found") - endif (NOT HAVE_SASL) - if (NOT HAVE_SASL_H) - message(FATAL_ERROR "Cyrus SASL support requested but sasl.h not found") - endif (NOT HAVE_SASL_H) - - set(BROKER_SASL_NAME "qpidd" CACHE STRING "SASL app name for the qpid broker") - set(qpidcommon_sasl_source - qpid/sys/cyrus/CyrusSecurityLayer.h - qpid/sys/cyrus/CyrusSecurityLayer.cpp - ) - set(qpidcommon_sasl_lib sasl2) -endif (BUILD_SASL) - -# See if XML Exchange is desired and prerequisites are available -CHECK_LIBRARY_EXISTS (xerces-c _init "" HAVE_XERCES) -CHECK_INCLUDE_FILE_CXX (xercesc/framework/MemBufInputSource.hpp HAVE_XERCES_H) -CHECK_INCLUDE_FILE_CXX (xqilla/xqilla-simple.hpp HAVE_XQILLA_H) -CHECK_INCLUDE_FILE_CXX (xqilla/ast/XQEffectiveBooleanValue.hpp HAVE_XQ_EBV) - -set (xml_default ${xml_force}) -if (CMAKE_SYSTEM_NAME STREQUAL Windows) -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - if (HAVE_XERCES AND HAVE_XERCES_H) - if (HAVE_XQILLA_H) - set (xml_default ON) - endif (HAVE_XQILLA_H) - endif (HAVE_XERCES AND HAVE_XERCES_H) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -option(BUILD_XML "Build with XML Exchange" ${xml_default}) -if (BUILD_XML) - if (NOT HAVE_XERCES) - message(FATAL_ERROR "XML Exchange support requested but xerces-c library not found") - endif (NOT HAVE_XERCES) - if (NOT HAVE_XERCES_H) - message(FATAL_ERROR "XML Exchange support requested but Xerces-C headers not found") - endif (NOT HAVE_XERCES_H) - if (NOT HAVE_XQILLA_H) - message(FATAL_ERROR "XML Exchange support requested but XQilla headers not found") - endif (NOT HAVE_XQILLA_H) - - if (HAVE_XQ_EBV) - add_definitions(-DXQ_EFFECTIVE_BOOLEAN_VALUE_HPP) - endif (HAVE_XQ_EBV) - - add_library (xml MODULE - qpid/xml/XmlExchange.cpp - qpid/xml/XmlExchange.h - qpid/xml/XmlExchangePlugin.cpp) - set_target_properties (xml PROPERTIES PREFIX "") - target_link_libraries (xml xerces-c xqilla qpidbroker pthread) - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties (xml PROPERTIES - PREFIX "" - LINK_FLAGS -Wl,--no-undefined) - endif (CMAKE_COMPILER_IS_GNUCXX) - install (TARGETS xml - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - - set(xml_tests XmlClientSessionTest) - -endif (BUILD_XML) - -# Build the ACL plugin -set (acl_default ON) -option(BUILD_ACL "Build ACL enforcement broker plugin" ${acl_default}) -if (BUILD_ACL) - set (acl_SOURCES - qpid/acl/Acl.cpp - qpid/acl/Acl.h - qpid/acl/AclData.cpp - qpid/acl/AclData.h - qpid/acl/AclPlugin.cpp - qpid/acl/AclReader.cpp - qpid/acl/AclReader.h - qpid/acl/AclValidator.cpp - qpid/acl/AclValidator.h - ) - # Windows builds the ACL code into the qpidbroker library; see QPID-1842 - # for history and rationale. If this is changed, remove the acl_SOURCES from - # the qpidbroker platform-specific source list. - if (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) - add_library (acl MODULE ${acl_SOURCES}) - set_target_properties (acl PROPERTIES PREFIX "") - target_link_libraries (acl qpidbroker ${Boost_PROGRAM_OPTIONS_LIBRARY}) - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties (acl PROPERTIES - PREFIX "" - LINK_FLAGS -Wl,--no-undefined) - endif (CMAKE_COMPILER_IS_GNUCXX) - install (TARGETS acl - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - endif (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) -endif (BUILD_ACL) - -# Check for optional cluster support requirements -include (cluster.cmake) - -# Check for optional RDMA support requirements -include (rdma.cmake) - -# Check for optional SSL support requirements -include (ssl.cmake) - -# Check for syslog capabilities not present on all systems -check_symbol_exists (LOG_AUTHPRIV "sys/syslog.h" HAVE_LOG_AUTHPRIV) -check_symbol_exists (LOG_FTP "sys/syslog.h" HAVE_LOG_FTP) - -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - if (MSVC) - add_definitions( - /D "_CRT_NONSTDC_NO_WARNINGS" - /D "NOMINMAX" - /D "WIN32_LEAN_AND_MEAN" - /wd4244 - /wd4800 - /wd4355 - ) - if (MSVC80) - add_definitions(/D "_WIN32_WINNT=0x0501") - endif (MSVC80) - - # set the RelWithDebInfo compile/link switches to equal Release - set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /O2 /Ob2 /D NDEBUG") - set (CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "/debug /INCREMENTAL:NO") - - if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../bindings/qpid/dotnet/src) - # Set the windows version for the .NET Binding cpp project - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../bindings/qpid/dotnet/src/org.apache.qpid.messaging.template.rc - ${CMAKE_CURRENT_BINARY_DIR}/windows/resources/org.apache.qpid.messaging.rc) - # Set the windows version for the .NET Binding sessionreceiver project - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../bindings/qpid/dotnet/src/sessionreceiver/properties/sessionreceiver-AssemblyInfo-template.cs - ${CMAKE_CURRENT_BINARY_DIR}/windows/generated_src/sessionreceiver-AssemblyInfo.cs) - endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../bindings/qpid/dotnet/src) - endif (MSVC) - - set (qpidtypes_platform_SOURCES - qpid/sys/windows/uuid.cpp - ) - set (qpidtypes_platform_LIBS - rpcrt4 - ) - - set (qpidcommon_platform_SOURCES - qpid/log/windows/SinkOptions.cpp - qpid/sys/windows/AsynchIO.cpp - qpid/sys/windows/FileSysDir.cpp - qpid/sys/windows/IocpPoller.cpp - qpid/sys/windows/IOHandle.cpp - qpid/sys/windows/LockFile.cpp - qpid/sys/windows/PipeHandle.cpp - qpid/sys/windows/PollableCondition.cpp - qpid/sys/windows/Shlib.cpp - qpid/sys/windows/Socket.cpp - qpid/sys/windows/SocketAddress.cpp - qpid/sys/windows/StrError.cpp - qpid/sys/windows/SystemInfo.cpp - qpid/sys/windows/Thread.cpp - qpid/sys/windows/Time.cpp - qpid/client/windows/SaslFactory.cpp - ${sslcommon_windows_SOURCES} - ) - - set (qpidcommon_platform_LIBS - ${Boost_THREAD_LIBRARY} ${windows_ssl_libs} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ws2_32 ) - set (qpidbroker_platform_SOURCES - qpid/broker/windows/BrokerDefaults.cpp - qpid/broker/windows/SaslAuthenticator.cpp - ${acl_SOURCES} - ${sslbroker_windows_SOURCES} - ) - set (qpidbroker_platform_LIBS - ${windows_ssl_libs} ${windows_ssl_server_libs} - ) - set (qpidclient_platform_SOURCES - ${sslclient_windows_SOURCES} - ) - set (qpidclient_platform_LIBS - ${windows_ssl_libs} - ) - - set (qpidd_platform_SOURCES - windows/QpiddBroker.cpp - ) - - set (qpidmessaging_platform_SOURCES - qpid/messaging/HandleInstantiator.cpp - ) - -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - - # POSIX (Non-Windows) platforms have a lot of overlap in sources; the only - # major difference is the poller module. - if (CMAKE_SYSTEM_NAME STREQUAL Linux) - set (qpid_poller_module - qpid/sys/epoll/EpollPoller.cpp - qpid/sys/posix/SystemInfo.cpp - ) - add_definitions(-pthread) - set (CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} -pthread) - endif (CMAKE_SYSTEM_NAME STREQUAL Linux) - - if (CMAKE_SYSTEM_NAME STREQUAL SunOS) - set (qpid_poller_module - qpid/sys/solaris/ECFPoller.cpp - qpid/sys/solaris/SystemInfo.cpp - ) - endif (CMAKE_SYSTEM_NAME STREQUAL SunOS) - - set (qpidtypes_platform_SOURCES) - set (qpidtypes_platform_LIBS - uuid - ) - - set (qpidcommon_platform_SOURCES - qpid/sys/posix/AsynchIO.cpp - qpid/sys/posix/Fork.cpp - qpid/sys/posix/FileSysDir.cpp - qpid/sys/posix/IOHandle.cpp - qpid/sys/posix/LockFile.cpp - qpid/sys/posix/Mutex.cpp - qpid/sys/posix/PipeHandle.cpp - qpid/sys/posix/PollableCondition.cpp - qpid/sys/posix/Shlib.cpp - qpid/log/posix/SinkOptions.cpp - qpid/sys/posix/Socket.cpp - qpid/sys/posix/SocketAddress.cpp - qpid/sys/posix/StrError.cpp - qpid/sys/posix/Thread.cpp - qpid/sys/posix/Time.cpp - qpid/SaslFactory.cpp - - ${qpid_poller_module} - ) - set (qpidcommon_platform_LIBS - ${Boost_PROGRAM_OPTIONS_LIBRARY} - ${Boost_FILESYSTEM_LIBRARY} - ${CMAKE_DL_LIBS} - ) - - set (qpidbroker_platform_SOURCES - qpid/broker/Daemon.cpp - qpid/broker/SaslAuthenticator.cpp - qpid/broker/SignalHandler.h - qpid/broker/SignalHandler.cpp - qpid/broker/posix/BrokerDefaults.cpp - ) - - set (qpidclient_platform_SOURCES - ) - - set (qpidd_platform_SOURCES - posix/QpiddBroker.cpp - ) - - set (qpidmessaging_platform_SOURCES - ) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -set (qpidcommon_SOURCES - ${rgen_framing_srcs} - ${qpidcommon_platform_SOURCES} - ${qpidcommon_sasl_source} - qpid/assert.cpp - qpid/Address.cpp - qpid/DataDir.cpp - qpid/Exception.cpp - qpid/Modules.cpp - qpid/Options.cpp - qpid/Plugin.cpp - qpid/RefCountedBuffer.cpp - qpid/SessionState.cpp - qpid/SessionId.cpp - qpid/StringUtils.cpp - qpid/Url.cpp - qpid/amqp_0_10/SessionHandler.cpp - qpid/framing/AccumulatedAck.cpp - qpid/framing/AMQBody.cpp - qpid/framing/AMQMethodBody.cpp - qpid/framing/AMQContentBody.cpp - qpid/framing/AMQFrame.cpp - qpid/framing/AMQHeaderBody.cpp - qpid/framing/AMQHeartbeatBody.cpp - qpid/framing/Array.cpp - qpid/framing/BodyHandler.cpp - qpid/framing/Buffer.cpp - qpid/framing/Endian.cpp - qpid/framing/FieldTable.cpp - qpid/framing/FieldValue.cpp - qpid/framing/FrameSet.cpp - qpid/framing/FrameDecoder.cpp - qpid/framing/List.cpp - qpid/framing/ProtocolInitiation.cpp - qpid/framing/ProtocolVersion.cpp - qpid/framing/SendContent.cpp - qpid/framing/SequenceNumber.cpp - qpid/framing/SequenceNumberSet.cpp - qpid/framing/SequenceSet.cpp - qpid/framing/Proxy.cpp - qpid/framing/Uuid.cpp - qpid/framing/TransferContent.cpp - qpid/log/Logger.cpp - qpid/log/Options.cpp - qpid/log/OstreamOutput.cpp - qpid/log/Selector.cpp - qpid/log/Statement.cpp - qpid/management/Buffer.cpp - qpid/management/ConnectionSettings.cpp - qpid/management/Mutex.cpp - qpid/management/Manageable.cpp - qpid/management/ManagementObject.cpp - qpid/sys/AggregateOutput.cpp - qpid/sys/AsynchIOHandler.cpp - qpid/sys/ClusterSafe.cpp - qpid/sys/Dispatcher.cpp - qpid/sys/DispatchHandle.cpp - qpid/sys/Runnable.cpp - qpid/sys/Shlib.cpp - qpid/sys/Timer.cpp - qpid/sys/TimerWarnings.cpp - qpid/amqp_0_10/Codecs.cpp -) -add_msvc_version (qpidcommon library dll) - -add_library (qpidcommon SHARED ${qpidcommon_SOURCES}) -if (CLOCK_GETTIME_IN_RT) - set (qpidcommon_platform_LIBS ${qpidcommon_platform_LIBS} rt) -endif (CLOCK_GETTIME_IN_RT) -target_link_libraries (qpidcommon qpidtypes - ${qpidcommon_platform_LIBS} - ${qpidcommon_sasl_lib}) -set_target_properties (qpidcommon PROPERTIES - VERSION ${qpidc_version}) -install (TARGETS qpidcommon - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_COMMON}) -install_pdb (qpidcommon ${QPID_COMPONENT_COMMON}) - -set(qpidtypes_SOURCES - qpid/types/Exception.cpp - qpid/types/Uuid.cpp - qpid/types/Variant.cpp - ${qpidtypes_platform_SOURCES} -) -add_msvc_version (qpidtypes library dll) -add_library(qpidtypes SHARED ${qpidtypes_SOURCES}) -target_link_libraries(qpidtypes ${qpidtypes_platform_LIBS}) -set_target_properties (qpidtypes PROPERTIES VERSION ${qpidc_version}) -install(TARGETS qpidtypes - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_COMMON}) -install_pdb (qpidtypes ${QPID_COMPONENT_COMMON}) - -set (qpidclient_SOURCES - ${rgen_client_srcs} - ${qpidclient_platform_SOURCES} - qpid/client/Bounds.cpp - qpid/client/Completion.cpp - qpid/client/Connection.cpp - qpid/client/ConnectionHandler.cpp - qpid/client/ConnectionImpl.cpp - qpid/client/ConnectionSettings.cpp - qpid/client/Connector.cpp - qpid/client/Demux.cpp - qpid/client/Dispatcher.cpp - qpid/client/FailoverManager.cpp - qpid/client/FailoverListener.cpp - qpid/client/Future.cpp - qpid/client/FutureCompletion.cpp - qpid/client/FutureResult.cpp - qpid/client/LoadPlugins.cpp - qpid/client/LocalQueue.cpp - qpid/client/LocalQueueImpl.cpp - qpid/client/Message.cpp - qpid/client/MessageImpl.cpp - qpid/client/MessageListener.cpp - qpid/client/MessageReplayTracker.cpp - qpid/client/QueueOptions.cpp - qpid/client/Results.cpp - qpid/client/SessionBase_0_10.cpp - qpid/client/SessionBase_0_10Access.h - qpid/client/ConnectionAccess.h - qpid/client/SessionImpl.cpp - qpid/client/StateManager.cpp - qpid/client/Subscription.cpp - qpid/client/SubscriptionImpl.cpp - qpid/client/SubscriptionManager.cpp - qpid/client/SubscriptionManagerImpl.cpp - qpid/client/TCPConnector.cpp -) -add_msvc_version (qpidclient library dll) - -add_library (qpidclient SHARED ${qpidclient_SOURCES}) -target_link_libraries (qpidclient qpidcommon ${qpidclient_platform_LIBS}) -set_target_properties (qpidclient PROPERTIES VERSION ${qpidc_version}) -install (TARGETS qpidclient - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_CLIENT}) -install (DIRECTORY ../include/qpid - DESTINATION ${QPID_INSTALL_INCLUDEDIR} - COMPONENT ${QPID_COMPONENT_CLIENT_INCLUDE} - PATTERN ".svn" EXCLUDE) -install_pdb (qpidclient ${QPID_COMPONENT_CLIENT}) - - -set (qpidmessaging_SOURCES - ${qpidmessaging_platform_SOURCES} - qpid/messaging/Address.cpp - qpid/messaging/AddressParser.h - qpid/messaging/AddressParser.cpp - qpid/messaging/Connection.cpp - qpid/messaging/ConnectionImpl.h - qpid/messaging/Duration.cpp - qpid/messaging/exceptions.cpp - qpid/messaging/Message.cpp - qpid/messaging/MessageImpl.h - qpid/messaging/MessageImpl.cpp - qpid/messaging/Receiver.cpp - qpid/messaging/ReceiverImpl.h - qpid/messaging/Session.cpp - qpid/messaging/SessionImpl.h - qpid/messaging/Sender.cpp - qpid/messaging/SenderImpl.h - qpid/messaging/FailoverUpdates.cpp - qpid/client/amqp0_10/AcceptTracker.h - qpid/client/amqp0_10/AcceptTracker.cpp - qpid/client/amqp0_10/AddressResolution.h - qpid/client/amqp0_10/AddressResolution.cpp - qpid/client/amqp0_10/ConnectionImpl.h - qpid/client/amqp0_10/ConnectionImpl.cpp - qpid/client/amqp0_10/IncomingMessages.h - qpid/client/amqp0_10/IncomingMessages.cpp - qpid/client/amqp0_10/MessageSink.h - qpid/client/amqp0_10/MessageSource.h - qpid/client/amqp0_10/OutgoingMessage.h - qpid/client/amqp0_10/OutgoingMessage.cpp - qpid/client/amqp0_10/ReceiverImpl.h - qpid/client/amqp0_10/ReceiverImpl.cpp - qpid/client/amqp0_10/SessionImpl.h - qpid/client/amqp0_10/SessionImpl.cpp - qpid/client/amqp0_10/SenderImpl.h - qpid/client/amqp0_10/SenderImpl.cpp - qpid/client/amqp0_10/SimpleUrlParser.h - qpid/client/amqp0_10/SimpleUrlParser.cpp -) -add_msvc_version (qpidmessaging library dll) - -add_library (qpidmessaging SHARED ${qpidmessaging_SOURCES}) -target_link_libraries (qpidmessaging qpidclient) -set_target_properties (qpidmessaging PROPERTIES VERSION ${qpidc_version}) -install (TARGETS qpidmessaging - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_CLIENT}) -install_pdb (qpidmessaging ${QPID_COMPONENT_CLIENT}) - -# Released source artifacts from Apache have the generated headers included in -# the source tree, not the binary tree. So don't attempt to grab them when -# they're not supposed to be there. -if (NOT QPID_GENERATED_HEADERS_IN_SOURCE) - install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../include/qpid - DESTINATION ${QPID_INSTALL_INCLUDEDIR} - COMPONENT ${QPID_COMPONENT_CLIENT_INCLUDE}) -endif (NOT QPID_GENERATED_HEADERS_IN_SOURCE) - - -if (_MSC_VER) - # Install the DtcPlugin project and call it qpidxarm. - set(AMQP_WCF_DIR ${qpid-cpp_SOURCE_DIR}/../wcf) - set(qpidxarm_SOURCES ${AMQP_WCF_DIR}/src/Apache/Qpid/DtcPlugin/DtcPlugin.cpp) - if (EXISTS ${qpidxarm_SOURCES}) - add_msvc_version (qpidxarm library dll) - add_library (qpidxarm SHARED ${qpidxarm_SOURCES}) - target_link_libraries (qpidxarm qpidclient qpidcommon) - install (TARGETS qpidxarm - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_CLIENT}) - install_pdb (qpidxarm ${QPID_COMPONENT_CLIENT}) - endif (EXISTS ${qpidxarm_SOURCES}) -endif (_MSC_VER) - -set (qpidbroker_SOURCES - ${mgen_broker_cpp} - ${qpidbroker_platform_SOURCES} - qpid/amqp_0_10/Connection.h - qpid/amqp_0_10/Connection.cpp - qpid/broker/Broker.cpp - qpid/broker/Exchange.cpp - qpid/broker/ExpiryPolicy.cpp - qpid/broker/Fairshare.cpp - qpid/broker/LegacyLVQ.cpp - qpid/broker/MessageDeque.cpp - qpid/broker/MessageMap.cpp - qpid/broker/PriorityQueue.cpp - qpid/broker/Queue.cpp - qpid/broker/QueueCleaner.cpp - qpid/broker/QueueListeners.cpp - qpid/broker/PersistableMessage.cpp - qpid/broker/Bridge.cpp - qpid/broker/Connection.cpp - qpid/broker/ConnectionHandler.cpp - qpid/broker/ConnectionFactory.cpp - qpid/broker/DeliverableMessage.cpp - qpid/broker/DeliveryRecord.cpp - qpid/broker/DirectExchange.cpp - qpid/broker/DtxAck.cpp - qpid/broker/DtxBuffer.cpp - qpid/broker/DtxManager.cpp - qpid/broker/DtxTimeout.cpp - qpid/broker/DtxWorkRecord.cpp - qpid/broker/ExchangeRegistry.cpp - qpid/broker/FanOutExchange.cpp - qpid/broker/HeadersExchange.cpp - qpid/broker/Link.cpp - qpid/broker/LinkRegistry.cpp - qpid/broker/Message.cpp - qpid/broker/MessageAdapter.cpp - qpid/broker/MessageBuilder.cpp - qpid/broker/MessageStoreModule.cpp - qpid/broker/NameGenerator.cpp - qpid/broker/NullMessageStore.cpp - qpid/broker/QueueBindings.cpp - qpid/broker/QueueEvents.cpp - qpid/broker/QueuePolicy.cpp - qpid/broker/QueueRegistry.cpp - qpid/broker/QueueFlowLimit.cpp - qpid/broker/RateTracker.cpp - qpid/broker/RecoveryManagerImpl.cpp - qpid/broker/RecoveredEnqueue.cpp - qpid/broker/RecoveredDequeue.cpp - qpid/broker/RetryList.cpp - qpid/broker/SecureConnection.cpp - qpid/broker/SecureConnectionFactory.cpp - qpid/broker/SemanticState.h - qpid/broker/SemanticState.cpp - qpid/broker/SessionAdapter.cpp - qpid/broker/SessionState.h - qpid/broker/SessionState.cpp - qpid/broker/SessionManager.h - qpid/broker/SessionManager.cpp - qpid/broker/SessionContext.h - qpid/broker/SessionHandler.h - qpid/broker/SessionHandler.cpp - qpid/broker/System.cpp - qpid/broker/ThresholdAlerts.cpp - qpid/broker/TopicExchange.cpp - qpid/broker/TxAccept.cpp - qpid/broker/TxBuffer.cpp - qpid/broker/TxPublish.cpp - qpid/broker/Vhost.cpp - qpid/management/ManagementAgent.cpp - qpid/management/ManagementDirectExchange.cpp - qpid/management/ManagementTopicExchange.cpp - qpid/sys/TCPIOPlugin.cpp -) -add_msvc_version (qpidbroker library dll) -add_library (qpidbroker SHARED ${qpidbroker_SOURCES}) -target_link_libraries (qpidbroker qpidcommon ${qpidbroker_platform_LIBS}) -set_target_properties (qpidbroker PROPERTIES VERSION ${qpidc_version}) -if (MSVC) - set_target_properties (qpidbroker PROPERTIES COMPILE_FLAGS /wd4290) -endif (MSVC) -install (TARGETS qpidbroker - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_BROKER}) -install_pdb (qpidbroker ${QPID_COMPONENT_BROKER}) - - -set (qpidd_SOURCES - ${qpidd_platform_SOURCES} - qpidd.cpp - qpidd.h -) -add_msvc_version (qpidd application exe) -add_executable (qpidd ${qpidd_SOURCES}) -target_link_libraries (qpidd qpidbroker qpidcommon ${Boost_PROGRAM_OPTIONS_LIBRARY} - ${Boost_FILESYSTEM_LIBRARY}) -install (TARGETS qpidd RUNTIME - DESTINATION ${QPID_INSTALL_BINDIR} - COMPONENT ${QPID_COMPONENT_BROKER}) -if (CPACK_GENERATOR STREQUAL "NSIS") - set (CPACK_NSIS_MENU_LINKS - "qpidd" "Start Qpid Broker") -endif (CPACK_GENERATOR STREQUAL "NSIS") - -# QMF library -# Library Version Information (CURRENT.REVISION.AGE): -# -# CURRENT => API/ABI version. Bump this if the interface changes -# REVISION => Version of underlying implementation. -# Bump if implementation changes but API/ABI doesn't -# AGE => Number of API/ABI versions this is backward compatible with -set (qmf_version 2.0.0) -set (qmf2_version 1.0.0) -set (qmfengine_version 1.0.0) - -set (qmf_SOURCES - qpid/agent/ManagementAgentImpl.cpp - qpid/agent/ManagementAgentImpl.h - ) - -add_msvc_version (qmf library dll) -add_library (qmf SHARED ${qmf_SOURCES}) -target_link_libraries (qmf qpidclient) -set_target_properties (qmf PROPERTIES - VERSION ${qmf_version}) -install (TARGETS qmf OPTIONAL - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_QMF}) -install_pdb (qmf ${QPID_COMPONENT_QMF}) - -if(NOT WIN32) - set (qmf2_HEADERS - ../include/qmf/AgentEvent.h - ../include/qmf/Agent.h - ../include/qmf/AgentSession.h - ../include/qmf/ConsoleEvent.h - ../include/qmf/ConsoleSession.h - ../include/qmf/DataAddr.h - ../include/qmf/Data.h - ../include/qmf/exceptions.h - ../include/qmf/Handle.h - ../include/qmf/ImportExport.h - ../include/qmf/Query.h - ../include/qmf/Schema.h - ../include/qmf/SchemaId.h - ../include/qmf/SchemaMethod.h - ../include/qmf/SchemaProperty.h - ../include/qmf/SchemaTypes.h - ../include/qmf/Subscription.h - ) - - set (qmf2_SOURCES - ${qmf2_HEADERS} - qmf/agentCapability.h - qmf/Agent.cpp - qmf/AgentEvent.cpp - qmf/AgentEventImpl.h - qmf/AgentImpl.h - qmf/AgentSession.cpp - qmf/AgentSubscription.cpp - qmf/AgentSubscription.h - qmf/ConsoleEvent.cpp - qmf/ConsoleEventImpl.h - qmf/ConsoleSession.cpp - qmf/ConsoleSessionImpl.h - qmf/constants.cpp - qmf/constants.h - qmf/DataAddr.cpp - qmf/DataAddrImpl.h - qmf/Data.cpp - qmf/DataImpl.h - qmf/exceptions.cpp - qmf/Expression.cpp - qmf/Expression.h - qmf/Hash.cpp - qmf/Hash.h - qmf/PrivateImplRef.h - qmf/Query.cpp - qmf/QueryImpl.h - qmf/Schema.cpp - qmf/SchemaCache.cpp - qmf/SchemaCache.h - qmf/SchemaId.cpp - qmf/SchemaIdImpl.h - qmf/SchemaImpl.h - qmf/SchemaMethod.cpp - qmf/SchemaMethodImpl.h - qmf/SchemaProperty.cpp - qmf/SchemaPropertyImpl.h - qmf/Subscription.cpp - qmf/SubscriptionImpl.h - ) - - add_msvc_version (qmf2 library dll) - add_library (qmf2 SHARED ${qmf2_SOURCES}) - target_link_libraries (qmf2 qpidmessaging qpidtypes qpidclient qpidcommon) - set_target_properties (qmf2 PROPERTIES - VERSION ${qmf2_version}) - install (TARGETS qmf2 OPTIONAL - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_QMF}) - install (FILES ${qmf2_HEADERS} - DESTINATION ${QPID_INSTALL_INCLUDEDIR}/qmf - COMPONENT ${QPID_COMPONENT_QMF}) - install_pdb (qmf2 ${QPID_COMPONENT_QMF}) -endif (NOT WIN32) - -set (qmfengine_SOURCES - qmf/engine/Agent.cpp - qmf/engine/BrokerProxyImpl.cpp - qmf/engine/BrokerProxyImpl.h - qmf/engine/ConnectionSettingsImpl.cpp - qmf/engine/ConnectionSettingsImpl.h - qmf/engine/ConsoleImpl.cpp - qmf/engine/ConsoleImpl.h - qmf/engine/EventImpl.cpp - qmf/engine/EventImpl.h - qmf/engine/MessageImpl.cpp - qmf/engine/MessageImpl.h - qmf/engine/ObjectIdImpl.cpp - qmf/engine/ObjectIdImpl.h - qmf/engine/ObjectImpl.cpp - qmf/engine/ObjectImpl.h - qmf/engine/Protocol.cpp - qmf/engine/Protocol.h - qmf/engine/QueryImpl.cpp - qmf/engine/QueryImpl.h - qmf/engine/SequenceManager.cpp - qmf/engine/SequenceManager.h - qmf/engine/SchemaImpl.cpp - qmf/engine/SchemaImpl.h - qmf/engine/ValueImpl.cpp - qmf/engine/ValueImpl.h - ) -if (NOT WIN32) - list(APPEND qmfengine_SOURCES qmf/engine/ResilientConnection.cpp) -endif (NOT WIN32) -add_msvc_version (qmfengine library dll) - -add_library (qmfengine SHARED ${qmfengine_SOURCES}) -target_link_libraries (qmfengine qpidclient) -set_target_properties (qmfengine PROPERTIES - VERSION ${qmfengine_version}) -install (TARGETS qmfengine OPTIONAL - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_QMF}) -install_pdb (qmfengine ${QPID_COMPONENT_QMF}) - -# QMF console library -#module_hdr += \ -# qpid/console/Agent.h \ -# qpid/console/Broker.h \ -# qpid/console/ClassKey.h \ -# qpid/console/ConsoleImportExport.h \ -# qpid/console/ConsoleListener.h \ -# qpid/console/Event.h \ -# qpid/console/Object.h \ -# qpid/console/ObjectId.h \ -# qpid/console/Package.h \ -# qpid/console/Schema.h \ -# qpid/console/SequenceManager.h \ -# qpid/console/SessionManager.h \ -# qpid/console/Value.h -set (qmfconsole_SOURCES - ../include/qpid/console/Agent.h - ../include/qpid/console/Broker.h - ../include/qpid/console/ClassKey.h - ../include/qpid/console/ConsoleImportExport.h - ../include/qpid/console/ConsoleListener.h - ../include/qpid/console/Event.h - ../include/qpid/console/Object.h - ../include/qpid/console/ObjectId.h - ../include/qpid/console/Package.h - ../include/qpid/console/Schema.h - ../include/qpid/console/SequenceManager.h - ../include/qpid/console/SessionManager.h - ../include/qpid/console/Value.h - qpid/console/Agent.cpp - qpid/console/Broker.cpp - qpid/console/ClassKey.cpp - qpid/console/Event.cpp - qpid/console/Object.cpp - qpid/console/ObjectId.cpp - qpid/console/Package.cpp - qpid/console/Schema.cpp - qpid/console/SequenceManager.cpp - qpid/console/SessionManager.cpp - qpid/console/Value.cpp - ) -add_msvc_version (qmfconsole library dll) -add_library (qmfconsole SHARED ${qmfconsole_SOURCES}) -target_link_libraries (qmfconsole qpidclient) -set_target_properties (qmfconsole PROPERTIES - VERSION ${qpidc_version}) -install (TARGETS qmfconsole - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_QMF}) -install_pdb (qmfconsole ${QPID_COMPONENT_QMF}) - -# A queue event listener plugin that creates messages on a replication -# queue corresponding to enqueue and dequeue events: -set (replicating_listener_SOURCES - qpid/replication/constants.h - qpid/replication/ReplicatingEventListener.cpp - qpid/replication/ReplicatingEventListener.h - ) -add_msvc_version (replicating_listener library dll) -add_library (replicating_listener MODULE ${replicating_listener_SOURCES}) -target_link_libraries (replicating_listener qpidbroker ${Boost_PROGRAM_OPTIONS_LIBRARY}) -set_target_properties (replicating_listener PROPERTIES PREFIX "") -if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(replicating_listener PROPERTIES - LINK_FLAGS -Wl,--no-undefined) -endif (CMAKE_COMPILER_IS_GNUCXX) -install (TARGETS replicating_listener - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - -# A custom exchange plugin that allows an exchange to be created that -# can process the messages from a replication queue (populated on the -# source system by the replicating listener plugin above) and take the -# corresponding action on the local queues -set (replication_exchange_SOURCES - qpid/replication/constants.h - qpid/replication/ReplicationExchange.cpp - qpid/replication/ReplicationExchange.h - ) -add_msvc_version (replication_exchange library dll) -add_library (replication_exchange MODULE ${replication_exchange_SOURCES}) -target_link_libraries (replication_exchange qpidbroker) -set_target_properties (replication_exchange PROPERTIES PREFIX "") -if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(replication_exchange PROPERTIES - LINK_FLAGS -Wl,--no-undefined) -endif (CMAKE_COMPILER_IS_GNUCXX) -install (TARGETS replication_exchange - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - -# This is only really needed until all the trunk builds (Linux, UNIX, Windows) -# are all on cmake only. This is because cmake builds always have a config.h -# file whereas older builds only have config.h on autoconf-generated builds. -add_definitions(-DHAVE_CONFIG_H) - -add_definitions(-DBOOST_FILESYSTEM_VERSION=2) - -# Now create the config file from all the info learned above. -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/config.h) -add_subdirectory(qpid/store) -add_subdirectory(tests) diff --git a/cpp/src/CMakeWinVersions.cmake b/cpp/src/CMakeWinVersions.cmake deleted file mode 100644 index 0bac7cab47..0000000000 --- a/cpp/src/CMakeWinVersions.cmake +++ /dev/null @@ -1,57 +0,0 @@ -#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-#
-# Versions settings overrides for Windows dll/exe file version resource.
-# These values are compiled into the dll and exe files.
-#
-# The settings override precedence from lowest to highest:
-# 1. CPACK settings from cpp/CMakeLists.txt
-# 2. Global settings from this file
-# 3. Command line version number (only) from add_msvc_version_full call
-# 4. Per-project settings from this file
-#
-
-#
-# Specification of global settings for all projects.
-#
-# set ("winver_PACKAGE_NAME" "qpid-cpp")
-# set ("winver_DESCRIPTION_SUMMARY" "Apache Qpid C++")
-# set ("winver_FILE_VERSION_N1" "0")
-# set ("winver_FILE_VERSION_N2" "11")
-# set ("winver_FILE_VERSION_N3" "0")
-# set ("winver_FILE_VERSION_N4" "0")
-# set ("winver_PRODUCT_VERSION_N1" "0")
-# set ("winver_PRODUCT_VERSION_N2" "11")
-# set ("winver_PRODUCT_VERSION_N3" "0")
-# set ("winver_PRODUCT_VERSION_N4" "0")
-# set ("winver_LEGAL_COPYRIGHT" "")
-
-#
-# Specification of per-project settings:
-#
-# set ("winver_${projectName}_FileVersionBinary" "0,11,0,0")
-# set ("winver_${projectName}_ProductVersionBinary" "0,11,0,0")
-# set ("winver_${projectName}_FileVersionString" "0, 11, 0, 0")
-# set ("winver_${projectName}_ProductVersionString" "0, 11, 0, 0")
-# set ("winver_${projectName}_FileDescription" "qpid-cpp-qpidcommon Library")
-# set ("winver_${projectName}_LegalCopyright" "")
-# set ("winver_${projectName}_InternalName" "qpidcommon")
-# set ("winver_${projectName}_OriginalFilename" "qpidcommon.dll")
-# set ("winver_${projectName}_ProductName" "Apache Qpid C++")
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am deleted file mode 100644 index 15021cc68b..0000000000 --- a/cpp/src/Makefile.am +++ /dev/null @@ -1,896 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -SUBDIRS = . tests - -# The Windows-only sources are not compiled using this Makefile, but -# are listed here to ensure they're included in releases. They are built -# using Visual Studio solutions/projects. -windows_dist = \ - qpid/client/windows/SaslFactory.cpp \ - qpid/client/windows/SslConnector.cpp \ - qpid/log/windows/SinkOptions.cpp \ - qpid/log/windows/SinkOptions.h \ - ../include/qpid/sys/windows/check.h \ - qpid/sys/windows/AsynchIO.cpp \ - qpid/sys/windows/AsynchIoResult.h \ - ../include/qpid/sys/windows/Condition.h \ - qpid/sys/windows/FileSysDir.cpp \ - ../include/qpid/sys/windows/IntegerTypes.h \ - qpid/sys/windows/IocpPoller.cpp \ - qpid/sys/windows/IOHandle.cpp \ - qpid/sys/windows/IoHandlePrivate.h \ - qpid/sys/windows/LockFile.cpp \ - qpid/sys/windows/PollableCondition.cpp \ - qpid/sys/windows/PipeHandle.cpp \ - ../include/qpid/sys/windows/Mutex.h \ - qpid/sys/windows/Shlib.cpp \ - qpid/sys/windows/SocketAddress.cpp \ - qpid/sys/windows/Socket.cpp \ - qpid/sys/windows/SslAsynchIO.cpp \ - qpid/sys/windows/SslAsynchIO.h \ - qpid/sys/windows/StrError.cpp \ - qpid/sys/windows/SystemInfo.cpp \ - qpid/sys/windows/Thread.cpp \ - qpid/sys/windows/Time.cpp \ - ../include/qpid/sys/windows/Time.h \ - qpid/sys/windows/uuid.cpp \ - qpid/sys/windows/uuid.h \ - windows/QpiddBroker.cpp \ - qpid/broker/windows/BrokerDefaults.cpp \ - qpid/broker/windows/SaslAuthenticator.cpp \ - qpid/broker/windows/SslProtocolFactory.cpp \ - qpid/messaging/HandleInstantiator.cpp \ - windows/resources/template-resource.rc \ - windows/resources/version-resource.h \ - windows/resources/qpid-icon.ico - -EXTRA_DIST= $(platform_dist) $(rgen_srcs) $(windows_dist) - -# Define variables that are be appended to by this file and included .mk files. -nobase_include_HEADERS = -libqpidcommon_la_SOURCES = - -## Generated code - -# Note: generated soure and makefiles included in distribution so a -# distribution can be built without code generation tools and XML -# sources. - -# This phony target is needed by generated makefile fragments: -force: - -if GENERATE - -# AMQP_FINAL_XML is defined in ../configure.ac -amqp_0_10_xml=@AMQP_FINAL_XML@ -specs=$(amqp_0_10_xml) $(top_srcdir)/xml/cluster.xml - -# Ruby generator. -rgen_dir=$(top_srcdir)/rubygen -rgen_cmd=ruby -I $(rgen_dir) $(rgen_dir)/generate . ../include $(specs) all - -$(rgen_srcs) $(srcdir)/rubygen.mk: rgen.timestamp -rgen.timestamp: $(rgen_generator) $(specs) - $(rgen_cmd) $(srcdir)/rubygen.mk; touch $@ -$(rgen_generator): - -# The CMake version is needed for dist -$(srcdir)/rubygen.cmake: $(rgen_generator) $(specs) - $(rgen_cmd) $(srcdir)/rubygen.cmake - -# Management generator. -mgen_dir=$(top_srcdir)/managementgen -mgen_cmd=$(mgen_dir)/qmf-gen -m $(srcdir)/managementgen.mk \ - -c $(srcdir)/managementgen.cmake -q -b -o qmf \ - $(top_srcdir)/../specs/management-schema.xml \ - $(srcdir)/qpid/acl/management-schema.xml \ - $(srcdir)/qpid/cluster/management-schema.xml - -$(srcdir)/managementgen.mk $(mgen_broker_cpp) $(dist_qpid_management_HEADERS): mgen.timestamp -mgen.timestamp: $(mgen_generator) - $(mgen_cmd); touch $@ -$(mgen_generator): - -endif # GENERATE - -include $(srcdir)/rubygen.mk -include $(srcdir)/managementgen.mk - -## Compiler flags -AM_CXXFLAGS = $(WARNING_CFLAGS) -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(srcdir) -I=$(builddir) - -# -# Destination for intalled programs and tests defined here -# -qpidexecdir = $(libexecdir)/qpid -AM_CXXFLAGS += -DQPID_LIBEXEC_DIR=\"$(qpidexecdir)\" -qpidexec_PROGRAMS = -qpidexec_SCRIPTS = -qpidtestdir = $(qpidexecdir)/tests -qpidtest_PROGRAMS = -qpidtest_SCRIPTS = -tmoduleexecdir = $(libdir)/qpid/tests -tmoduleexec_LTLIBRARIES= - -AM_CXXFLAGS += -DBOOST_FILESYSTEM_VERSION=2 - -## Automake macros to build libraries and executables. -qpidd_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDD_MODULE_DIR=\"$(dmoduleexecdir)\" -DQPIDD_CONF_FILE=\"$(sysconfdir)/qpidd.conf\" -libqpidclient_la_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDC_MODULE_DIR=\"$(cmoduleexecdir)\" -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.conf\" - -qpidd_LDADD = \ - libqpidbroker.la \ - libqpidcommon.la - -posix_qpidd_src = posix/QpiddBroker.cpp - -sbin_PROGRAMS = qpidd -qpidd_SOURCES = qpidd.cpp qpidd.h $(posix_qpidd_src) - -## Platform specific code. - -# Posix-specific code -libqpidcommon_la_SOURCES += \ - qpid/log/posix/SinkOptions.cpp \ - qpid/sys/posix/IOHandle.cpp \ - qpid/sys/posix/Socket.cpp \ - qpid/sys/posix/SocketAddress.cpp \ - qpid/sys/posix/AsynchIO.cpp \ - qpid/sys/posix/FileSysDir.cpp \ - qpid/sys/posix/LockFile.cpp \ - qpid/sys/posix/Time.cpp \ - qpid/sys/posix/Thread.cpp \ - qpid/sys/posix/Shlib.cpp \ - qpid/sys/posix/Mutex.cpp \ - qpid/sys/posix/Fork.cpp \ - qpid/sys/posix/StrError.cpp \ - qpid/sys/posix/PollableCondition.cpp \ - qpid/sys/posix/PidFile.h \ - qpid/sys/posix/PipeHandle.cpp \ - qpid/log/posix/SinkOptions.h \ - qpid/sys/posix/Fork.h - -nobase_include_HEADERS += \ - ../include/qpid/sys/posix/Condition.h \ - ../include/qpid/sys/posix/IntegerTypes.h \ - ../include/qpid/sys/posix/Mutex.h \ - ../include/qpid/sys/posix/PrivatePosix.h \ - ../include/qpid/sys/posix/Time.h \ - ../include/qpid/sys/posix/check.h - -if HAVE_EPOLL - poller = qpid/sys/epoll/EpollPoller.cpp -endif - -if HAVE_ECF - poller = qpid/sys/solaris/ECFPoller.cpp -endif - -if SUNOS - systeminfo = qpid/sys/solaris/SystemInfo.cpp -else - systeminfo = qpid/sys/posix/SystemInfo.cpp -endif - -libqpidcommon_la_SOURCES += $(poller) $(systeminfo) - -posix_broker_src = \ - qpid/broker/posix/BrokerDefaults.cpp - -lib_LTLIBRARIES = libqpidtypes.la libqpidcommon.la libqpidbroker.la libqpidclient.la libqpidmessaging.la - -# Definitions for client and daemon plugins -PLUGINLDFLAGS=-no-undefined -module -avoid-version -confdir=$(sysconfdir)/qpid -dmoduleexecdir=$(libdir)/qpid/daemon -cmoduleexecdir=$(libdir)/qpid/client -dmoduleexec_LTLIBRARIES = -cmoduleexec_LTLIBRARIES = - -include cluster.mk -include acl.mk -include qmf.mk -include qmfc.mk -if HAVE_XML -include xml.mk -endif -include replication.mk - -if RDMA - -# RDMA (Infiniband) protocol code -librdmawrap_la_SOURCES = \ - qpid/sys/rdma/rdma_exception.h \ - qpid/sys/rdma/rdma_factories.cpp \ - qpid/sys/rdma/rdma_factories.h \ - qpid/sys/rdma/RdmaIO.cpp \ - qpid/sys/rdma/RdmaIO.h \ - qpid/sys/rdma/rdma_wrap.cpp \ - qpid/sys/rdma/rdma_wrap.h -librdmawrap_la_LIBADD = \ - libqpidcommon.la \ - -lrdmacm \ - -libverbs -librdmawrap_la_CXXFLAGS = \ - $(AM_CXXFLAGS) -Wno-missing-field-initializers -lib_LTLIBRARIES += \ - librdmawrap.la -RDMAWRAP_VERSION_INFO = 2:0:0 -librdmawrap_la_LDFLAGS = -version-info $(RDMAWRAP_VERSION_INFO) -no-undefined - -rdma_la_SOURCES = \ - qpid/sys/RdmaIOPlugin.cpp -rdma_la_LIBADD = \ - libqpidbroker.la \ - librdmawrap.la \ - -libverbs -rdma_la_LDFLAGS = $(PLUGINLDFLAGS) -rdma_la_CXXFLAGS = \ - $(AM_CXXFLAGS) -Wno-missing-field-initializers -dmoduleexec_LTLIBRARIES += \ - rdma.la - -rdmaconnector_la_SOURCES = \ - qpid/client/RdmaConnector.cpp -rdmaconnector_la_LIBADD = \ - libqpidclient.la \ - librdmawrap.la \ - -libverbs -rdmaconnector_la_LDFLAGS = $(PLUGINLDFLAGS) -rdmaconnector_la_CXXFLAGS = \ - $(AM_CXXFLAGS) -Wno-missing-field-initializers -cmoduleexec_LTLIBRARIES += \ - rdmaconnector.la - -# RDMA test/sample programs -noinst_PROGRAMS = RdmaServer RdmaClient -RdmaServer_SOURCES = qpid/sys/rdma/RdmaServer.cpp -RdmaServer_LDADD = \ - librdmawrap.la libqpidcommon.la -RdmaClient_SOURCES = qpid/sys/rdma/RdmaClient.cpp -RdmaClient_CXXFLAGS = \ - $(AM_CXXFLAGS) -Wno-missing-field-initializers -RdmaClient_LDADD = \ - librdmawrap.la libqpidcommon.la - -endif - -if SSL -include ssl.mk -endif - -EXTRA_DIST +=\ - CMakeLists.txt \ - cluster.cmake \ - config.h.cmake \ - rdma.cmake \ - ssl.cmake \ - managementgen.cmake \ - rubygen.cmake \ - $(rgen_amqp_0_10_srcs) \ - qpid/amqp_0_10/apply.h \ - qpid/amqp_0_10/built_in_types.h \ - qpid/amqp_0_10/complex_types.cpp \ - qpid/amqp_0_10/Array.h \ - qpid/amqp_0_10/Array.cpp \ - qpid/amqp_0_10/Body.h \ - qpid/amqp_0_10/Command.h \ - qpid/amqp_0_10/CommmandPacker.h \ - qpid/amqp_0_10/Control.h \ - qpid/amqp_0_10/Header.h \ - qpid/amqp_0_10/Header.cpp \ - qpid/amqp_0_10/FrameHeader.h \ - qpid/amqp_0_10/FrameHeader.cpp \ - qpid/amqp_0_10/Holder.h \ - qpid/amqp_0_10/Codec.h \ - qpid/amqp_0_10/Packer.h \ - qpid/amqp_0_10/Decimal.h \ - qpid/amqp_0_10/SerializableString.h \ - qpid/amqp_0_10/Map.h \ - qpid/amqp_0_10/Map.cpp \ - qpid/amqp_0_10/Struct.h \ - qpid/amqp_0_10/Struct32.h \ - qpid/amqp_0_10/Struct32.cpp \ - qpid/amqp_0_10/Unit.h \ - qpid/amqp_0_10/Unit.cpp \ - qpid/amqp_0_10/UnitHandler.h \ - qpid/amqp_0_10/UnknownType.h \ - qpid/amqp_0_10/UnknownType.cpp \ - qpid/amqp_0_10/UnknownStruct.h \ - qpid/amqp_0_10/UnknownStruct.cpp \ - qpid/store - -libqpidcommon_la_LIBADD = \ - libqpidtypes.la \ - -lboost_program_options \ - -lboost_filesystem \ - -luuid \ - $(LIB_DLOPEN) \ - $(LIB_CLOCK_GETTIME) - -libqpidcommon_la_SOURCES += \ - $(rgen_framing_srcs) \ - $(platform_src) \ - qpid/Address.cpp \ - qpid/DataDir.cpp \ - qpid/DataDir.h \ - qpid/DisableExceptionLogging.h \ - qpid/Exception.cpp \ - qpid/Modules.cpp \ - qpid/Modules.h \ - qpid/Options.cpp \ - qpid/Plugin.cpp \ - qpid/Plugin.h \ - qpid/RefCounted.h \ - qpid/RefCountedBuffer.cpp \ - qpid/RefCountedBuffer.h \ - qpid/BufferRef.h \ - qpid/Sasl.h \ - qpid/SaslFactory.cpp \ - qpid/SaslFactory.h \ - qpid/Serializer.h \ - qpid/SessionId.cpp \ - qpid/SessionState.cpp \ - qpid/SessionState.h \ - qpid/SessionState.h \ - qpid/SharedObject.h \ - qpid/StringUtils.cpp \ - qpid/StringUtils.h \ - qpid/Url.cpp \ - qpid/Version.h \ - qpid/amqp_0_10/Exception.h \ - qpid/amqp_0_10/SessionHandler.cpp \ - qpid/amqp_0_10/SessionHandler.h \ - qpid/amqp_0_10/apply.h \ - qpid/assert.cpp qpid/assert.h \ - qpid/assert.h \ - qpid/framing/AMQBody.cpp \ - qpid/framing/AMQBody.h \ - qpid/framing/AMQCommandControlBody.h \ - qpid/framing/AMQContentBody.cpp \ - qpid/framing/AMQContentBody.h \ - qpid/framing/AMQDataBlock.h \ - qpid/framing/AMQFrame.cpp \ - qpid/framing/AMQFrame.h \ - qpid/framing/AMQHeaderBody.cpp \ - qpid/framing/AMQHeaderBody.h \ - qpid/framing/AMQHeartbeatBody.cpp \ - qpid/framing/AMQHeartbeatBody.h \ - qpid/framing/AMQMethodBody.cpp \ - qpid/framing/AMQMethodBody.h \ - qpid/framing/AMQP_HighestVersion.h \ - qpid/framing/AMQP_HighestVersion.h \ - qpid/framing/AccumulatedAck.cpp \ - qpid/framing/AccumulatedAck.h \ - qpid/framing/Array.cpp \ - qpid/framing/BodyFactory.h \ - qpid/framing/BodyHandler.cpp \ - qpid/framing/BodyHandler.h \ - qpid/framing/Buffer.cpp \ - qpid/framing/ResizableBuffer.h \ - qpid/framing/ChannelHandler.h \ - qpid/framing/Endian.cpp \ - qpid/framing/Endian.h \ - qpid/framing/FieldTable.cpp \ - qpid/framing/FieldValue.cpp \ - qpid/framing/FrameDecoder.cpp \ - qpid/framing/FrameDecoder.h \ - qpid/framing/FrameDefaultVisitor.h \ - qpid/framing/FrameHandler.h \ - qpid/framing/FrameSet.cpp \ - qpid/framing/FrameSet.h \ - qpid/framing/Handler.h \ - qpid/framing/HeaderProperties.h \ - qpid/framing/InitiationHandler.h \ - qpid/framing/InputHandler.h \ - qpid/framing/Invoker.h \ - qpid/framing/IsInSequenceSet.h \ - qpid/framing/List.cpp \ - qpid/framing/MethodBodyFactory.h \ - qpid/framing/MethodContent.h \ - qpid/framing/ModelMethod.h \ - qpid/framing/OutputHandler.h \ - qpid/framing/ProtocolInitiation.cpp \ - qpid/framing/ProtocolInitiation.h \ - qpid/framing/ProtocolVersion.cpp \ - qpid/framing/Proxy.cpp \ - qpid/framing/Proxy.h \ - qpid/framing/SendContent.cpp \ - qpid/framing/SendContent.h \ - qpid/framing/SequenceNumber.cpp \ - qpid/framing/SequenceNumberSet.cpp \ - qpid/framing/SequenceNumberSet.h \ - qpid/framing/SequenceSet.cpp \ - qpid/framing/TransferContent.cpp \ - qpid/framing/TransferContent.h \ - qpid/framing/TypeFilter.h \ - qpid/framing/Uuid.cpp \ - qpid/framing/Visitor.h \ - qpid/framing/amqp_framing.h \ - qpid/framing/frame_functors.h \ - qpid/framing/variant.h \ - qpid/log/Helpers.h \ - qpid/log/Logger.cpp \ - qpid/log/Options.cpp \ - qpid/log/OstreamOutput.cpp \ - qpid/log/OstreamOutput.h \ - qpid/log/Selector.cpp \ - qpid/log/Statement.cpp \ - qpid/management/Buffer.cpp \ - qpid/management/ConnectionSettings.cpp \ - qpid/management/Manageable.cpp \ - qpid/management/ManagementObject.cpp \ - qpid/management/Mutex.cpp \ - qpid/memory.h \ - qpid/pointer_to_other.h \ - qpid/ptr_map.h \ - qpid/sys/AggregateOutput.cpp \ - qpid/sys/AggregateOutput.h \ - qpid/sys/AsynchIO.h \ - qpid/sys/AsynchIOHandler.cpp \ - qpid/sys/AsynchIOHandler.h \ - qpid/sys/AtomicCount.h \ - qpid/sys/AtomicValue.h \ - qpid/sys/AtomicValue_gcc.h \ - qpid/sys/AtomicValue_mutex.h \ - qpid/sys/BlockingQueue.h \ - qpid/sys/ClusterSafe.h \ - qpid/sys/ClusterSafe.cpp \ - qpid/sys/Codec.h \ - qpid/sys/ConnectionCodec.h \ - qpid/sys/ConnectionInputHandler.h \ - qpid/sys/ConnectionInputHandlerFactory.h \ - qpid/sys/ConnectionOutputHandler.h \ - qpid/sys/ConnectionOutputHandlerPtr.h \ - qpid/sys/CopyOnWriteArray.h \ - qpid/sys/DeletionManager.h \ - qpid/sys/DispatchHandle.cpp \ - qpid/sys/DispatchHandle.h \ - qpid/sys/Dispatcher.cpp \ - qpid/sys/Dispatcher.h \ - qpid/sys/FileSysDir.h \ - qpid/sys/Fork.h \ - qpid/sys/LockFile.h \ - qpid/sys/LockPtr.h \ - qpid/sys/OutputControl.h \ - qpid/sys/OutputTask.h \ - qpid/sys/PipeHandle.h \ - qpid/sys/PollableCondition.h \ - qpid/sys/PollableQueue.h \ - qpid/sys/Poller.h \ - qpid/sys/ProtocolFactory.h \ - qpid/sys/Runnable.cpp \ - qpid/sys/ScopedIncrement.h \ - qpid/sys/SecurityLayer.h \ - qpid/sys/SecuritySettings.h \ - qpid/sys/Semaphore.h \ - qpid/sys/Shlib.cpp \ - qpid/sys/Shlib.h \ - qpid/sys/ShutdownHandler.h \ - qpid/sys/Socket.h \ - qpid/sys/SocketAddress.h \ - qpid/sys/StateMonitor.h \ - qpid/sys/TimeoutHandler.h \ - qpid/sys/Timer.cpp \ - qpid/sys/Timer.h \ - qpid/sys/TimerWarnings.cpp \ - qpid/sys/TimerWarnings.h \ - qpid/sys/Waitable.h \ - qpid/sys/alloca.h \ - qpid/sys/uuid.h \ - qpid/amqp_0_10/Codecs.cpp - -if HAVE_SASL -libqpidcommon_la_SOURCES += qpid/sys/cyrus/CyrusSecurityLayer.h -libqpidcommon_la_SOURCES += qpid/sys/cyrus/CyrusSecurityLayer.cpp -libqpidcommon_la_LIBADD += -lsasl2 -endif - -QPIDCOMMON_VERSION_INFO = 2:0:0 -libqpidcommon_la_LDFLAGS=-version-info $(QPIDCOMMON_VERSION_INFO) - -libqpidbroker_la_LIBADD = libqpidcommon.la -libqpidbroker_la_SOURCES = \ - $(mgen_broker_cpp) \ - $(posix_broker_src) \ - qpid/amqp_0_10/Connection.cpp \ - qpid/amqp_0_10/Connection.h \ - qpid/broker/AclModule.h \ - qpid/broker/Bridge.cpp \ - qpid/broker/Bridge.h \ - qpid/broker/Broker.cpp \ - qpid/broker/Broker.h \ - qpid/broker/BrokerImportExport.h \ - qpid/broker/Connection.cpp \ - qpid/broker/Connection.h \ - qpid/broker/ConnectionFactory.cpp \ - qpid/broker/ConnectionFactory.h \ - qpid/broker/ConnectionHandler.cpp \ - qpid/broker/ConnectionHandler.h \ - qpid/broker/ConnectionState.h \ - qpid/broker/ConnectionToken.h \ - qpid/broker/Consumer.h \ - qpid/broker/Daemon.cpp \ - qpid/broker/Daemon.h \ - qpid/broker/Deliverable.h \ - qpid/broker/DeliverableMessage.cpp \ - qpid/broker/DeliverableMessage.h \ - qpid/broker/DeliveryAdapter.h \ - qpid/broker/DeliveryId.h \ - qpid/broker/DeliveryRecord.cpp \ - qpid/broker/DeliveryRecord.h \ - qpid/broker/DirectExchange.cpp \ - qpid/broker/DirectExchange.h \ - qpid/broker/DtxAck.cpp \ - qpid/broker/DtxAck.h \ - qpid/broker/DtxBuffer.cpp \ - qpid/broker/DtxBuffer.h \ - qpid/broker/DtxManager.cpp \ - qpid/broker/DtxManager.h \ - qpid/broker/DtxTimeout.cpp \ - qpid/broker/DtxTimeout.h \ - qpid/broker/DtxWorkRecord.cpp \ - qpid/broker/DtxWorkRecord.h \ - qpid/broker/Exchange.cpp \ - qpid/broker/Exchange.h \ - qpid/broker/ExchangeRegistry.cpp \ - qpid/broker/ExchangeRegistry.h \ - qpid/broker/ExpiryPolicy.cpp \ - qpid/broker/ExpiryPolicy.h \ - qpid/broker/Fairshare.h \ - qpid/broker/Fairshare.cpp \ - qpid/broker/FanOutExchange.cpp \ - qpid/broker/FanOutExchange.h \ - qpid/broker/FedOps.h \ - qpid/broker/HandlerImpl.h \ - qpid/broker/HeadersExchange.cpp \ - qpid/broker/HeadersExchange.h \ - qpid/broker/AsyncCompletion.h \ - qpid/broker/LegacyLVQ.h \ - qpid/broker/LegacyLVQ.cpp \ - qpid/broker/Link.cpp \ - qpid/broker/Link.h \ - qpid/broker/LinkRegistry.cpp \ - qpid/broker/LinkRegistry.h \ - qpid/broker/Message.cpp \ - qpid/broker/Message.h \ - qpid/broker/MessageAdapter.cpp \ - qpid/broker/MessageAdapter.h \ - qpid/broker/MessageBuilder.cpp \ - qpid/broker/MessageBuilder.h \ - qpid/broker/MessageDeque.h \ - qpid/broker/MessageDeque.cpp \ - qpid/broker/MessageMap.h \ - qpid/broker/MessageMap.cpp \ - qpid/broker/Messages.h \ - qpid/broker/MessageStore.h \ - qpid/broker/MessageStoreModule.cpp \ - qpid/broker/MessageStoreModule.h \ - qpid/broker/PriorityQueue.h \ - qpid/broker/PriorityQueue.cpp \ - qpid/broker/NameGenerator.cpp \ - qpid/broker/NameGenerator.h \ - qpid/broker/NullMessageStore.cpp \ - qpid/broker/NullMessageStore.h \ - qpid/broker/OwnershipToken.h \ - qpid/broker/Persistable.h \ - qpid/broker/PersistableConfig.h \ - qpid/broker/PersistableExchange.h \ - qpid/broker/PersistableMessage.cpp \ - qpid/broker/PersistableMessage.h \ - qpid/broker/PersistableQueue.h \ - qpid/broker/Queue.cpp \ - qpid/broker/Queue.h \ - qpid/broker/QueueBindings.cpp \ - qpid/broker/QueueBindings.h \ - qpid/broker/QueueCleaner.cpp \ - qpid/broker/QueueCleaner.h \ - qpid/broker/QueueEvents.cpp \ - qpid/broker/QueueEvents.h \ - qpid/broker/QueueListeners.cpp \ - qpid/broker/QueueListeners.h \ - qpid/broker/QueueObserver.h \ - qpid/broker/QueuePolicy.cpp \ - qpid/broker/QueuePolicy.h \ - qpid/broker/QueueRegistry.cpp \ - qpid/broker/QueueRegistry.h \ - qpid/broker/QueuedMessage.h \ - qpid/broker/QueueFlowLimit.h \ - qpid/broker/QueueFlowLimit.cpp \ - qpid/broker/RateFlowcontrol.h \ - qpid/broker/RateTracker.cpp \ - qpid/broker/RateTracker.h \ - qpid/broker/RecoverableConfig.h \ - qpid/broker/RecoverableExchange.h \ - qpid/broker/RecoverableMessage.h \ - qpid/broker/RecoverableQueue.h \ - qpid/broker/RecoverableTransaction.h \ - qpid/broker/RecoveredDequeue.cpp \ - qpid/broker/RecoveredDequeue.h \ - qpid/broker/RecoveredEnqueue.cpp \ - qpid/broker/RecoveredEnqueue.h \ - qpid/broker/RecoveryManager.h \ - qpid/broker/RecoveryManagerImpl.cpp \ - qpid/broker/RecoveryManagerImpl.h \ - qpid/broker/RetryList.cpp \ - qpid/broker/RetryList.h \ - qpid/broker/SaslAuthenticator.cpp \ - qpid/broker/SaslAuthenticator.h \ - qpid/broker/SecureConnection.cpp \ - qpid/broker/SecureConnection.h \ - qpid/broker/SecureConnectionFactory.cpp \ - qpid/broker/SecureConnectionFactory.h \ - qpid/broker/SemanticState.cpp \ - qpid/broker/SemanticState.h \ - qpid/broker/SessionAdapter.cpp \ - qpid/broker/SessionAdapter.h \ - qpid/broker/SessionAdapter.h \ - qpid/broker/SessionContext.h \ - qpid/broker/SessionHandler.cpp \ - qpid/broker/SessionHandler.h \ - qpid/broker/SessionManager.cpp \ - qpid/broker/SessionManager.h \ - qpid/broker/SessionManager.h \ - qpid/broker/SessionOutputException.h \ - qpid/broker/SessionState.cpp \ - qpid/broker/SessionState.h \ - qpid/broker/SignalHandler.cpp \ - qpid/broker/SignalHandler.h \ - qpid/broker/System.cpp \ - qpid/broker/System.h \ - qpid/broker/ThresholdAlerts.cpp \ - qpid/broker/ThresholdAlerts.h \ - qpid/broker/TopicExchange.cpp \ - qpid/broker/TopicExchange.h \ - qpid/broker/TransactionalStore.h \ - qpid/broker/TxAccept.cpp \ - qpid/broker/TxAccept.h \ - qpid/broker/TxBuffer.cpp \ - qpid/broker/TxBuffer.h \ - qpid/broker/TxOp.h \ - qpid/broker/TxOpVisitor.h \ - qpid/broker/TxPublish.cpp \ - qpid/broker/TxPublish.h \ - qpid/broker/Vhost.cpp \ - qpid/broker/Vhost.h \ - qpid/management/ManagementAgent.cpp \ - qpid/management/ManagementAgent.h \ - qpid/management/ManagementDirectExchange.cpp \ - qpid/management/ManagementDirectExchange.h \ - qpid/management/ManagementTopicExchange.cpp \ - qpid/management/ManagementTopicExchange.h \ - qpid/sys/TCPIOPlugin.cpp - -QPIDBROKER_VERSION_INFO = 2:0:0 -libqpidbroker_la_LDFLAGS = -version-info $(QPIDBROKER_VERSION_INFO) - -libqpidclient_la_LIBADD = libqpidcommon.la -luuid - -libqpidclient_la_SOURCES = \ - $(rgen_client_srcs) \ - qpid/client/Bounds.cpp \ - qpid/client/Bounds.h \ - qpid/client/ChainableFrameHandler.h \ - qpid/client/Completion.cpp \ - qpid/client/CompletionImpl.h \ - qpid/client/Connection.cpp \ - qpid/client/ConnectionAccess.h \ - qpid/client/ConnectionHandler.cpp \ - qpid/client/ConnectionHandler.h \ - qpid/client/ConnectionImpl.cpp \ - qpid/client/ConnectionImpl.h \ - qpid/client/ConnectionSettings.cpp \ - qpid/client/Connector.cpp \ - qpid/client/Connector.h \ - qpid/client/Demux.cpp \ - qpid/client/Demux.h \ - qpid/client/Dispatcher.cpp \ - qpid/client/Dispatcher.h \ - qpid/client/Execution.h \ - qpid/client/FailoverListener.cpp \ - qpid/client/FailoverManager.cpp \ - qpid/client/Future.cpp \ - qpid/client/FutureCompletion.cpp \ - qpid/client/FutureResult.cpp \ - qpid/client/LoadPlugins.h \ - qpid/client/LoadPlugins.cpp \ - qpid/client/LocalQueue.cpp \ - qpid/client/LocalQueueImpl.cpp \ - qpid/client/LocalQueueImpl.h \ - qpid/client/Message.cpp \ - qpid/client/MessageImpl.cpp \ - qpid/client/MessageImpl.h \ - qpid/client/MessageListener.cpp \ - qpid/client/MessageReplayTracker.cpp \ - qpid/client/PrivateImplRef.h \ - qpid/client/QueueOptions.cpp \ - qpid/client/Results.cpp \ - qpid/client/Results.h \ - qpid/client/SessionBase_0_10.cpp \ - qpid/client/SessionBase_0_10Access.h \ - qpid/client/SessionImpl.cpp \ - qpid/client/SessionImpl.h \ - qpid/client/StateManager.cpp \ - qpid/client/StateManager.h \ - qpid/client/Subscription.cpp \ - qpid/client/SubscriptionImpl.cpp \ - qpid/client/SubscriptionImpl.h \ - qpid/client/SubscriptionManager.cpp \ - qpid/client/SubscriptionManagerImpl.cpp \ - qpid/client/SubscriptionManagerImpl.h \ - qpid/client/TCPConnector.cpp \ - qpid/client/TCPConnector.h - -QPIDCLIENT_VERSION_INFO = 2:0:0 -libqpidclient_la_LDFLAGS = -version-info $(QPIDCLIENT_VERSION_INFO) - -libqpidtypes_la_LIBADD= -luuid -libqpidtypes_la_SOURCES= \ - qpid/types/Exception.cpp \ - qpid/types/Uuid.cpp \ - qpid/types/Variant.cpp \ - ../include/qpid/types/ImportExport.h - -QPIDTYPES_VERSION_INFO = 1:0:0 -libqpidtypes_la_LDFLAGS = -version-info $(QPIDTYPES_VERSION_INFO) - -libqpidmessaging_la_LIBADD = libqpidclient.la libqpidtypes.la -libqpidmessaging_la_SOURCES = \ - qpid/messaging/Address.cpp \ - qpid/messaging/AddressParser.h \ - qpid/messaging/AddressParser.cpp \ - qpid/messaging/Connection.cpp \ - qpid/messaging/Duration.cpp \ - qpid/messaging/exceptions.cpp \ - qpid/messaging/Message.cpp \ - qpid/messaging/MessageImpl.h \ - qpid/messaging/MessageImpl.cpp \ - qpid/messaging/PrivateImplRef.h \ - qpid/messaging/Sender.cpp \ - qpid/messaging/Receiver.cpp \ - qpid/messaging/Session.cpp \ - qpid/messaging/ConnectionImpl.h \ - qpid/messaging/SenderImpl.h \ - qpid/messaging/ReceiverImpl.h \ - qpid/messaging/SessionImpl.h \ - qpid/messaging/FailoverUpdates.cpp \ - qpid/client/amqp0_10/AcceptTracker.h \ - qpid/client/amqp0_10/AcceptTracker.cpp \ - qpid/client/amqp0_10/AddressResolution.h \ - qpid/client/amqp0_10/AddressResolution.cpp \ - qpid/client/amqp0_10/ConnectionImpl.h \ - qpid/client/amqp0_10/ConnectionImpl.cpp \ - qpid/client/amqp0_10/IncomingMessages.h \ - qpid/client/amqp0_10/IncomingMessages.cpp \ - qpid/client/amqp0_10/MessageSink.h \ - qpid/client/amqp0_10/MessageSource.h \ - qpid/client/amqp0_10/OutgoingMessage.h \ - qpid/client/amqp0_10/OutgoingMessage.cpp \ - qpid/client/amqp0_10/ReceiverImpl.h \ - qpid/client/amqp0_10/ReceiverImpl.cpp \ - qpid/client/amqp0_10/SessionImpl.h \ - qpid/client/amqp0_10/SessionImpl.cpp \ - qpid/client/amqp0_10/SenderImpl.h \ - qpid/client/amqp0_10/SenderImpl.cpp \ - qpid/client/amqp0_10/SimpleUrlParser.h \ - qpid/client/amqp0_10/SimpleUrlParser.cpp - -QPIDMESSAGING_VERSION_INFO = 2:0:0 -libqpidmessaging_la_LDFLAGS = -version-info $(QPIDMESSAGING_VERSION_INFO) - -# NOTE: only public header files (which should be in ../include) -# should go in this list. Private headers should go in the SOURCES -# list for one of the libraries or executables that includes it. - -nobase_include_HEADERS += \ - ../include/qpid/Address.h \ - ../include/qpid/CommonImportExport.h \ - ../include/qpid/Exception.h \ - ../include/qpid/ImportExport.h \ - ../include/qpid/InlineAllocator.h \ - ../include/qpid/InlineVector.h \ - ../include/qpid/Msg.h \ - ../include/qpid/Options.h \ - ../include/qpid/RangeSet.h \ - ../include/qpid/SessionId.h \ - ../include/qpid/Url.h \ - ../include/qpid/amqp_0_10/Codecs.h \ - ../include/qpid/client/AsyncSession.h \ - ../include/qpid/client/ClientImportExport.h \ - ../include/qpid/client/Completion.h \ - ../include/qpid/client/Connection.h \ - ../include/qpid/client/ConnectionSettings.h \ - ../include/qpid/client/FailoverListener.h \ - ../include/qpid/client/FailoverManager.h \ - ../include/qpid/client/FlowControl.h \ - ../include/qpid/client/Future.h \ - ../include/qpid/client/FutureCompletion.h \ - ../include/qpid/client/FutureResult.h \ - ../include/qpid/client/Handle.h \ - ../include/qpid/client/LocalQueue.h \ - ../include/qpid/client/Message.h \ - ../include/qpid/client/MessageListener.h \ - ../include/qpid/client/MessageReplayTracker.h \ - ../include/qpid/client/QueueOptions.h \ - ../include/qpid/client/Session.h \ - ../include/qpid/client/SessionBase_0_10.h \ - ../include/qpid/client/Subscription.h \ - ../include/qpid/client/SubscriptionManager.h \ - ../include/qpid/client/SubscriptionSettings.h \ - ../include/qpid/client/TypedResult.h \ - ../include/qpid/framing/Array.h \ - ../include/qpid/framing/Buffer.h \ - ../include/qpid/framing/FieldTable.h \ - ../include/qpid/framing/FieldValue.h \ - ../include/qpid/framing/List.h \ - ../include/qpid/framing/ProtocolVersion.h \ - ../include/qpid/framing/SequenceNumber.h \ - ../include/qpid/framing/SequenceSet.h \ - ../include/qpid/framing/StructHelper.h \ - ../include/qpid/framing/Uuid.h \ - ../include/qpid/framing/amqp_types.h \ - ../include/qpid/framing/amqp_types_full.h \ - ../include/qpid/log/Logger.h \ - ../include/qpid/log/Options.h \ - ../include/qpid/log/Selector.h \ - ../include/qpid/log/SinkOptions.h \ - ../include/qpid/log/Statement.h \ - ../include/qpid/management/Args.h \ - ../include/qpid/management/Buffer.h \ - ../include/qpid/management/ConnectionSettings.h \ - ../include/qpid/management/Manageable.h \ - ../include/qpid/management/ManagementEvent.h \ - ../include/qpid/management/ManagementObject.h \ - ../include/qpid/management/Mutex.h \ - ../include/qpid/sys/Condition.h \ - ../include/qpid/sys/ExceptionHolder.h \ - ../include/qpid/sys/IOHandle.h \ - ../include/qpid/sys/IntegerTypes.h \ - ../include/qpid/sys/Monitor.h \ - ../include/qpid/sys/Mutex.h \ - ../include/qpid/sys/Runnable.h \ - ../include/qpid/sys/StrError.h \ - ../include/qpid/sys/SystemInfo.h \ - ../include/qpid/sys/Thread.h \ - ../include/qpid/sys/Time.h \ - ../include/qpid/messaging/Address.h \ - ../include/qpid/messaging/Connection.h \ - ../include/qpid/messaging/Duration.h \ - ../include/qpid/messaging/exceptions.h \ - ../include/qpid/messaging/Handle.h \ - ../include/qpid/messaging/ImportExport.h \ - ../include/qpid/messaging/Message.h \ - ../include/qpid/messaging/Receiver.h \ - ../include/qpid/messaging/Sender.h \ - ../include/qpid/messaging/Session.h \ - ../include/qpid/messaging/FailoverUpdates.h \ - ../include/qpid/types/Exception.h \ - ../include/qpid/types/Uuid.h \ - ../include/qpid/types/Variant.h \ - ../include/qpid/types/ImportExport.h - -# Create the default data directory -install-data-local: - $(mkinstalldirs) $(DESTDIR)/$(localstatedir)/lib/qpidd - -# Support for pkg-config -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = qpid.pc diff --git a/cpp/src/acl.mk b/cpp/src/acl.mk deleted file mode 100644 index b8e2ff0e13..0000000000 --- a/cpp/src/acl.mk +++ /dev/null @@ -1,41 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# -# acl library makefile fragment, to be included in Makefile.am -# -dmoduleexec_LTLIBRARIES += acl.la - -acl_la_SOURCES = \ - qpid/acl/Acl.cpp \ - qpid/acl/Acl.h \ - qpid/acl/AclData.cpp \ - qpid/acl/AclData.h \ - qpid/acl/AclPlugin.cpp \ - qpid/acl/AclReader.cpp \ - qpid/acl/AclReader.h \ - qpid/acl/AclValidator.cpp \ - qpid/acl/AclValidator.h - -acl_la_LIBADD = libqpidbroker.la -if SUNOS - acl_la_LIBADD += libqmfagent.la libqmfconsole.la libqpidcommon.la -lboost_program_options $(SUNCC_RUNTIME_LIBS) -endif - -acl_la_LDFLAGS = $(PLUGINLDFLAGS) - diff --git a/cpp/src/cluster.cmake b/cpp/src/cluster.cmake deleted file mode 100644 index a389f8f13f..0000000000 --- a/cpp/src/cluster.cmake +++ /dev/null @@ -1,168 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# -# Cluster library CMake fragment, to be included in CMakeLists.txt -# - -# Optional cluster support. Requires CPG; if building it, can optionally -# include CMAN support as well. - -include(CheckIncludeFiles) -include(CheckLibraryExists) - -set(LIBCPG_PATH /usr/lib/openais /usr/lib64/openais /usr/lib/corosync /usr/lib64/corosync CACHE STRING "Default locations for libcpg (cluster library)" ) -find_library(LIBCPG cpg ${LIBCPG_PATH}) -if (LIBCPG) - CHECK_LIBRARY_EXISTS (${LIBCPG} cpg_local_get "" HAVE_LIBCPG) - CHECK_INCLUDE_FILES (openais/cpg.h HAVE_OPENAIS_CPG_H) - CHECK_INCLUDE_FILES (corosync/cpg.h HAVE_COROSYNC_CPG_H) -endif (LIBCPG) - -set (cluster_default ${cluster_force}) -if (CMAKE_SYSTEM_NAME STREQUAL Windows) -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - if (HAVE_LIBCPG) - if (HAVE_OPENAIS_CPG_H OR HAVE_COROSYNC_CPG_H) - set (cluster_default ON) - endif (HAVE_OPENAIS_CPG_H OR HAVE_COROSYNC_CPG_H) - endif (HAVE_LIBCPG) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -option(BUILD_CLUSTER "Build with CPG support for clustering" ${cluster_default}) -if (BUILD_CLUSTER) - - if (NOT HAVE_LIBCPG) - message(FATAL_ERROR "libcpg not found, install openais-devel or corosync-devel") - endif (NOT HAVE_LIBCPG) - if (NOT HAVE_OPENAIS_CPG_H AND NOT HAVE_COROSYNC_CPG_H) - message(FATAL_ERROR "cpg.h not found, install openais-devel or corosync-devel") - endif (NOT HAVE_OPENAIS_CPG_H AND NOT HAVE_COROSYNC_CPG_H) - - CHECK_LIBRARY_EXISTS (cman cman_is_quorate "" HAVE_LIBCMAN) - CHECK_INCLUDE_FILES (libcman.h HAVE_LIBCMAN_H) - - set(cluster_quorum_default ${cluster_quorum_force}) - if (HAVE_LIBCMAN AND HAVE_LIBCMAN_H) - set(cluster_quorum_default ON) - endif (HAVE_LIBCMAN AND HAVE_LIBCMAN_H) - - option(BUILD_CLUSTER_QUORUM "Include libcman quorum service integration" ${cluster_quorum_default}) - if (BUILD_CLUSTER_QUORUM) - if (NOT HAVE_LIBCMAN) - message(FATAL_ERROR "libcman not found, install cman-devel or cmanlib-devel") - endif (NOT HAVE_LIBCMAN) - if (NOT HAVE_LIBCMAN_H) - message(FATAL_ERROR "libcman.h not found, install cman-devel or cmanlib-devel") - endif (NOT HAVE_LIBCMAN_H) - - set (CMAN_SOURCES qpid/cluster/Quorum_cman.h qpid/cluster/Quorum_cman.cpp) - set (CMAN_LIB cman) - else (BUILD_CLUSTER_QUORUM) - set (CMAN_SOURCES qpid/cluster/Quorum_null.h) - endif (BUILD_CLUSTER_QUORUM) - - set (cluster_SOURCES - ${CMAN_SOURCES} - qpid/cluster/Cluster.cpp - qpid/cluster/Cluster.h - qpid/cluster/ClusterTimer.cpp - qpid/cluster/ClusterTimer.h - qpid/cluster/Decoder.cpp - qpid/cluster/Decoder.h - qpid/cluster/PollableQueue.h - qpid/cluster/ClusterMap.cpp - qpid/cluster/ClusterMap.h - qpid/cluster/ClusterPlugin.cpp - qpid/cluster/ClusterSettings.h - qpid/cluster/Connection.cpp - qpid/cluster/Connection.h - qpid/cluster/ConnectionCodec.cpp - qpid/cluster/ConnectionCodec.h - qpid/cluster/Cpg.cpp - qpid/cluster/Cpg.h - qpid/cluster/Dispatchable.h - qpid/cluster/UpdateClient.cpp - qpid/cluster/UpdateClient.h - qpid/cluster/RetractClient.cpp - qpid/cluster/RetractClient.h - qpid/cluster/ErrorCheck.cpp - qpid/cluster/ErrorCheck.h - qpid/cluster/Event.cpp - qpid/cluster/Event.h - qpid/cluster/EventFrame.h - qpid/cluster/EventFrame.cpp - qpid/cluster/ExpiryPolicy.h - qpid/cluster/ExpiryPolicy.cpp - qpid/cluster/FailoverExchange.cpp - qpid/cluster/FailoverExchange.h - qpid/cluster/UpdateExchange.cpp - qpid/cluster/UpdateExchange.h - qpid/cluster/UpdateReceiver.h - qpid/cluster/LockedConnectionMap.h - qpid/cluster/Multicaster.cpp - qpid/cluster/Multicaster.h - qpid/cluster/McastFrameHandler.h - qpid/cluster/NoOpConnectionOutputHandler.h - qpid/cluster/Numbering.h - qpid/cluster/OutputInterceptor.cpp - qpid/cluster/OutputInterceptor.h - qpid/cluster/PollerDispatch.cpp - qpid/cluster/PollerDispatch.h - qpid/cluster/ProxyInputHandler.h - qpid/cluster/Quorum.h - qpid/cluster/InitialStatusMap.h - qpid/cluster/InitialStatusMap.cpp - qpid/cluster/MemberSet.h - qpid/cluster/MemberSet.cpp - qpid/cluster/types.h - qpid/cluster/SecureConnectionFactory.h - qpid/cluster/SecureConnectionFactory.cpp - qpid/cluster/StoreStatus.h - qpid/cluster/StoreStatus.cpp - qpid/cluster/UpdateDataExchange.h - qpid/cluster/UpdateDataExchange.cpp - ) - - add_library (cluster MODULE ${cluster_SOURCES}) - target_link_libraries (cluster ${LIBCPG} ${CMAN_LIB} qpidbroker qpidclient ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}) - set_target_properties (cluster PROPERTIES PREFIX "") - - # Create a second shared library for linking with test executables, - # cmake will not allow a module to be linked with an executable. - add_library (cluster_shared SHARED ${cluster_SOURCES}) - target_link_libraries (cluster_shared ${LIBCPG} ${CMAN_LIB} qpidbroker qpidclient ${Boost_FILESYSTEM_LIBRARY}) - - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(cluster PROPERTIES - LINK_FLAGS "-Wl,--no-undefined -pthread") - endif (CMAKE_COMPILER_IS_GNUCXX) - - install (TARGETS cluster - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - - add_library (watchdog MODULE qpid/cluster/WatchDogPlugin.cpp) - set_target_properties (watchdog PROPERTIES PREFIX "") - - add_executable(qpidd_watchdog qpid/cluster/qpidd_watchdog.cpp) - -endif (BUILD_CLUSTER) - -# Distribute all sources. -#EXTRA_DIST += qpid/cluster/Quorum_cman.h qpid/cluster/Quorum_cman.cpp qpid/cluster/Quorum_null.h diff --git a/cpp/src/cluster.mk b/cpp/src/cluster.mk deleted file mode 100644 index 3ce4ce25b3..0000000000 --- a/cpp/src/cluster.mk +++ /dev/null @@ -1,113 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# -# Cluster library makefile fragment, to be included in Makefile.am -# - -# Optional CMAN support - -# Distribute all sources. -EXTRA_DIST += qpid/cluster/Quorum_cman.h qpid/cluster/Quorum_cman.cpp qpid/cluster/Quorum_null.h - -if HAVE_LIBCMAN -CMAN_SOURCES = qpid/cluster/Quorum_cman.h qpid/cluster/Quorum_cman.cpp -libcman = -lcman -else -CMAN_SOURCES = qpid/cluster/Quorum_null.h -endif - -if HAVE_LIBCPG - -dmoduleexec_LTLIBRARIES += cluster.la - -cluster_la_SOURCES = \ - $(CMAN_SOURCES) \ - qpid/cluster/Cluster.cpp \ - qpid/cluster/Cluster.h \ - qpid/cluster/ClusterTimer.cpp \ - qpid/cluster/ClusterTimer.h \ - qpid/cluster/Decoder.cpp \ - qpid/cluster/Decoder.h \ - qpid/cluster/PollableQueue.h \ - qpid/cluster/ClusterMap.cpp \ - qpid/cluster/ClusterMap.h \ - qpid/cluster/ClusterPlugin.cpp \ - qpid/cluster/ClusterSettings.h \ - qpid/cluster/Connection.cpp \ - qpid/cluster/Connection.h \ - qpid/cluster/ConnectionCodec.cpp \ - qpid/cluster/ConnectionCodec.h \ - qpid/cluster/Cpg.cpp \ - qpid/cluster/Cpg.h \ - qpid/cluster/Dispatchable.h \ - qpid/cluster/UpdateClient.cpp \ - qpid/cluster/UpdateClient.h \ - qpid/cluster/RetractClient.cpp \ - qpid/cluster/RetractClient.h \ - qpid/cluster/ErrorCheck.cpp \ - qpid/cluster/ErrorCheck.h \ - qpid/cluster/Event.cpp \ - qpid/cluster/Event.h \ - qpid/cluster/EventFrame.h \ - qpid/cluster/EventFrame.cpp \ - qpid/cluster/ExpiryPolicy.h \ - qpid/cluster/ExpiryPolicy.cpp \ - qpid/cluster/FailoverExchange.cpp \ - qpid/cluster/FailoverExchange.h \ - qpid/cluster/UpdateExchange.h \ - qpid/cluster/UpdateExchange.cpp \ - qpid/cluster/UpdateReceiver.h \ - qpid/cluster/LockedConnectionMap.h \ - qpid/cluster/Multicaster.cpp \ - qpid/cluster/Multicaster.h \ - qpid/cluster/McastFrameHandler.h \ - qpid/cluster/NoOpConnectionOutputHandler.h \ - qpid/cluster/Numbering.h \ - qpid/cluster/OutputInterceptor.cpp \ - qpid/cluster/OutputInterceptor.h \ - qpid/cluster/PollerDispatch.cpp \ - qpid/cluster/PollerDispatch.h \ - qpid/cluster/ProxyInputHandler.h \ - qpid/cluster/Quorum.h \ - qpid/cluster/InitialStatusMap.h \ - qpid/cluster/InitialStatusMap.cpp \ - qpid/cluster/MemberSet.h \ - qpid/cluster/MemberSet.cpp \ - qpid/cluster/types.h \ - qpid/cluster/SecureConnectionFactory.h \ - qpid/cluster/SecureConnectionFactory.cpp \ - qpid/cluster/StoreStatus.h \ - qpid/cluster/StoreStatus.cpp \ - qpid/cluster/UpdateDataExchange.h \ - qpid/cluster/UpdateDataExchange.cpp - -cluster_la_LIBADD= -lcpg $(libcman) libqpidbroker.la libqpidclient.la -cluster_la_CXXFLAGS = $(AM_CXXFLAGS) -fno-strict-aliasing -cluster_la_LDFLAGS = $(PLUGINLDFLAGS) - -# The watchdog plugin and helper executable -dmoduleexec_LTLIBRARIES += watchdog.la -watchdog_la_SOURCES = qpid/cluster/WatchDogPlugin.cpp -watchdog_la_LIBADD = libqpidbroker.la -watchdog_la_LDFLAGS = $(PLUGINLDFLAGS) - -qpidexec_PROGRAMS += qpidd_watchdog -qpidd_watchdog_SOURCES = qpid/cluster/qpidd_watchdog.cpp - -endif # HAVE_LIBCPG diff --git a/cpp/src/config.h.cmake b/cpp/src/config.h.cmake deleted file mode 100644 index 2bb84c6e47..0000000000 --- a/cpp/src/config.h.cmake +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * This file is automatically generated and will be overwritten by the - * next CMake invocation. - */ - -#ifndef QPID_CONFIG_H -#define QPID_CONFIG_H - -// PACKAGE_NAME and PACKAGE_VERSION are carry-overs from the autoconf world. -// They tend to cause confusion and problems when mixing headers from multiple -// autoconf-configured packages, so it's best to remove these in favor of -// Qpid-specific names as soon as the autoconf stuff is removed. -#define PACKAGE_NAME "${CMAKE_PROJECT_NAME}" -#define PACKAGE_VERSION "${qpidc_version}" - -#cmakedefine QPIDC_CONF_FILE "${QPIDC_CONF_FILE}" -#cmakedefine QPIDD_CONF_FILE "${QPIDD_CONF_FILE}" - -#cmakedefine QPIDC_MODULE_DIR "${QPIDC_MODULE_DIR}" -#cmakedefine QPIDD_MODULE_DIR "${QPIDD_MODULE_DIR}" - -#cmakedefine QPID_LIBEXEC_DIR "${QPID_LIBEXEC_DIR}" - -#define QPID_SHLIB_PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}" -#define QPID_MODULE_PREFIX -#cmakedefine QPID_DEBUG_POSTFIX "${QPID_DEBUG_POSTFIX}" -#if defined(QPID_DEBUG_POSTFIX) && defined (_DEBUG) -# define QPID_SHLIB_POSTFIX QPID_DEBUG_POSTFIX -# define QPID_MODULE_POSTFIX QPID_DEBUG_POSTFIX -#else -# define QPID_SHLIB_POSTFIX -# define QPID_MODULE_POSTFIX -#endif -#define QPID_SHLIB_SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}" -#define QPID_MODULE_SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}" - -#cmakedefine QPID_HAS_CLOCK_GETTIME - -#cmakedefine BROKER_SASL_NAME "${BROKER_SASL_NAME}" -#cmakedefine HAVE_SASL ${HAVE_SASL} - -#cmakedefine HAVE_OPENAIS_CPG_H ${HAVE_OPENAIS_CPG_H} -#cmakedefine HAVE_COROSYNC_CPG_H ${HAVE_COROSYNC_CPG_H} -#cmakedefine HAVE_LIBCMAN_H ${HAVE_LIBCMAN_H} -#cmakedefine HAVE_LOG_AUTHPRIV -#cmakedefine HAVE_LOG_FTP - -#endif /* QPID_CONFIG_H */ diff --git a/cpp/src/generate.sh b/cpp/src/generate.sh deleted file mode 100755 index 581a45ff7f..0000000000 --- a/cpp/src/generate.sh +++ /dev/null @@ -1,67 +0,0 @@ -# !/bin/sh - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Generate code from AMQP specification. -# specs and gentools_dir are set by Makefile -# -set -e - -test -z "$JAVA" && JAVA=java ; -test -z "$JAVAC" && JAVAC=javac ; - -srcdir=`dirname $0` -checkspecs() { - for s in $specs; do test -f $s || return 1; done - return 0 -} - -# Can we generate code? -if { test -d $gentools_dir && checkspecs && - which $JAVA && which $JAVAC; } > /dev/null; -then - echo "Generating code." - mkdir -p gen/qpid/framing - ( cd $gentools_dir/src && $JAVAC `find -name '*.java' -print` ; ) - $JAVA -cp $gentools_dir/src org.apache.qpid.gentools.Main \ - -c -o gen/qpid/framing -t $gentools_dir/templ.cpp $specs - GENERATED=yes -fi - -# Print a Makefile variable assignment. -make_assign() { - echo -n "$1 = "; shift - prefix=$1; shift - for f in $*; do echo "\\" ; echo -n " $prefix$f "; done - echo -} - -# Generate a Makefile fragment -( - make_assign "generated_cpp" "" `find gen -name '*.cpp' -print` - make_assign "generated_h" "" `find gen -name '*.h' -print` - if test x$GENERATED = xyes; then - make_assign "generator" "" $specs \ - `find ../gentools \( -name '*.java' -o -name '*.tmpl' \) -print` - fi -) > generate.mk-t -mv generate.mk-t $srcdir/generate.mk - - - diff --git a/cpp/src/posix/QpiddBroker.cpp b/cpp/src/posix/QpiddBroker.cpp deleted file mode 100644 index 879935462e..0000000000 --- a/cpp/src/posix/QpiddBroker.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "config.h" -#include "qpidd.h" -#include "qpid/Exception.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Daemon.h" -#include "qpid/broker/SignalHandler.h" -#include "qpid/log/Logger.h" - -#include <iostream> -#include <signal.h> -#include <unistd.h> -#include <sys/utsname.h> - -using namespace std; -using namespace qpid; -using qpid::broker::Broker; -using qpid::broker::Daemon; - -BootstrapOptions::BootstrapOptions(const char* argv0) - : qpid::Options("Options"), - common("", QPIDD_CONF_FILE), - module(QPIDD_MODULE_DIR), - log(argv0) -{ - add(common); - add(module); - add(log); -} - -namespace { -const std::string TCP = "tcp"; -} - -struct DaemonOptions : public qpid::Options { - bool daemon; - bool quit; - bool check; - int wait; - std::string piddir; - std::string transport; - - DaemonOptions() : qpid::Options("Daemon options"), daemon(false), quit(false), check(false), wait(600), transport(TCP) - { - char *home = ::getenv("HOME"); - - if (home == 0) - piddir += "/tmp"; - else - piddir += home; - piddir += "/.qpidd"; - - addOptions() - ("daemon,d", optValue(daemon), "Run as a daemon. Logs to syslog by default in this mode.") - ("transport", optValue(transport, "TRANSPORT"), "The transport for which to return the port") - ("pid-dir", optValue(piddir, "DIR"), "Directory where port-specific PID file is stored") - ("wait,w", optValue(wait, "SECONDS"), "Sets the maximum wait time to initialize the daemon. If the daemon fails to initialize, prints an error and returns 1") - ("check,c", optValue(check), "Prints the daemon's process ID to stdout and returns 0 if the daemon is running, otherwise returns 1") - ("quit,q", optValue(quit), "Tells the daemon to shut down"); - } -}; - -struct QpiddPosixOptions : public QpiddOptionsPrivate { - DaemonOptions daemon; - QpiddOptions *parent; - - QpiddPosixOptions(QpiddOptions *parent_) : parent(parent_) { - parent->add(daemon); - } -}; - -QpiddOptions::QpiddOptions(const char* argv0) - : qpid::Options("Options"), - common("", QPIDD_CONF_FILE), - module(QPIDD_MODULE_DIR), - log(argv0) -{ - add(common); - add(module); - add(broker); - add(log); - - platform.reset(new QpiddPosixOptions(this)); - qpid::Plugin::addOptions(*this); -} - -void QpiddOptions::usage() const { - cout << "Usage: qpidd [OPTIONS]" << endl << endl << *this << endl; -} - -// Set the broker pointer on the signal handler, then reset at end of scope. -// This is to ensure that the signal handler doesn't keep a broker -// reference after main() has returned. -// -struct ScopedSetBroker { - ScopedSetBroker(const boost::intrusive_ptr<Broker>& broker) { - qpid::broker::SignalHandler::setBroker(broker.get()); - } - ~ScopedSetBroker() { qpid::broker::SignalHandler::setBroker(0); } -}; - -struct QpiddDaemon : public Daemon { - QpiddPosixOptions *options; - - QpiddDaemon(std::string pidDir, QpiddPosixOptions *opts) - : Daemon(pidDir), options(opts) {} - - /** Code for parent process */ - void parent() { - uint16_t port = wait(options->daemon.wait); - if (options->parent->broker.port == 0 || options->daemon.transport != TCP) - cout << port << endl; - } - - /** Code for forked child process */ - void child() { - boost::intrusive_ptr<Broker> brokerPtr(new Broker(options->parent->broker)); - ScopedSetBroker ssb(brokerPtr); - brokerPtr->accept(); - uint16_t port=brokerPtr->getPort(options->daemon.transport); - ready(port); // Notify parent. - brokerPtr->run(); - } -}; - -int QpiddBroker::execute (QpiddOptions *options) { - // Options that affect a running daemon. - QpiddPosixOptions *myOptions = - static_cast<QpiddPosixOptions *>(options->platform.get()); - if (myOptions == 0) - throw Exception("Internal error obtaining platform options"); - - if (myOptions->daemon.check || myOptions->daemon.quit) { - pid_t pid = Daemon::getPid(myOptions->daemon.piddir, - options->broker.port); - if (pid < 0) - return 1; - if (myOptions->daemon.check) - cout << pid << endl; - if (myOptions->daemon.quit) { - if (kill(pid, SIGINT) < 0) - throw Exception("Failed to stop daemon: " + qpid::sys::strError(errno)); - // Wait for the process to die before returning - int retry=10000; // Try up to 10 seconds - while (kill(pid,0) == 0 && --retry) - sys::usleep(1000); - if (retry == 0) - throw Exception("Gave up waiting for daemon process to exit"); - } - return 0; - } - - // Starting the broker. - if (myOptions->daemon.daemon) { - // For daemon mode replace default stderr with syslog. - options->log.sinkOptions->detached(); - qpid::log::Logger::instance().configure(options->log); - // Fork the daemon - QpiddDaemon d(myOptions->daemon.piddir, myOptions); - d.fork(); // Broker is stared in QpiddDaemon::child() - } - else { // Non-daemon broker. - boost::intrusive_ptr<Broker> brokerPtr(new Broker(options->broker)); - ScopedSetBroker ssb(brokerPtr); - brokerPtr->accept(); - if (options->broker.port == 0 || myOptions->daemon.transport != TCP) - cout << uint16_t(brokerPtr->getPort(myOptions->daemon.transport)) << endl; - brokerPtr->run(); - } - return 0; -} diff --git a/cpp/src/prof b/cpp/src/prof deleted file mode 100755 index acfbaff2d4..0000000000 --- a/cpp/src/prof +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -# -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# - - -rm /var/lib/oprofile/oprofiled.log - -opcontrol --reset -opcontrol --setup --no-vmlinux --separate=library -opcontrol --start -# -- Do stuff here -- -./qpidd -# -- End of stuff -- -opcontrol --stop -opcontrol --dump -opcontrol --shutdown -opreport -l ./.libs/lt-qpidd > stats.txt -opannotate --source --output-dir=qpidd-prof ./.libs/lt-qpidd - -# clear the relusts -#opcontrol --reset diff --git a/cpp/src/qmf.mk b/cpp/src/qmf.mk deleted file mode 100644 index f3462f1a93..0000000000 --- a/cpp/src/qmf.mk +++ /dev/null @@ -1,167 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# -# qmf library makefile fragment, to be included in Makefile.am -# -lib_LTLIBRARIES += \ - libqmf.la \ - libqmfengine.la \ - libqmf2.la - -# -# Public headers for the QMF API -# -QMF_API = \ - ../include/qpid/agent/ManagementAgent.h \ - ../include/qpid/agent/QmfAgentImportExport.h - -# -# Public headers for the QMF2 API -# -QMF2_API = \ - ../include/qmf/AgentEvent.h \ - ../include/qmf/Agent.h \ - ../include/qmf/AgentSession.h \ - ../include/qmf/ConsoleEvent.h \ - ../include/qmf/ConsoleSession.h \ - ../include/qmf/DataAddr.h \ - ../include/qmf/Data.h \ - ../include/qmf/exceptions.h \ - ../include/qmf/Handle.h \ - ../include/qmf/ImportExport.h \ - ../include/qmf/Query.h \ - ../include/qmf/Schema.h \ - ../include/qmf/SchemaId.h \ - ../include/qmf/SchemaMethod.h \ - ../include/qmf/SchemaProperty.h \ - ../include/qmf/SchemaTypes.h \ - ../include/qmf/Subscription.h - - -# -# Public headers for the QMF Engine API -# -QMF_ENGINE_API = \ - ../include/qmf/engine/Agent.h \ - ../include/qmf/engine/ConnectionSettings.h \ - ../include/qmf/engine/Console.h \ - ../include/qmf/engine/Event.h \ - ../include/qmf/engine/Message.h \ - ../include/qmf/engine/Object.h \ - ../include/qmf/engine/ObjectId.h \ - ../include/qmf/engine/QmfEngineImportExport.h \ - ../include/qmf/engine/Query.h \ - ../include/qmf/engine/ResilientConnection.h \ - ../include/qmf/engine/Schema.h \ - ../include/qmf/engine/Typecode.h \ - ../include/qmf/engine/Value.h - -# Public header files -nobase_include_HEADERS += \ - $(QMF_API) \ - $(QMF_ENGINE_API) \ - $(QMF2_API) - -libqmf_la_SOURCES = \ - $(QMF_API) \ - qpid/agent/ManagementAgentImpl.cpp \ - qpid/agent/ManagementAgentImpl.h - -libqmf2_la_SOURCES = \ - $(QMF2_API) \ - qmf/agentCapability.h \ - qmf/Agent.cpp \ - qmf/AgentEvent.cpp \ - qmf/AgentEventImpl.h \ - qmf/AgentImpl.h \ - qmf/AgentSession.cpp \ - qmf/AgentSubscription.cpp \ - qmf/AgentSubscription.h \ - qmf/ConsoleEvent.cpp \ - qmf/ConsoleEventImpl.h \ - qmf/ConsoleSession.cpp \ - qmf/ConsoleSessionImpl.h \ - qmf/constants.cpp \ - qmf/constants.h \ - qmf/DataAddr.cpp \ - qmf/DataAddrImpl.h \ - qmf/Data.cpp \ - qmf/DataImpl.h \ - qmf/exceptions.cpp \ - qmf/Expression.cpp \ - qmf/Expression.h \ - qmf/Hash.cpp \ - qmf/Hash.h \ - qmf/PrivateImplRef.h \ - qmf/Query.cpp \ - qmf/QueryImpl.h \ - qmf/Schema.cpp \ - qmf/SchemaCache.cpp \ - qmf/SchemaCache.h \ - qmf/SchemaId.cpp \ - qmf/SchemaIdImpl.h \ - qmf/SchemaImpl.h \ - qmf/SchemaMethod.cpp \ - qmf/SchemaMethodImpl.h \ - qmf/SchemaProperty.cpp \ - qmf/SchemaPropertyImpl.h \ - qmf/Subscription.cpp \ - qmf/SubscriptionImpl.h - -libqmfengine_la_SOURCES = \ - $(QMF_ENGINE_API) \ - qmf/engine/Agent.cpp \ - qmf/engine/BrokerProxyImpl.cpp \ - qmf/engine/BrokerProxyImpl.h \ - qmf/engine/ConnectionSettingsImpl.cpp \ - qmf/engine/ConnectionSettingsImpl.h \ - qmf/engine/ConsoleImpl.cpp \ - qmf/engine/ConsoleImpl.h \ - qmf/engine/EventImpl.cpp \ - qmf/engine/EventImpl.h \ - qmf/engine/MessageImpl.cpp \ - qmf/engine/MessageImpl.h \ - qmf/engine/ObjectIdImpl.cpp \ - qmf/engine/ObjectIdImpl.h \ - qmf/engine/ObjectImpl.cpp \ - qmf/engine/ObjectImpl.h \ - qmf/engine/Protocol.cpp \ - qmf/engine/Protocol.h \ - qmf/engine/QueryImpl.cpp \ - qmf/engine/QueryImpl.h \ - qmf/engine/ResilientConnection.cpp \ - qmf/engine/SequenceManager.cpp \ - qmf/engine/SequenceManager.h \ - qmf/engine/SchemaImpl.cpp \ - qmf/engine/SchemaImpl.h \ - qmf/engine/ValueImpl.cpp \ - qmf/engine/ValueImpl.h - -libqmf_la_LIBADD = libqmfengine.la -libqmf2_la_LIBADD = libqpidmessaging.la libqpidtypes.la -libqmfengine_la_LIBADD = libqpidclient.la - -QMF_VERSION_INFO = 1:0:0 -QMF2_VERSION_INFO = 1:0:0 -QMFENGINE_VERSION_INFO = 1:1:0 - -libqmf_la_LDFLAGS = -version-info $(QMF_VERSION_INFO) -libqmf2_la_LDFLAGS = -version-info $(QMF2_VERSION_INFO) -libqmfengine_la_LDFLAGS = -version-info $(QMFENGINE_VERSION_INFO) diff --git a/cpp/src/qmf/Agent.cpp b/cpp/src/qmf/Agent.cpp deleted file mode 100644 index 915f2a1c88..0000000000 --- a/cpp/src/qmf/Agent.cpp +++ /dev/null @@ -1,657 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/AgentImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/ConsoleEventImpl.h" -#include "qmf/ConsoleSession.h" -#include "qmf/DataImpl.h" -#include "qmf/Query.h" -#include "qmf/SchemaImpl.h" -#include "qmf/agentCapability.h" -#include "qmf/constants.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/management/Buffer.h" -#include "qpid/log/Statement.h" -#include <boost/lexical_cast.hpp> - -using qpid::types::Variant; -using qpid::messaging::Duration; -using qpid::messaging::Message; -using qpid::messaging::Sender; -using namespace std; -using namespace qmf; - -typedef PrivateImplRef<Agent> PI; - -Agent::Agent(AgentImpl* impl) { PI::ctor(*this, impl); } -Agent::Agent(const Agent& s) : qmf::Handle<AgentImpl>() { PI::copy(*this, s); } -Agent::~Agent() { PI::dtor(*this); } -Agent& Agent::operator=(const Agent& s) { return PI::assign(*this, s); } -string Agent::getName() const { return isValid() ? impl->getName() : ""; } -uint32_t Agent::getEpoch() const { return isValid() ? impl->getEpoch() : 0; } -string Agent::getVendor() const { return isValid() ? impl->getVendor() : ""; } -string Agent::getProduct() const { return isValid() ? impl->getProduct() : ""; } -string Agent::getInstance() const { return isValid() ? impl->getInstance() : ""; } -const Variant& Agent::getAttribute(const string& k) const { return impl->getAttribute(k); } -const Variant::Map& Agent::getAttributes() const { return impl->getAttributes(); } -ConsoleEvent Agent::querySchema(Duration t) { return impl->querySchema(t); } -uint32_t Agent::querySchemaAsync() { return impl->querySchemaAsync(); } -ConsoleEvent Agent::query(const Query& q, Duration t) { return impl->query(q, t); } -ConsoleEvent Agent::query(const string& q, Duration t) { return impl->query(q, t); } -uint32_t Agent::queryAsync(const Query& q) { return impl->queryAsync(q); } -uint32_t Agent::queryAsync(const string& q) { return impl->queryAsync(q); } -ConsoleEvent Agent::callMethod(const string& m, const Variant::Map& a, const DataAddr& d, Duration t) { return impl->callMethod(m, a, d, t); } -uint32_t Agent::callMethodAsync(const string& m, const Variant::Map& a, const DataAddr& d) { return impl->callMethodAsync(m, a, d); } -uint32_t Agent::getPackageCount() const { return impl->getPackageCount(); } -const string& Agent::getPackage(uint32_t i) const { return impl->getPackage(i); } -uint32_t Agent::getSchemaIdCount(const string& p) const { return impl->getSchemaIdCount(p); } -SchemaId Agent::getSchemaId(const string& p, uint32_t i) const { return impl->getSchemaId(p, i); } -Schema Agent::getSchema(const SchemaId& s, Duration t) { return impl->getSchema(s, t); } - - - -AgentImpl::AgentImpl(const std::string& n, uint32_t e, ConsoleSessionImpl& s) : - name(n), directSubject(n), epoch(e), session(s), touched(true), untouchedCount(0), capability(0), - sender(session.directSender), nextCorrelator(1), schemaCache(s.schemaCache) -{ -} - -void AgentImpl::setAttribute(const std::string& k, const qpid::types::Variant& v) -{ - attributes[k] = v; - if (k == "qmf.agent_capability") - try { - capability = v.asUint32(); - } catch (std::exception&) {} - if (k == "_direct_subject") - try { - directSubject = v.asString(); - sender = session.topicSender; - } catch (std::exception&) {} -} - -const Variant& AgentImpl::getAttribute(const string& k) const -{ - Variant::Map::const_iterator iter = attributes.find(k); - if (iter == attributes.end()) - throw KeyNotFound(k); - return iter->second; -} - - -ConsoleEvent AgentImpl::query(const Query& query, Duration timeout) -{ - boost::shared_ptr<SyncContext> context(new SyncContext()); - uint32_t correlator; - ConsoleEvent result; - - { - qpid::sys::Mutex::ScopedLock l(lock); - correlator = nextCorrelator++; - contextMap[correlator] = context; - } - try { - sendQuery(query, correlator); - { - uint64_t milliseconds = timeout.getMilliseconds(); - qpid::sys::Mutex::ScopedLock cl(context->lock); - if (!context->response.isValid() || !context->response.isFinal()) - context->cond.wait(context->lock, - qpid::sys::AbsTime(qpid::sys::now(), - qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC))); - if (context->response.isValid() && - ((context->response.getType() == CONSOLE_QUERY_RESPONSE && context->response.isFinal()) || - (context->response.getType() == CONSOLE_EXCEPTION))) - result = context->response; - else { - auto_ptr<ConsoleEventImpl> impl(new ConsoleEventImpl(CONSOLE_EXCEPTION)); - Data exception(new DataImpl()); - exception.setProperty("error_text", "Timed out waiting for the agent to respond"); - impl->addData(exception); - result = ConsoleEvent(impl.release()); - } - } - } catch (qpid::types::Exception&) { - } - - { - qpid::sys::Mutex::ScopedLock l(lock); - contextMap.erase(correlator); - } - - return result; -} - - -ConsoleEvent AgentImpl::query(const string& text, Duration timeout) -{ - return query(stringToQuery(text), timeout); -} - - -uint32_t AgentImpl::queryAsync(const Query& query) -{ - uint32_t correlator; - - { - qpid::sys::Mutex::ScopedLock l(lock); - correlator = nextCorrelator++; - } - - sendQuery(query, correlator); - return correlator; -} - - -uint32_t AgentImpl::queryAsync(const string& text) -{ - return queryAsync(stringToQuery(text)); -} - - -ConsoleEvent AgentImpl::callMethod(const string& method, const Variant::Map& args, const DataAddr& addr, Duration timeout) -{ - boost::shared_ptr<SyncContext> context(new SyncContext()); - uint32_t correlator; - ConsoleEvent result; - - { - qpid::sys::Mutex::ScopedLock l(lock); - correlator = nextCorrelator++; - contextMap[correlator] = context; - } - try { - sendMethod(method, args, addr, correlator); - { - uint64_t milliseconds = timeout.getMilliseconds(); - qpid::sys::Mutex::ScopedLock cl(context->lock); - if (!context->response.isValid()) - context->cond.wait(context->lock, - qpid::sys::AbsTime(qpid::sys::now(), - qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC))); - if (context->response.isValid()) - result = context->response; - else { - auto_ptr<ConsoleEventImpl> impl(new ConsoleEventImpl(CONSOLE_EXCEPTION)); - Data exception(new DataImpl()); - exception.setProperty("error_text", "Timed out waiting for the agent to respond"); - impl->addData(exception); - result = ConsoleEvent(impl.release()); - } - } - } catch (qpid::types::Exception&) { - } - - { - qpid::sys::Mutex::ScopedLock l(lock); - contextMap.erase(correlator); - } - - return result; -} - - -uint32_t AgentImpl::callMethodAsync(const string& method, const Variant::Map& args, const DataAddr& addr) -{ - uint32_t correlator; - - { - qpid::sys::Mutex::ScopedLock l(lock); - correlator = nextCorrelator++; - } - - sendMethod(method, args, addr, correlator); - return correlator; -} - - -uint32_t AgentImpl::getPackageCount() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - - // - // Populate the package set. - // - for (set<SchemaId>::const_iterator iter = schemaIdSet.begin(); iter != schemaIdSet.end(); iter++) - packageSet.insert(iter->getPackageName()); - - return packageSet.size(); -} - - -const string& AgentImpl::getPackage(uint32_t idx) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - uint32_t count(0); - for (set<string>::const_iterator iter = packageSet.begin(); iter != packageSet.end(); iter++) { - if (idx == count) - return *iter; - count++; - } - throw IndexOutOfRange(); -} - - -uint32_t AgentImpl::getSchemaIdCount(const string& pname) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - uint32_t count(0); - for (set<SchemaId>::const_iterator iter = schemaIdSet.begin(); iter != schemaIdSet.end(); iter++) - if (iter->getPackageName() == pname) - count++; - return count; -} - - -SchemaId AgentImpl::getSchemaId(const string& pname, uint32_t idx) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - uint32_t count(0); - for (set<SchemaId>::const_iterator iter = schemaIdSet.begin(); iter != schemaIdSet.end(); iter++) { - if (iter->getPackageName() == pname) { - if (idx == count) - return *iter; - count++; - } - } - throw IndexOutOfRange(); -} - - -Schema AgentImpl::getSchema(const SchemaId& id, Duration timeout) -{ - if (!schemaCache->haveSchema(id)) - // - // The desired schema is not in the cache. We need to asynchronously query the remote - // agent for the information. The call to schemaCache->getSchema will block waiting for - // the response to be received. - // - sendSchemaRequest(id); - - return schemaCache->getSchema(id, timeout); -} - - -void AgentImpl::handleException(const Variant::Map& content, const Message& msg) -{ - const string& cid(msg.getCorrelationId()); - Variant::Map::const_iterator aIter; - uint32_t correlator; - boost::shared_ptr<SyncContext> context; - - try { correlator = boost::lexical_cast<uint32_t>(cid); } - catch(const boost::bad_lexical_cast&) { correlator = 0; } - - { - qpid::sys::Mutex::ScopedLock l(lock); - map<uint32_t, boost::shared_ptr<SyncContext> >::iterator iter = contextMap.find(correlator); - if (iter != contextMap.end()) - context = iter->second; - } - - if (context.get() != 0) { - // - // This exception is associated with a synchronous request. - // - qpid::sys::Mutex::ScopedLock cl(context->lock); - context->response = ConsoleEvent(new ConsoleEventImpl(CONSOLE_EXCEPTION)); - ConsoleEventImplAccess::get(context->response).addData(new DataImpl(content, this)); - ConsoleEventImplAccess::get(context->response).setAgent(this); - context->cond.notify(); - } else { - // - // This exception is associated with an asynchronous request. - // - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_EXCEPTION)); - eventImpl->setCorrelator(correlator); - eventImpl->setAgent(this); - eventImpl->addData(new DataImpl(content, this)); - session.enqueueEvent(eventImpl.release()); - } -} - - -void AgentImpl::handleMethodResponse(const Variant::Map& response, const Message& msg) -{ - const string& cid(msg.getCorrelationId()); - Variant::Map::const_iterator aIter; - Variant::Map argMap; - uint32_t correlator; - boost::shared_ptr<SyncContext> context; - - QPID_LOG(trace, "RCVD MethodResponse cid=" << cid << " map=" << response); - - aIter = response.find("_arguments"); - if (aIter != response.end()) - argMap = aIter->second.asMap(); - - try { correlator = boost::lexical_cast<uint32_t>(cid); } - catch(const boost::bad_lexical_cast&) { correlator = 0; } - - { - qpid::sys::Mutex::ScopedLock l(lock); - map<uint32_t, boost::shared_ptr<SyncContext> >::iterator iter = contextMap.find(correlator); - if (iter != contextMap.end()) - context = iter->second; - } - - if (context.get() != 0) { - // - // This response is associated with a synchronous request. - // - qpid::sys::Mutex::ScopedLock cl(context->lock); - context->response = ConsoleEvent(new ConsoleEventImpl(CONSOLE_METHOD_RESPONSE)); - ConsoleEventImplAccess::get(context->response).setArguments(argMap); - ConsoleEventImplAccess::get(context->response).setAgent(this); - context->cond.notify(); - } else { - // - // This response is associated with an asynchronous request. - // - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_METHOD_RESPONSE)); - eventImpl->setCorrelator(correlator); - eventImpl->setAgent(this); - eventImpl->setArguments(argMap); - session.enqueueEvent(eventImpl.release()); - } -} - - -void AgentImpl::handleDataIndication(const Variant::List& list, const Message& msg) -{ - Variant::Map::const_iterator aIter; - const Variant::Map& props(msg.getProperties()); - boost::shared_ptr<SyncContext> context; - - aIter = props.find("qmf.content"); - if (aIter == props.end()) - return; - - string content_type(aIter->second.asString()); - if (content_type != "_event") - return; - - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - const Variant::Map& eventMap(lIter->asMap()); - Data data(new DataImpl(eventMap, this)); - int severity(SEV_NOTICE); - uint64_t timestamp(0); - - aIter = eventMap.find("_severity"); - if (aIter != eventMap.end()) - severity = int(aIter->second.asInt8()); - - aIter = eventMap.find("_timestamp"); - if (aIter != eventMap.end()) - timestamp = aIter->second.asUint64(); - - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_EVENT)); - eventImpl->setAgent(this); - eventImpl->addData(data); - eventImpl->setSeverity(severity); - eventImpl->setTimestamp(timestamp); - if (data.hasSchema()) - learnSchemaId(data.getSchemaId()); - session.enqueueEvent(eventImpl.release()); - } -} - - -void AgentImpl::handleQueryResponse(const Variant::List& list, const Message& msg) -{ - const string& cid(msg.getCorrelationId()); - Variant::Map::const_iterator aIter; - const Variant::Map& props(msg.getProperties()); - uint32_t correlator; - bool final(false); - boost::shared_ptr<SyncContext> context; - - aIter = props.find("partial"); - if (aIter == props.end()) - final = true; - - aIter = props.find("qmf.content"); - if (aIter == props.end()) - return; - - string content_type(aIter->second.asString()); - if (content_type != "_schema" && content_type != "_schema_id" && content_type != "_data") - return; - - try { correlator = boost::lexical_cast<uint32_t>(cid); } - catch(const boost::bad_lexical_cast&) { correlator = 0; } - - { - qpid::sys::Mutex::ScopedLock l(lock); - map<uint32_t, boost::shared_ptr<SyncContext> >::iterator iter = contextMap.find(correlator); - if (iter != contextMap.end()) - context = iter->second; - } - - if (context.get() != 0) { - // - // This response is associated with a synchronous request. - // - qpid::sys::Mutex::ScopedLock cl(context->lock); - if (!context->response.isValid()) - context->response = ConsoleEvent(new ConsoleEventImpl(CONSOLE_QUERY_RESPONSE)); - - if (content_type == "_data") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - Data data(new DataImpl(lIter->asMap(), this)); - ConsoleEventImplAccess::get(context->response).addData(data); - if (data.hasSchema()) - learnSchemaId(data.getSchemaId()); - } - else if (content_type == "_schema_id") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - SchemaId schemaId(new SchemaIdImpl(lIter->asMap())); - ConsoleEventImplAccess::get(context->response).addSchemaId(schemaId); - learnSchemaId(schemaId); - } - else if (content_type == "_schema") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - Schema schema(new SchemaImpl(lIter->asMap())); - schemaCache->declareSchema(schema); - } - - if (final) { - ConsoleEventImplAccess::get(context->response).setFinal(); - ConsoleEventImplAccess::get(context->response).setAgent(this); - context->cond.notify(); - } - } else { - // - // This response is associated with an asynchronous request. - // - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_QUERY_RESPONSE)); - eventImpl->setCorrelator(correlator); - eventImpl->setAgent(this); - - if (content_type == "_data") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - Data data(new DataImpl(lIter->asMap(), this)); - eventImpl->addData(data); - if (data.hasSchema()) - learnSchemaId(data.getSchemaId()); - } - else if (content_type == "_schema_id") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - SchemaId schemaId(new SchemaIdImpl(lIter->asMap())); - eventImpl->addSchemaId(schemaId); - learnSchemaId(schemaId); - } - else if (content_type == "_schema") - for (Variant::List::const_iterator lIter = list.begin(); lIter != list.end(); lIter++) { - Schema schema(new SchemaImpl(lIter->asMap())); - schemaCache->declareSchema(schema); - } - - if (final) - eventImpl->setFinal(); - if (content_type != "_schema") - session.enqueueEvent(eventImpl.release()); - } -} - - -Query AgentImpl::stringToQuery(const std::string& text) -{ - qpid::messaging::AddressParser parser(text); - Variant::Map map; - Variant::Map::const_iterator iter; - string className; - string packageName; - - parser.parseMap(map); - - iter = map.find("class"); - if (iter != map.end()) - className = iter->second.asString(); - - iter = map.find("package"); - if (iter != map.end()) - packageName = iter->second.asString(); - - Query query(QUERY_OBJECT, className, packageName); - - iter = map.find("where"); - if (iter != map.end()) - query.setPredicate(iter->second.asList()); - - return query; -} - - -void AgentImpl::sendQuery(const Query& query, uint32_t correlator) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_REQUEST; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_QUERY_REQUEST; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - msg.setReplyTo(session.replyAddress); - msg.setCorrelationId(boost::lexical_cast<string>(correlator)); - msg.setSubject(directSubject); - string userId(session.connection.getAuthenticatedUsername()); - if (!userId.empty()) - msg.setUserId(userId); - encode(QueryImplAccess::get(query).asMap(), msg); - if (sender.isValid()) { - sender.send(msg); - QPID_LOG(trace, "SENT QueryRequest to=" << sender.getName() << "/" << directSubject << " cid=" << correlator); - } -} - - -void AgentImpl::sendMethod(const string& method, const Variant::Map& args, const DataAddr& addr, uint32_t correlator) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_REQUEST; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_METHOD_REQUEST; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - map["_method_name"] = method; - map["_object_id"] = addr.asMap(); - map["_arguments"] = args; - - msg.setReplyTo(session.replyAddress); - msg.setCorrelationId(boost::lexical_cast<string>(correlator)); - msg.setSubject(directSubject); - string userId(session.connection.getAuthenticatedUsername()); - if (!userId.empty()) - msg.setUserId(userId); - encode(map, msg); - if (sender.isValid()) { - sender.send(msg); - QPID_LOG(trace, "SENT MethodRequest method=" << method << " to=" << sender.getName() << "/" << directSubject << " content=" << map << " cid=" << correlator); - } -} - -void AgentImpl::sendSchemaRequest(const SchemaId& id) -{ - uint32_t correlator; - - { - qpid::sys::Mutex::ScopedLock l(lock); - correlator = nextCorrelator++; - } - - if (capability >= AGENT_CAPABILITY_V2_SCHEMA) { - Query query(QUERY_SCHEMA, id); - sendQuery(query, correlator); - return; - } - -#define RAW_BUFFER_SIZE 1024 - char rawBuffer[RAW_BUFFER_SIZE]; - qpid::management::Buffer buffer(rawBuffer, RAW_BUFFER_SIZE); - - buffer.putOctet('A'); - buffer.putOctet('M'); - buffer.putOctet('2'); - buffer.putOctet('S'); - buffer.putLong(correlator); - buffer.putShortString(id.getPackageName()); - buffer.putShortString(id.getName()); - buffer.putBin128(id.getHash().data()); - - string content(rawBuffer, buffer.getPosition()); - - Message msg; - msg.setReplyTo(session.replyAddress); - msg.setContent(content); - msg.setSubject(directSubject); - string userId(session.connection.getAuthenticatedUsername()); - if (!userId.empty()) - msg.setUserId(userId); - if (sender.isValid()) { - sender.send(msg); - QPID_LOG(trace, "SENT V1SchemaRequest to=" << sender.getName() << "/" << directSubject); - } -} - - -void AgentImpl::learnSchemaId(const SchemaId& id) -{ - schemaCache->declareSchemaId(id); - schemaIdSet.insert(id); -} - - -AgentImpl& AgentImplAccess::get(Agent& item) -{ - return *item.impl; -} - - -const AgentImpl& AgentImplAccess::get(const Agent& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/AgentEvent.cpp b/cpp/src/qmf/AgentEvent.cpp deleted file mode 100644 index 2dc24ecac1..0000000000 --- a/cpp/src/qmf/AgentEvent.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/AgentEventImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/SchemaImpl.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef<AgentEvent> PI; - -AgentEvent::AgentEvent(AgentEventImpl* impl) { PI::ctor(*this, impl); } -AgentEvent::AgentEvent(const AgentEvent& s) : qmf::Handle<AgentEventImpl>() { PI::copy(*this, s); } -AgentEvent::~AgentEvent() { PI::dtor(*this); } -AgentEvent& AgentEvent::operator=(const AgentEvent& s) { return PI::assign(*this, s); } - -AgentEventCode AgentEvent::getType() const { return impl->getType(); } -const string& AgentEvent::getUserId() const { return impl->getUserId(); } -Query AgentEvent::getQuery() const { return impl->getQuery(); } -bool AgentEvent::hasDataAddr() const { return impl->hasDataAddr(); } -DataAddr AgentEvent::getDataAddr() const { return impl->getDataAddr(); } -const string& AgentEvent::getMethodName() const { return impl->getMethodName(); } -qpid::types::Variant::Map& AgentEvent::getArguments() { return impl->getArguments(); } -qpid::types::Variant::Map& AgentEvent::getArgumentSubtypes() { return impl->getArgumentSubtypes(); } -void AgentEvent::addReturnArgument(const std::string& k, const qpid::types::Variant& v, const std::string& s) { impl->addReturnArgument(k, v, s); } - -uint32_t AgentEventImpl::enqueueData(const Data& data) -{ - qpid::sys::Mutex::ScopedLock l(lock); - dataQueue.push(data); - return dataQueue.size(); -} - - -Data AgentEventImpl::dequeueData() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (dataQueue.empty()) - return Data(); - Data data(dataQueue.front()); - dataQueue.pop(); - return data; -} - - -void AgentEventImpl::addReturnArgument(const string& key, const Variant& val, const string& subtype) -{ - if (schema.isValid() && !SchemaImplAccess::get(schema).isValidMethodOutArg(methodName, key, val)) - throw QmfException("Output argument is unknown or the type is incompatible"); - outArguments[key] = val; - if (!subtype.empty()) - outArgumentSubtypes[key] = subtype; -} - - -AgentEventImpl& AgentEventImplAccess::get(AgentEvent& item) -{ - return *item.impl; -} - - -const AgentEventImpl& AgentEventImplAccess::get(const AgentEvent& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/AgentEventImpl.h b/cpp/src/qmf/AgentEventImpl.h deleted file mode 100644 index 1ecb41775a..0000000000 --- a/cpp/src/qmf/AgentEventImpl.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef _QMF_AGENT_EVENT_IMPL_H_ -#define _QMF_AGENT_EVENT_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/messaging/Address.h" -#include "qmf/AgentEvent.h" -#include "qmf/Query.h" -#include "qmf/DataAddr.h" -#include "qmf/Data.h" -#include "qmf/Schema.h" -#include <queue> - -namespace qmf { - class AgentEventImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only methods - // - AgentEventImpl(AgentEventCode e) : eventType(e) {} - void setUserId(const std::string& u) { userId = u; } - void setQuery(const Query& q) { query = q; } - void setDataAddr(const DataAddr& d) { dataAddr = d; } - void setMethodName(const std::string& m) { methodName = m; } - void setArguments(const qpid::types::Variant::Map& a) { arguments = a; } - void setArgumentSubtypes(const qpid::types::Variant::Map& a) { argumentSubtypes = a; } - void setReplyTo(const qpid::messaging::Address& r) { replyTo = r; } - void setSchema(const Schema& s) { schema = s; } - const qpid::messaging::Address& getReplyTo() { return replyTo; } - void setCorrelationId(const std::string& c) { correlationId = c; } - const std::string& getCorrelationId() { return correlationId; } - const qpid::types::Variant::Map& getReturnArguments() const { return outArguments; } - const qpid::types::Variant::Map& getReturnArgumentSubtypes() const { return outArgumentSubtypes; } - uint32_t enqueueData(const Data&); - Data dequeueData(); - - // - // Methods from API handle - // - AgentEventCode getType() const { return eventType; } - const std::string& getUserId() const { return userId; } - Query getQuery() const { return query; } - bool hasDataAddr() const { return dataAddr.isValid(); } - DataAddr getDataAddr() const { return dataAddr; } - const std::string& getMethodName() const { return methodName; } - qpid::types::Variant::Map& getArguments() { return arguments; } - qpid::types::Variant::Map& getArgumentSubtypes() { return argumentSubtypes; } - void addReturnArgument(const std::string&, const qpid::types::Variant&, const std::string&); - - private: - const AgentEventCode eventType; - std::string userId; - qpid::messaging::Address replyTo; - std::string correlationId; - Query query; - DataAddr dataAddr; - Schema schema; - std::string methodName; - qpid::types::Variant::Map arguments; - qpid::types::Variant::Map argumentSubtypes; - qpid::types::Variant::Map outArguments; - qpid::types::Variant::Map outArgumentSubtypes; - - qpid::sys::Mutex lock; - std::queue<Data> dataQueue; - }; - - struct AgentEventImplAccess - { - static AgentEventImpl& get(AgentEvent&); - static const AgentEventImpl& get(const AgentEvent&); - }; -} - -#endif diff --git a/cpp/src/qmf/AgentImpl.h b/cpp/src/qmf/AgentImpl.h deleted file mode 100644 index 7fa4f4373a..0000000000 --- a/cpp/src/qmf/AgentImpl.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef _QMF_AGENT_IMPL_H_ -#define _QMF_AGENT_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/Agent.h" -#include "qmf/ConsoleEventImpl.h" -#include "qmf/ConsoleSessionImpl.h" -#include "qmf/QueryImpl.h" -#include "qmf/SchemaCache.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Sender.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Condition.h" -#include <boost/shared_ptr.hpp> -#include <map> -#include <set> - -namespace qmf { - class AgentImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only methods - // - AgentImpl(const std::string& n, uint32_t e, ConsoleSessionImpl& s); - void setAttribute(const std::string& k, const qpid::types::Variant& v); - void setAttribute(const std::string& k, const std::string& v) { attributes[k] = v; } - void touch() { touched = true; } - uint32_t age() { untouchedCount = touched ? 0 : untouchedCount + 1; touched = false; return untouchedCount; } - uint32_t getCapability() const { return capability; } - void handleException(const qpid::types::Variant::Map&, const qpid::messaging::Message&); - void handleMethodResponse(const qpid::types::Variant::Map&, const qpid::messaging::Message&); - void handleDataIndication(const qpid::types::Variant::List&, const qpid::messaging::Message&); - void handleQueryResponse(const qpid::types::Variant::List&, const qpid::messaging::Message&); - - // - // Methods from API handle - // - const std::string& getName() const { return name; } - uint32_t getEpoch() const { return epoch; } - void setEpoch(uint32_t e) { epoch = e; } - std::string getVendor() const { return getAttribute("_vendor").asString(); } - std::string getProduct() const { return getAttribute("_product").asString(); } - std::string getInstance() const { return getAttribute("_instance").asString(); } - const qpid::types::Variant& getAttribute(const std::string& k) const; - const qpid::types::Variant::Map& getAttributes() const { return attributes; } - - ConsoleEvent querySchema(qpid::messaging::Duration t) { return query(Query(QUERY_SCHEMA_ID), t); } - uint32_t querySchemaAsync() { return queryAsync(Query(QUERY_SCHEMA_ID)); } - - ConsoleEvent query(const Query& q, qpid::messaging::Duration t); - ConsoleEvent query(const std::string& q, qpid::messaging::Duration t); - uint32_t queryAsync(const Query& q); - uint32_t queryAsync(const std::string& q); - - ConsoleEvent callMethod(const std::string& m, const qpid::types::Variant::Map& a, const DataAddr&, qpid::messaging::Duration t); - uint32_t callMethodAsync(const std::string& m, const qpid::types::Variant::Map& a, const DataAddr&); - - uint32_t getPackageCount() const; - const std::string& getPackage(uint32_t i) const; - uint32_t getSchemaIdCount(const std::string& p) const; - SchemaId getSchemaId(const std::string& p, uint32_t i) const; - Schema getSchema(const SchemaId& s, qpid::messaging::Duration t); - - private: - struct SyncContext { - qpid::sys::Mutex lock; - qpid::sys::Condition cond; - ConsoleEvent response; - }; - - mutable qpid::sys::Mutex lock; - std::string name; - std::string directSubject; - uint32_t epoch; - ConsoleSessionImpl& session; - bool touched; - uint32_t untouchedCount; - uint32_t capability; - qpid::messaging::Sender sender; - qpid::types::Variant::Map attributes; - uint32_t nextCorrelator; - std::map<uint32_t, boost::shared_ptr<SyncContext> > contextMap; - boost::shared_ptr<SchemaCache> schemaCache; - mutable std::set<std::string> packageSet; - std::set<SchemaId, SchemaIdCompare> schemaIdSet; - - Query stringToQuery(const std::string&); - void sendQuery(const Query&, uint32_t); - void sendSchemaIdQuery(uint32_t); - void sendMethod(const std::string&, const qpid::types::Variant::Map&, const DataAddr&, uint32_t); - void sendSchemaRequest(const SchemaId&); - void learnSchemaId(const SchemaId&); - }; - - struct AgentImplAccess - { - static AgentImpl& get(Agent&); - static const AgentImpl& get(const Agent&); - }; -} - -#endif diff --git a/cpp/src/qmf/AgentSession.cpp b/cpp/src/qmf/AgentSession.cpp deleted file mode 100644 index 71d369325f..0000000000 --- a/cpp/src/qmf/AgentSession.cpp +++ /dev/null @@ -1,1072 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/AgentSession.h" -#include "qmf/AgentEventImpl.h" -#include "qmf/SchemaIdImpl.h" -#include "qmf/SchemaImpl.h" -#include "qmf/DataAddrImpl.h" -#include "qmf/DataImpl.h" -#include "qmf/QueryImpl.h" -#include "qmf/agentCapability.h" -#include "qmf/constants.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Condition.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/management/Buffer.h" -#include <queue> -#include <map> -#include <set> -#include <iostream> -#include <memory> - -using namespace std; -using namespace qpid::messaging; -using namespace qmf; -using qpid::types::Variant; - -namespace qmf { - class AgentSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable { - public: - ~AgentSessionImpl(); - - // - // Methods from API handle - // - AgentSessionImpl(Connection& c, const string& o); - void setDomain(const string& d) { checkOpen(); domain = d; } - void setVendor(const string& v) { checkOpen(); attributes["_vendor"] = v; } - void setProduct(const string& p) { checkOpen(); attributes["_product"] = p; } - void setInstance(const string& i) { checkOpen(); attributes["_instance"] = i; } - void setAttribute(const string& k, const qpid::types::Variant& v) { checkOpen(); attributes[k] = v; } - const string& getName() const { return agentName; } - void open(); - void close(); - bool nextEvent(AgentEvent& e, Duration t); - int pendingEvents() const; - - void registerSchema(Schema& s); - DataAddr addData(Data& d, const string& n, bool persist); - void delData(const DataAddr&); - - void authAccept(AgentEvent& e); - void authReject(AgentEvent& e, const string& m); - void raiseException(AgentEvent& e, const string& s); - void raiseException(AgentEvent& e, const Data& d); - void response(AgentEvent& e, const Data& d); - void complete(AgentEvent& e); - void methodSuccess(AgentEvent& e); - void raiseEvent(const Data& d); - void raiseEvent(const Data& d, int s); - - private: - typedef map<DataAddr, Data, DataAddrCompare> DataIndex; - typedef map<SchemaId, Schema, SchemaIdCompare> SchemaMap; - - mutable qpid::sys::Mutex lock; - qpid::sys::Condition cond; - Connection connection; - Session session; - Sender directSender; - Sender topicSender; - string domain; - Variant::Map attributes; - Variant::Map options; - string agentName; - bool opened; - queue<AgentEvent> eventQueue; - qpid::sys::Thread* thread; - bool threadCanceled; - uint32_t bootSequence; - uint32_t interval; - uint64_t lastHeartbeat; - uint64_t lastVisit; - bool forceHeartbeat; - bool externalStorage; - bool autoAllowQueries; - bool autoAllowMethods; - uint32_t maxSubscriptions; - uint32_t minSubInterval; - uint32_t subLifetime; - bool publicEvents; - bool listenOnDirect; - bool strictSecurity; - uint64_t schemaUpdateTime; - string directBase; - string topicBase; - - SchemaMap schemata; - DataIndex globalIndex; - map<SchemaId, DataIndex, SchemaIdCompareNoHash> schemaIndex; - - void checkOpen(); - void setAgentName(); - void enqueueEvent(const AgentEvent&); - void handleLocateRequest(const Variant::List& content, const Message& msg); - void handleMethodRequest(const Variant::Map& content, const Message& msg); - void handleQueryRequest(const Variant::Map& content, const Message& msg); - void handleSchemaRequest(AgentEvent&); - void handleV1SchemaRequest(qpid::management::Buffer&, uint32_t, const Message&); - void dispatch(Message); - void sendHeartbeat(); - void send(Message, const Address&); - void flushResponses(AgentEvent&, bool); - void periodicProcessing(uint64_t); - void run(); - }; -} - -typedef qmf::PrivateImplRef<AgentSession> PI; - -AgentSession::AgentSession(AgentSessionImpl* impl) { PI::ctor(*this, impl); } -AgentSession::AgentSession(const AgentSession& s) : qmf::Handle<AgentSessionImpl>() { PI::copy(*this, s); } -AgentSession::~AgentSession() { PI::dtor(*this); } -AgentSession& AgentSession::operator=(const AgentSession& s) { return PI::assign(*this, s); } - -AgentSession::AgentSession(Connection& c, const string& o) { PI::ctor(*this, new AgentSessionImpl(c, o)); } -void AgentSession::setDomain(const string& d) { impl->setDomain(d); } -void AgentSession::setVendor(const string& v) { impl->setVendor(v); } -void AgentSession::setProduct(const string& p) { impl->setProduct(p); } -void AgentSession::setInstance(const string& i) { impl->setInstance(i); } -void AgentSession::setAttribute(const string& k, const qpid::types::Variant& v) { impl->setAttribute(k, v); } -const string& AgentSession::getName() const { return impl->getName(); } -void AgentSession::open() { impl->open(); } -void AgentSession::close() { impl->close(); } -bool AgentSession::nextEvent(AgentEvent& e, Duration t) { return impl->nextEvent(e, t); } -int AgentSession::pendingEvents() const { return impl->pendingEvents(); } -void AgentSession::registerSchema(Schema& s) { impl->registerSchema(s); } -DataAddr AgentSession::addData(Data& d, const string& n, bool p) { return impl->addData(d, n, p); } -void AgentSession::delData(const DataAddr& a) { impl->delData(a); } -void AgentSession::authAccept(AgentEvent& e) { impl->authAccept(e); } -void AgentSession::authReject(AgentEvent& e, const string& m) { impl->authReject(e, m); } -void AgentSession::raiseException(AgentEvent& e, const string& s) { impl->raiseException(e, s); } -void AgentSession::raiseException(AgentEvent& e, const Data& d) { impl->raiseException(e, d); } -void AgentSession::response(AgentEvent& e, const Data& d) { impl->response(e, d); } -void AgentSession::complete(AgentEvent& e) { impl->complete(e); } -void AgentSession::methodSuccess(AgentEvent& e) { impl->methodSuccess(e); } -void AgentSession::raiseEvent(const Data& d) { impl->raiseEvent(d); } -void AgentSession::raiseEvent(const Data& d, int s) { impl->raiseEvent(d, s); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -AgentSessionImpl::AgentSessionImpl(Connection& c, const string& options) : - connection(c), domain("default"), opened(false), thread(0), threadCanceled(false), - bootSequence(1), interval(60), lastHeartbeat(0), lastVisit(0), forceHeartbeat(false), - externalStorage(false), autoAllowQueries(true), autoAllowMethods(true), - maxSubscriptions(64), minSubInterval(3000), subLifetime(300), publicEvents(true), - listenOnDirect(true), strictSecurity(false), - schemaUpdateTime(uint64_t(qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now()))) -{ - // - // Set Agent Capability Level - // - attributes["qmf.agent_capability"] = AGENT_CAPABILITY_0_8; - - if (!options.empty()) { - qpid::messaging::AddressParser parser(options); - Variant::Map optMap; - Variant::Map::const_iterator iter; - - parser.parseMap(optMap); - - iter = optMap.find("domain"); - if (iter != optMap.end()) - domain = iter->second.asString(); - - iter = optMap.find("interval"); - if (iter != optMap.end()) { - interval = iter->second.asUint32(); - if (interval < 1) - interval = 1; - } - - iter = optMap.find("external"); - if (iter != optMap.end()) - externalStorage = iter->second.asBool(); - - iter = optMap.find("allow-queries"); - if (iter != optMap.end()) - autoAllowQueries = iter->second.asBool(); - - iter = optMap.find("allow-methods"); - if (iter != optMap.end()) - autoAllowMethods = iter->second.asBool(); - - iter = optMap.find("max-subscriptions"); - if (iter != optMap.end()) - maxSubscriptions = iter->second.asUint32(); - - iter = optMap.find("min-sub-interval"); - if (iter != optMap.end()) - minSubInterval = iter->second.asUint32(); - - iter = optMap.find("sub-lifetime"); - if (iter != optMap.end()) - subLifetime = iter->second.asUint32(); - - iter = optMap.find("public-events"); - if (iter != optMap.end()) - publicEvents = iter->second.asBool(); - - iter = optMap.find("listen-on-direct"); - if (iter != optMap.end()) - listenOnDirect = iter->second.asBool(); - - iter = optMap.find("strict-security"); - if (iter != optMap.end()) - strictSecurity = iter->second.asBool(); - } -} - - -AgentSessionImpl::~AgentSessionImpl() -{ - if (opened) - close(); -} - - -void AgentSessionImpl::open() -{ - if (opened) - throw QmfException("The session is already open"); - - const string addrArgs(";{create:never,node:{type:topic}}"); - const string routableAddr("direct-agent.route." + qpid::types::Uuid(true).str()); - attributes["_direct_subject"] = routableAddr; - - // Establish messaging addresses - setAgentName(); - directBase = "qmf." + domain + ".direct"; - topicBase = "qmf." + domain + ".topic"; - - // Create AMQP session, receivers, and senders - session = connection.createSession(); - Receiver directRx; - Receiver routableDirectRx = session.createReceiver(topicBase + "/" + routableAddr + addrArgs); - Receiver topicRx = session.createReceiver(topicBase + "/console.#" + addrArgs); - - if (listenOnDirect && !strictSecurity) { - directRx = session.createReceiver(directBase + "/" + agentName + addrArgs); - directRx.setCapacity(64); - } - - routableDirectRx.setCapacity(64); - topicRx.setCapacity(64); - - if (!strictSecurity) - directSender = session.createSender(directBase + addrArgs); - topicSender = session.createSender(topicBase + addrArgs); - - // Start the receiver thread - threadCanceled = false; - opened = true; - thread = new qpid::sys::Thread(*this); - - // Send an initial agent heartbeat message - sendHeartbeat(); -} - - -void AgentSessionImpl::close() -{ - if (!opened) - return; - - // Stop and join the receiver thread - threadCanceled = true; - thread->join(); - delete thread; - - // Close the AMQP session - session.close(); - opened = false; -} - - -bool AgentSessionImpl::nextEvent(AgentEvent& event, Duration timeout) -{ - uint64_t milliseconds = timeout.getMilliseconds(); - qpid::sys::Mutex::ScopedLock l(lock); - - if (eventQueue.empty() && milliseconds > 0) - cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(), - qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC))); - - if (!eventQueue.empty()) { - event = eventQueue.front(); - eventQueue.pop(); - return true; - } - - return false; -} - - -int AgentSessionImpl::pendingEvents() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return eventQueue.size(); -} - - -void AgentSessionImpl::registerSchema(Schema& schema) -{ - if (!schema.isFinalized()) - schema.finalize(); - const SchemaId& schemaId(schema.getSchemaId()); - - qpid::sys::Mutex::ScopedLock l(lock); - schemata[schemaId] = schema; - schemaIndex[schemaId] = DataIndex(); - - // - // Get the news out at the next periodic interval that there is new schema information. - // - schemaUpdateTime = uint64_t(qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now())); - forceHeartbeat = true; -} - - -DataAddr AgentSessionImpl::addData(Data& data, const string& name, bool persistent) -{ - if (externalStorage) - throw QmfException("addData() must not be called when the 'external' option is enabled."); - - string dataName; - if (name.empty()) - dataName = qpid::types::Uuid(true).str(); - else - dataName = name; - - DataAddr addr(dataName, agentName, persistent ? 0 : bootSequence); - data.setAddr(addr); - - { - qpid::sys::Mutex::ScopedLock l(lock); - DataIndex::const_iterator iter = globalIndex.find(addr); - if (iter != globalIndex.end()) - throw QmfException("Duplicate Data Address"); - - globalIndex[addr] = data; - if (data.hasSchema()) - schemaIndex[data.getSchemaId()][addr] = data; - } - - // - // TODO: Survey active subscriptions to see if they need to hear about this new data. - // - - return addr; -} - - -void AgentSessionImpl::delData(const DataAddr& addr) -{ - { - qpid::sys::Mutex::ScopedLock l(lock); - DataIndex::iterator iter = globalIndex.find(addr); - if (iter == globalIndex.end()) - return; - if (iter->second.hasSchema()) { - const SchemaId& schemaId(iter->second.getSchemaId()); - schemaIndex[schemaId].erase(addr); - } - globalIndex.erase(iter); - } - - // - // TODO: Survey active subscriptions to see if they need to hear about this deleted data. - // -} - - -void AgentSessionImpl::authAccept(AgentEvent& authEvent) -{ - auto_ptr<AgentEventImpl> eventImpl(new AgentEventImpl(AGENT_QUERY)); - eventImpl->setQuery(authEvent.getQuery()); - eventImpl->setUserId(authEvent.getUserId()); - eventImpl->setReplyTo(AgentEventImplAccess::get(authEvent).getReplyTo()); - eventImpl->setCorrelationId(AgentEventImplAccess::get(authEvent).getCorrelationId()); - AgentEvent event(eventImpl.release()); - - if (externalStorage) { - enqueueEvent(event); - return; - } - - const Query& query(authEvent.getQuery()); - if (query.getDataAddr().isValid()) { - { - qpid::sys::Mutex::ScopedLock l(lock); - DataIndex::const_iterator iter = globalIndex.find(query.getDataAddr()); - if (iter != globalIndex.end()) - response(event, iter->second); - } - complete(event); - return; - } - - if (query.getSchemaId().isValid()) { - { - qpid::sys::Mutex::ScopedLock l(lock); - map<SchemaId, DataIndex>::const_iterator iter = schemaIndex.find(query.getSchemaId()); - if (iter != schemaIndex.end()) - for (DataIndex::const_iterator dIter = iter->second.begin(); dIter != iter->second.end(); dIter++) - if (query.matchesPredicate(dIter->second.getProperties())) - response(event, dIter->second); - } - complete(event); - return; - } - - raiseException(event, "Query is Invalid"); -} - - -void AgentSessionImpl::authReject(AgentEvent& event, const string& error) -{ - raiseException(event, "Action Forbidden - " + error); -} - - -void AgentSessionImpl::raiseException(AgentEvent& event, const string& error) -{ - Data exception(new DataImpl()); - exception.setProperty("error_text", error); - raiseException(event, exception); -} - - -void AgentSessionImpl::raiseException(AgentEvent& event, const Data& data) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_EXCEPTION; - headers[protocol::HEADER_KEY_CONTENT] = protocol::HEADER_CONTENT_DATA; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - AgentEventImpl& eventImpl(AgentEventImplAccess::get(event)); - const DataImpl& dataImpl(DataImplAccess::get(data)); - - msg.setCorrelationId(eventImpl.getCorrelationId()); - encode(dataImpl.asMap(), msg); - send(msg, eventImpl.getReplyTo()); - - QPID_LOG(trace, "SENT Exception to=" << eventImpl.getReplyTo()); -} - - -void AgentSessionImpl::response(AgentEvent& event, const Data& data) -{ - AgentEventImpl& impl(AgentEventImplAccess::get(event)); - uint32_t count = impl.enqueueData(data); - if (count >= 8) - flushResponses(event, false); -} - - -void AgentSessionImpl::complete(AgentEvent& event) -{ - flushResponses(event, true); -} - - -void AgentSessionImpl::methodSuccess(AgentEvent& event) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - AgentEventImpl& eventImpl(AgentEventImplAccess::get(event)); - - const Variant::Map& outArgs(eventImpl.getReturnArguments()); - const Variant::Map& outSubtypes(eventImpl.getReturnArgumentSubtypes()); - - map["_arguments"] = outArgs; - if (!outSubtypes.empty()) - map["_subtypes"] = outSubtypes; - - msg.setCorrelationId(eventImpl.getCorrelationId()); - encode(map, msg); - send(msg, eventImpl.getReplyTo()); - - QPID_LOG(trace, "SENT MethodResponse to=" << eventImpl.getReplyTo()); -} - - -void AgentSessionImpl::raiseEvent(const Data& data) -{ - int severity(SEV_NOTICE); - if (data.hasSchema()) { - const Schema& schema(DataImplAccess::get(data).getSchema()); - if (schema.isValid()) - severity = schema.getDefaultSeverity(); - } - - raiseEvent(data, severity); -} - - -void AgentSessionImpl::raiseEvent(const Data& data, int severity) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - string subject("agent.ind.event"); - - if (data.hasSchema()) { - const SchemaId& schemaId(data.getSchemaId()); - if (schemaId.getType() != SCHEMA_TYPE_EVENT) - throw QmfException("Cannot call raiseEvent on data that is not an Event"); - subject = subject + "." + schemaId.getPackageName() + "." + schemaId.getName(); - } - - if (severity < SEV_EMERG || severity > SEV_DEBUG) - throw QmfException("Invalid severity value"); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_INDICATION; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_DATA_INDICATION; - headers[protocol::HEADER_KEY_CONTENT] = protocol::HEADER_CONTENT_EVENT; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - msg.setSubject(subject); - - Variant::List list; - Variant::Map dataAsMap(DataImplAccess::get(data).asMap()); - dataAsMap["_severity"] = severity; - dataAsMap["_timestamp"] = uint64_t(qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now())); - list.push_back(dataAsMap); - encode(list, msg); - topicSender.send(msg); - - QPID_LOG(trace, "SENT EventIndication to=" << topicSender.getName() << "/" << subject); -} - - -void AgentSessionImpl::checkOpen() -{ - if (opened) - throw QmfException("Operation must be performed before calling open()"); -} - - -void AgentSessionImpl::enqueueEvent(const AgentEvent& event) -{ - qpid::sys::Mutex::ScopedLock l(lock); - bool notify = eventQueue.empty(); - eventQueue.push(event); - if (notify) - cond.notify(); -} - - -void AgentSessionImpl::setAgentName() -{ - Variant::Map::iterator iter; - string vendor; - string product; - string instance; - - iter = attributes.find("_vendor"); - if (iter == attributes.end()) - attributes["_vendor"] = vendor; - else - vendor = iter->second.asString(); - - iter = attributes.find("_product"); - if (iter == attributes.end()) - attributes["_product"] = product; - else - product = iter->second.asString(); - - iter = attributes.find("_instance"); - if (iter == attributes.end()) { - instance = qpid::types::Uuid(true).str(); - attributes["_instance"] = instance; - } else - instance = iter->second.asString(); - - agentName = vendor + ":" + product + ":" + instance; - attributes["_name"] = agentName; -} - - -void AgentSessionImpl::handleLocateRequest(const Variant::List& predicate, const Message& msg) -{ - QPID_LOG(trace, "RCVD AgentLocateRequest from=" << msg.getReplyTo()); - - if (!predicate.empty()) { - Query agentQuery(QUERY_OBJECT); - agentQuery.setPredicate(predicate); - if (!agentQuery.matchesPredicate(attributes)) { - QPID_LOG(trace, "AgentLocate predicate does not match this agent, ignoring"); - return; - } - } - - Message reply; - Variant::Map map; - Variant::Map& headers(reply.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_INDICATION; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_AGENT_LOCATE_RESPONSE; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - map["_values"] = attributes; - map["_values"].asMap()[protocol::AGENT_ATTR_TIMESTAMP] = uint64_t(qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now())); - map["_values"].asMap()[protocol::AGENT_ATTR_HEARTBEAT_INTERVAL] = interval; - map["_values"].asMap()[protocol::AGENT_ATTR_EPOCH] = bootSequence; - map["_values"].asMap()[protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP] = schemaUpdateTime; - - encode(map, reply); - send(reply, msg.getReplyTo()); - QPID_LOG(trace, "SENT AgentLocateResponse to=" << msg.getReplyTo()); -} - - -void AgentSessionImpl::handleMethodRequest(const Variant::Map& content, const Message& msg) -{ - QPID_LOG(trace, "RCVD MethodRequest map=" << content << " from=" << msg.getReplyTo() << " cid=" << msg.getCorrelationId()); - - // - // Construct an AgentEvent to be sent to the application. - // - auto_ptr<AgentEventImpl> eventImpl(new AgentEventImpl(AGENT_METHOD)); - eventImpl->setUserId(msg.getUserId()); - eventImpl->setReplyTo(msg.getReplyTo()); - eventImpl->setCorrelationId(msg.getCorrelationId()); - - Variant::Map::const_iterator iter; - - iter = content.find("_method_name"); - if (iter == content.end()) { - AgentEvent event(eventImpl.release()); - raiseException(event, "Malformed MethodRequest: missing _method_name field"); - return; - } - eventImpl->setMethodName(iter->second.asString()); - - iter = content.find("_arguments"); - if (iter != content.end()) - eventImpl->setArguments(iter->second.asMap()); - - iter = content.find("_subtypes"); - if (iter != content.end()) - eventImpl->setArgumentSubtypes(iter->second.asMap()); - - iter = content.find("_object_id"); - if (iter != content.end()) { - DataAddr addr(new DataAddrImpl(iter->second.asMap())); - eventImpl->setDataAddr(addr); - DataIndex::const_iterator iter(globalIndex.find(addr)); - if (iter == globalIndex.end()) { - AgentEvent event(eventImpl.release()); - raiseException(event, "No data object found with the specified address"); - return; - } - - const Schema& schema(DataImplAccess::get(iter->second).getSchema()); - if (schema.isValid()) { - eventImpl->setSchema(schema); - for (Variant::Map::const_iterator aIter = eventImpl->getArguments().begin(); - aIter != eventImpl->getArguments().end(); aIter++) { - const Schema& schema(DataImplAccess::get(iter->second).getSchema()); - if (!SchemaImplAccess::get(schema).isValidMethodInArg(eventImpl->getMethodName(), aIter->first, aIter->second)) { - AgentEvent event(eventImpl.release()); - raiseException(event, "Invalid argument: " + aIter->first); - return; - } - } - } - } - - enqueueEvent(AgentEvent(eventImpl.release())); -} - - -void AgentSessionImpl::handleQueryRequest(const Variant::Map& content, const Message& msg) -{ - QPID_LOG(trace, "RCVD QueryRequest query=" << content << " from=" << msg.getReplyTo() << " cid=" << msg.getCorrelationId()); - - // - // Construct an AgentEvent to be sent to the application or directly handled by the agent. - // - auto_ptr<QueryImpl> queryImpl(new QueryImpl(content)); - auto_ptr<AgentEventImpl> eventImpl(new AgentEventImpl(AGENT_AUTH_QUERY)); - eventImpl->setUserId(msg.getUserId()); - eventImpl->setReplyTo(msg.getReplyTo()); - eventImpl->setCorrelationId(msg.getCorrelationId()); - eventImpl->setQuery(queryImpl.release()); - AgentEvent ae(eventImpl.release()); - - if (ae.getQuery().getTarget() == QUERY_SCHEMA_ID || ae.getQuery().getTarget() == QUERY_SCHEMA) { - handleSchemaRequest(ae); - return; - } - - if (autoAllowQueries) - authAccept(ae); - else - enqueueEvent(ae); -} - - -void AgentSessionImpl::handleSchemaRequest(AgentEvent& event) -{ - SchemaMap::const_iterator iter; - string error; - const Query& query(event.getQuery()); - - Message msg; - Variant::List content; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_QUERY_RESPONSE; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - { - qpid::sys::Mutex::ScopedLock l(lock); - if (query.getTarget() == QUERY_SCHEMA_ID) { - headers[protocol::HEADER_KEY_CONTENT] = "_schema_id"; - for (iter = schemata.begin(); iter != schemata.end(); iter++) - content.push_back(SchemaIdImplAccess::get(iter->first).asMap()); - } else if (query.getSchemaId().isValid()) { - headers[protocol::HEADER_KEY_CONTENT] = "_schema"; - iter = schemata.find(query.getSchemaId()); - if (iter != schemata.end()) - content.push_back(SchemaImplAccess::get(iter->second).asMap()); - } else { - error = "Invalid Schema Query: Requests for SCHEMA must supply a valid schema ID."; - } - } - - if (!error.empty()) { - raiseException(event, error); - return; - } - - AgentEventImpl& eventImpl(AgentEventImplAccess::get(event)); - - msg.setCorrelationId(eventImpl.getCorrelationId()); - encode(content, msg); - send(msg, eventImpl.getReplyTo()); - - QPID_LOG(trace, "SENT QueryResponse(Schema) to=" << eventImpl.getReplyTo()); -} - - -void AgentSessionImpl::handleV1SchemaRequest(qpid::management::Buffer& buffer, uint32_t seq, const Message& msg) -{ - string packageName; - string className; - uint8_t hashBits[16]; - - buffer.getShortString(packageName); - buffer.getShortString(className); - buffer.getBin128(hashBits); - - QPID_LOG(trace, "RCVD QMFv1 SchemaRequest for " << packageName << ":" << className); - - qpid::types::Uuid hash(hashBits); - map<SchemaId, Schema>::const_iterator iter; - string replyContent; - - SchemaId dataId(SCHEMA_TYPE_DATA, packageName, className); - dataId.setHash(hash); - - { - qpid::sys::Mutex::ScopedLock l(lock); - iter = schemata.find(dataId); - if (iter != schemata.end()) - replyContent = SchemaImplAccess::get(iter->second).asV1Content(seq); - else { - SchemaId eventId(SCHEMA_TYPE_EVENT, packageName, className); - eventId.setHash(hash); - iter = schemata.find(dataId); - if (iter != schemata.end()) - replyContent = SchemaImplAccess::get(iter->second).asV1Content(seq); - else - return; - } - } - - Message reply; - Variant::Map& headers(reply.getProperties()); - - headers[protocol::HEADER_KEY_AGENT] = agentName; - reply.setContent(replyContent); - - send(reply, msg.getReplyTo()); - QPID_LOG(trace, "SENT QMFv1 SchemaResponse to=" << msg.getReplyTo()); -} - - -void AgentSessionImpl::dispatch(Message msg) -{ - const Variant::Map& properties(msg.getProperties()); - Variant::Map::const_iterator iter; - - // - // If strict-security is enabled, make sure that reply-to address complies with the - // strict-security addressing pattern (i.e. start with 'qmf.<domain>.topic/direct-console.'). - // - if (strictSecurity && msg.getReplyTo()) { - if (msg.getReplyTo().getName() != topicBase || msg.getReplyTo().getSubject().find("direct-console.") != 0) { - QPID_LOG(warning, "Reply-to violates strict-security policy: " << msg.getReplyTo().str()); - return; - } - } - - iter = properties.find(protocol::HEADER_KEY_APP_ID); - if (iter != properties.end() && iter->second.asString() == protocol::HEADER_APP_ID_QMF) { - // - // Dispatch a QMFv2 formatted message - // - iter = properties.find(protocol::HEADER_KEY_OPCODE); - if (iter == properties.end()) { - QPID_LOG(trace, "Message received with no 'qmf.opcode' header"); - return; - } - - const string& opcode = iter->second.asString(); - - if (msg.getContentType() == "amqp/list") { - Variant::List content; - decode(msg, content); - - if (opcode == protocol::HEADER_OPCODE_AGENT_LOCATE_REQUEST) handleLocateRequest(content, msg); - else { - QPID_LOG(trace, "Unexpected QMFv2 opcode with 'amqp/list' content: " << opcode); - } - - } else if (msg.getContentType() == "amqp/map") { - Variant::Map content; - decode(msg, content); - - if (opcode == protocol::HEADER_OPCODE_METHOD_REQUEST) handleMethodRequest(content, msg); - else if (opcode == protocol::HEADER_OPCODE_QUERY_REQUEST) handleQueryRequest(content, msg); - else { - QPID_LOG(trace, "Unexpected QMFv2 opcode with 'amqp/map' content: " << opcode); - } - } else { - QPID_LOG(trace, "Unexpected QMFv2 content type. Expected amqp/list or amqp/map"); - } - - } else { - // - // Dispatch a QMFv1 formatted message - // - const string& body(msg.getContent()); - if (body.size() < 8) - return; - qpid::management::Buffer buffer(const_cast<char*>(body.c_str()), body.size()); - - if (buffer.getOctet() != 'A') return; - if (buffer.getOctet() != 'M') return; - if (buffer.getOctet() != '2') return; - char v1Opcode(buffer.getOctet()); - uint32_t seq(buffer.getLong()); - - if (v1Opcode == 'S') handleV1SchemaRequest(buffer, seq, msg); - else { - QPID_LOG(trace, "Unknown or Unsupported QMFv1 opcode: " << v1Opcode); - } - } -} - - -void AgentSessionImpl::sendHeartbeat() -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - std::stringstream address; - - address << "agent.ind.heartbeat"; - - // append .<vendor>.<product> to address key if present. - Variant::Map::const_iterator v; - if ((v = attributes.find("_vendor")) != attributes.end() && !v->second.getString().empty()) { - address << "." << v->second.getString(); - if ((v = attributes.find("_product")) != attributes.end() && !v->second.getString().empty()) { - address << "." << v->second.getString(); - } - } - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_INDICATION; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_AGENT_HEARTBEAT_INDICATION; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - msg.setSubject(address.str()); - - map["_values"] = attributes; - map["_values"].asMap()[protocol::AGENT_ATTR_TIMESTAMP] = uint64_t(qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now())); - map["_values"].asMap()[protocol::AGENT_ATTR_HEARTBEAT_INTERVAL] = interval; - map["_values"].asMap()[protocol::AGENT_ATTR_EPOCH] = bootSequence; - map["_values"].asMap()[protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP] = schemaUpdateTime; - - encode(map, msg); - topicSender.send(msg); - QPID_LOG(trace, "SENT AgentHeartbeat name=" << agentName); -} - - -void AgentSessionImpl::send(Message msg, const Address& to) -{ - Sender sender; - - if (strictSecurity && to.getName() != topicBase) { - QPID_LOG(warning, "Address violates strict-security policy: " << to); - return; - } - - if (to.getName() == directBase) { - msg.setSubject(to.getSubject()); - sender = directSender; - } else if (to.getName() == topicBase) { - msg.setSubject(to.getSubject()); - sender = topicSender; - } else - sender = session.createSender(to); - - sender.send(msg); -} - - -void AgentSessionImpl::flushResponses(AgentEvent& event, bool final) -{ - Message msg; - Variant::Map map; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_RESPONSE; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_QUERY_RESPONSE; - headers[protocol::HEADER_KEY_CONTENT] = protocol::HEADER_CONTENT_DATA; - headers[protocol::HEADER_KEY_AGENT] = agentName; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - if (!final) - headers[protocol::HEADER_KEY_PARTIAL] = Variant(); - - Variant::List body; - AgentEventImpl& eventImpl(AgentEventImplAccess::get(event)); - Data data(eventImpl.dequeueData()); - while (data.isValid()) { - DataImpl& dataImpl(DataImplAccess::get(data)); - body.push_back(dataImpl.asMap()); - data = eventImpl.dequeueData(); - } - - msg.setCorrelationId(eventImpl.getCorrelationId()); - encode(body, msg); - send(msg, eventImpl.getReplyTo()); - - QPID_LOG(trace, "SENT QueryResponse to=" << eventImpl.getReplyTo()); -} - - -void AgentSessionImpl::periodicProcessing(uint64_t seconds) -{ - // - // The granularity of this timer is seconds. Don't waste time looking for work if - // it's been less than a second since we last visited. - // - if (seconds == lastVisit) - return; - //uint64_t thisInterval(seconds - lastVisit); - lastVisit = seconds; - - // - // First time through, set lastHeartbeat to the current time. - // - if (lastHeartbeat == 0) - lastHeartbeat = seconds; - - // - // If the hearbeat interval has elapsed, send a heartbeat. - // - if (forceHeartbeat || (seconds - lastHeartbeat >= interval)) { - lastHeartbeat = seconds; - forceHeartbeat = false; - sendHeartbeat(); - } - - // - // TODO: process any active subscriptions on their intervals. - // -} - - -void AgentSessionImpl::run() -{ - QPID_LOG(debug, "AgentSession thread started for agent " << agentName); - - try { - while (!threadCanceled) { - periodicProcessing((uint64_t) qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now()) / qpid::sys::TIME_SEC); - - Receiver rx; - bool valid = session.nextReceiver(rx, Duration::SECOND); - if (threadCanceled) - break; - if (valid) { - try { - dispatch(rx.fetch()); - } catch (qpid::types::Exception& e) { - QPID_LOG(error, "Exception caught in message dispatch: " << e.what()); - } - session.acknowledge(); - } - } - } catch (qpid::types::Exception& e) { - QPID_LOG(error, "Exception caught in message thread - exiting: " << e.what()); - enqueueEvent(AgentEvent(new AgentEventImpl(AGENT_THREAD_FAILED))); - } - - QPID_LOG(debug, "AgentSession thread exiting for agent " << agentName); -} - diff --git a/cpp/src/qmf/AgentSubscription.cpp b/cpp/src/qmf/AgentSubscription.cpp deleted file mode 100644 index 4dc5cb74a4..0000000000 --- a/cpp/src/qmf/AgentSubscription.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/AgentSubscription.h" - -using namespace qmf; - -AgentSubscription::AgentSubscription(uint64_t _id, uint64_t _interval, uint64_t _life, - const std::string& _replyTo, const std::string& _cid, Query _query) : - id(_id), interval(_interval), lifetime(_life), timeSincePublish(0), timeSinceKeepalive(0), - replyTo(_replyTo), cid(_cid), query(_query) -{ -} - - -AgentSubscription::~AgentSubscription() -{ -} - - -bool AgentSubscription::tick(uint64_t seconds) -{ - timeSinceKeepalive += seconds; - if (timeSinceKeepalive >= lifetime) - return false; - - timeSincePublish += seconds; - if (timeSincePublish >= interval) { - } - - return true; -} - diff --git a/cpp/src/qmf/AgentSubscription.h b/cpp/src/qmf/AgentSubscription.h deleted file mode 100644 index 01e8f43e9f..0000000000 --- a/cpp/src/qmf/AgentSubscription.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _QMF_AGENT_SUBSCRIPTION_H_ -#define _QMF_AGENT_SUBSCRIPTION_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" -#include "qpid/types/Variant.h" -#include "qmf/Query.h" -#include "qmf/Data.h" -#include <boost/shared_ptr.hpp> - -namespace qmf { - class AgentSubscription { - public: - AgentSubscription(uint64_t _id, uint64_t _interval, uint64_t _life, - const std::string& _replyTo, const std::string& _cid, Query _query); - ~AgentSubscription(); - bool tick(uint64_t seconds); - void keepalive() { timeSinceKeepalive = 0; } - - private: - uint64_t id; - uint64_t interval; - uint64_t lifetime; - uint64_t timeSincePublish; - uint64_t timeSinceKeepalive; - const std::string replyTo; - const std::string cid; - Query query; - }; - -} - -#endif diff --git a/cpp/src/qmf/ConsoleEvent.cpp b/cpp/src/qmf/ConsoleEvent.cpp deleted file mode 100644 index b2a5e321c7..0000000000 --- a/cpp/src/qmf/ConsoleEvent.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/ConsoleEventImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef<ConsoleEvent> PI; - -ConsoleEvent::ConsoleEvent(ConsoleEventImpl* impl) { PI::ctor(*this, impl); } -ConsoleEvent::ConsoleEvent(const ConsoleEvent& s) : qmf::Handle<ConsoleEventImpl>() { PI::copy(*this, s); } -ConsoleEvent::~ConsoleEvent() { PI::dtor(*this); } -ConsoleEvent& ConsoleEvent::operator=(const ConsoleEvent& s) { return PI::assign(*this, s); } - -ConsoleEventCode ConsoleEvent::getType() const { return impl->getType(); } -uint32_t ConsoleEvent::getCorrelator() const { return impl->getCorrelator(); } -Agent ConsoleEvent::getAgent() const { return impl->getAgent(); } -AgentDelReason ConsoleEvent::getAgentDelReason() const { return impl->getAgentDelReason(); } -uint32_t ConsoleEvent::getSchemaIdCount() const { return impl->getSchemaIdCount(); } -SchemaId ConsoleEvent::getSchemaId(uint32_t i) const { return impl->getSchemaId(i); } -uint32_t ConsoleEvent::getDataCount() const { return impl->getDataCount(); } -Data ConsoleEvent::getData(uint32_t i) const { return impl->getData(i); } -bool ConsoleEvent::isFinal() const { return impl->isFinal(); } -const Variant::Map& ConsoleEvent::getArguments() const { return impl->getArguments(); } -int ConsoleEvent::getSeverity() const { return impl->getSeverity(); } -uint64_t ConsoleEvent::getTimestamp() const { return impl->getTimestamp(); } - - -SchemaId ConsoleEventImpl::getSchemaId(uint32_t i) const -{ - uint32_t count = 0; - for (list<SchemaId>::const_iterator iter = newSchemaIds.begin(); iter != newSchemaIds.end(); iter++) { - if (count++ == i) - return *iter; - } - throw IndexOutOfRange(); -} - - -Data ConsoleEventImpl::getData(uint32_t i) const -{ - uint32_t count = 0; - for (list<Data>::const_iterator iter = dataList.begin(); iter != dataList.end(); iter++) { - if (count++ == i) - return *iter; - } - throw IndexOutOfRange(); -} - - -ConsoleEventImpl& ConsoleEventImplAccess::get(ConsoleEvent& item) -{ - return *item.impl; -} - - -const ConsoleEventImpl& ConsoleEventImplAccess::get(const ConsoleEvent& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/ConsoleEventImpl.h b/cpp/src/qmf/ConsoleEventImpl.h deleted file mode 100644 index 9843971456..0000000000 --- a/cpp/src/qmf/ConsoleEventImpl.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _QMF_CONSOLE_EVENT_IMPL_H_ -#define _QMF_CONSOLE_EVENT_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/ConsoleEvent.h" -#include "qmf/Agent.h" -#include "qmf/Data.h" -#include "qpid/types/Variant.h" -#include <list> - -namespace qmf { - class ConsoleEventImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only methods - // - ConsoleEventImpl(ConsoleEventCode e, AgentDelReason r = AGENT_DEL_AGED) : - eventType(e), delReason(r), correlator(0), final(false) {} - void setCorrelator(uint32_t c) { correlator = c; } - void setAgent(const Agent& a) { agent = a; } - void addData(const Data& d) { dataList.push_back(Data(d)); } - void addSchemaId(const SchemaId& s) { newSchemaIds.push_back(SchemaId(s)); } - void setFinal() { final = true; } - void setArguments(const qpid::types::Variant::Map& a) { arguments = a; } - void setSeverity(int s) { severity = s; } - void setTimestamp(uint64_t t) { timestamp = t; } - - // - // Methods from API handle - // - ConsoleEventCode getType() const { return eventType; } - uint32_t getCorrelator() const { return correlator; } - Agent getAgent() const { return agent; } - AgentDelReason getAgentDelReason() const { return delReason; } - uint32_t getSchemaIdCount() const { return newSchemaIds.size(); } - SchemaId getSchemaId(uint32_t) const; - uint32_t getDataCount() const { return dataList.size(); } - Data getData(uint32_t i) const; - bool isFinal() const { return final; } - const qpid::types::Variant::Map& getArguments() const { return arguments; } - int getSeverity() const { return severity; } - uint64_t getTimestamp() const { return timestamp; } - - private: - const ConsoleEventCode eventType; - const AgentDelReason delReason; - uint32_t correlator; - Agent agent; - bool final; - std::list<Data> dataList; - std::list<SchemaId> newSchemaIds; - qpid::types::Variant::Map arguments; - int severity; - uint64_t timestamp; - }; - - struct ConsoleEventImplAccess - { - static ConsoleEventImpl& get(ConsoleEvent&); - static const ConsoleEventImpl& get(const ConsoleEvent&); - }; -} - -#endif diff --git a/cpp/src/qmf/ConsoleSession.cpp b/cpp/src/qmf/ConsoleSession.cpp deleted file mode 100644 index 7b839930e1..0000000000 --- a/cpp/src/qmf/ConsoleSession.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/PrivateImplRef.h" -#include "qmf/ConsoleSessionImpl.h" -#include "qmf/AgentImpl.h" -#include "qmf/SchemaId.h" -#include "qmf/SchemaImpl.h" -#include "qmf/ConsoleEventImpl.h" -#include "qmf/constants.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Receiver.h" - -using namespace std; -using namespace qmf; -using qpid::messaging::Address; -using qpid::messaging::Connection; -using qpid::messaging::Receiver; -using qpid::messaging::Sender; -using qpid::messaging::Duration; -using qpid::messaging::Message; -using qpid::types::Variant; - -typedef qmf::PrivateImplRef<ConsoleSession> PI; - -ConsoleSession::ConsoleSession(ConsoleSessionImpl* impl) { PI::ctor(*this, impl); } -ConsoleSession::ConsoleSession(const ConsoleSession& s) : qmf::Handle<ConsoleSessionImpl>() { PI::copy(*this, s); } -ConsoleSession::~ConsoleSession() { PI::dtor(*this); } -ConsoleSession& ConsoleSession::operator=(const ConsoleSession& s) { return PI::assign(*this, s); } - -ConsoleSession::ConsoleSession(Connection& c, const string& o) { PI::ctor(*this, new ConsoleSessionImpl(c, o)); } -void ConsoleSession::setDomain(const string& d) { impl->setDomain(d); } -void ConsoleSession::setAgentFilter(const string& f) { impl->setAgentFilter(f); } -void ConsoleSession::open() { impl->open(); } -void ConsoleSession::close() { impl->close(); } -bool ConsoleSession::nextEvent(ConsoleEvent& e, Duration t) { return impl->nextEvent(e, t); } -int ConsoleSession::pendingEvents() const { return impl->pendingEvents(); } -uint32_t ConsoleSession::getAgentCount() const { return impl->getAgentCount(); } -Agent ConsoleSession::getAgent(uint32_t i) const { return impl->getAgent(i); } -Agent ConsoleSession::getConnectedBrokerAgent() const { return impl->getConnectedBrokerAgent(); } -Subscription ConsoleSession::subscribe(const Query& q, const string& f, const string& o) { return impl->subscribe(q, f, o); } -Subscription ConsoleSession::subscribe(const string& q, const string& f, const string& o) { return impl->subscribe(q, f, o); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -ConsoleSessionImpl::ConsoleSessionImpl(Connection& c, const string& options) : - connection(c), domain("default"), maxAgentAgeMinutes(5), - opened(false), thread(0), threadCanceled(false), lastVisit(0), lastAgePass(0), - connectedBrokerInAgentList(false), schemaCache(new SchemaCache()) -{ - if (!options.empty()) { - qpid::messaging::AddressParser parser(options); - Variant::Map optMap; - Variant::Map::const_iterator iter; - - parser.parseMap(optMap); - - iter = optMap.find("domain"); - if (iter != optMap.end()) - domain = iter->second.asString(); - - iter = optMap.find("max-agent-age"); - if (iter != optMap.end()) - maxAgentAgeMinutes = iter->second.asUint32(); - - iter = optMap.find("listen-on-direct"); - if (iter != optMap.end()) - listenOnDirect = iter->second.asBool(); - - iter = optMap.find("strict-security"); - if (iter != optMap.end()) - strictSecurity = iter->second.asBool(); - } -} - - -ConsoleSessionImpl::~ConsoleSessionImpl() -{ - if (opened) - close(); -} - - -void ConsoleSessionImpl::setAgentFilter(const string& predicate) -{ - agentQuery = Query(QUERY_OBJECT, predicate); - - // - // Purge the agent list of any agents that don't match the filter. - // - { - qpid::sys::Mutex::ScopedLock l(lock); - map<string, Agent> toDelete; - for (map<string, Agent>::iterator iter = agents.begin(); iter != agents.end(); iter++) - if (!agentQuery.matchesPredicate(iter->second.getAttributes())) { - toDelete[iter->first] = iter->second; - if (iter->second.getName() == connectedBrokerAgent.getName()) - connectedBrokerInAgentList = false; - } - - for (map<string, Agent>::iterator iter = toDelete.begin(); iter != toDelete.end(); iter++) { - agents.erase(iter->first); - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_DEL, AGENT_DEL_FILTER)); - eventImpl->setAgent(iter->second); - enqueueEventLH(eventImpl.release()); - } - - if (!connectedBrokerInAgentList && connectedBrokerAgent.isValid() && - agentQuery.matchesPredicate(connectedBrokerAgent.getAttributes())) { - agents[connectedBrokerAgent.getName()] = connectedBrokerAgent; - connectedBrokerInAgentList = true; - - // - // Enqueue a notification of the new agent. - // - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_ADD)); - eventImpl->setAgent(connectedBrokerAgent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - } - } - - // - // Broadcast an agent locate request with our new criteria. - // - if (opened) - sendAgentLocate(); -} - - -void ConsoleSessionImpl::open() -{ - if (opened) - throw QmfException("The session is already open"); - - // Establish messaging addresses - directBase = "qmf." + domain + ".direct"; - topicBase = "qmf." + domain + ".topic"; - - string myKey("direct-console." + qpid::types::Uuid(true).str()); - - replyAddress = Address(topicBase + "/" + myKey + ";{node:{type:topic}}"); - - // Create AMQP session, receivers, and senders - session = connection.createSession(); - Receiver directRx = session.createReceiver(replyAddress); - Receiver topicRx = session.createReceiver(topicBase + "/agent.#"); // TODO: be more discriminating - if (!strictSecurity) { - Receiver legacyRx = session.createReceiver("amq.direct/" + myKey + ";{node:{type:topic}}"); - legacyRx.setCapacity(64); - directSender = session.createSender(directBase + ";{create:never,node:{type:topic}}"); - directSender.setCapacity(128); - } - - directRx.setCapacity(64); - topicRx.setCapacity(128); - - topicSender = session.createSender(topicBase + ";{create:never,node:{type:topic}}"); - - topicSender.setCapacity(128); - - // Start the receiver thread - threadCanceled = false; - thread = new qpid::sys::Thread(*this); - - // Send an agent_locate to direct address 'broker' to identify the connected-broker-agent. - sendBrokerLocate(); - if (agentQuery) - sendAgentLocate(); - - opened = true; -} - - -void ConsoleSessionImpl::close() -{ - if (!opened) - throw QmfException("The session is already closed"); - - // Stop and join the receiver thread - threadCanceled = true; - thread->join(); - delete thread; - - // Close the AMQP session - session.close(); - opened = false; -} - - -bool ConsoleSessionImpl::nextEvent(ConsoleEvent& event, Duration timeout) -{ - uint64_t milliseconds = timeout.getMilliseconds(); - qpid::sys::Mutex::ScopedLock l(lock); - - if (eventQueue.empty() && milliseconds > 0) - cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(), - qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC))); - - if (!eventQueue.empty()) { - event = eventQueue.front(); - eventQueue.pop(); - return true; - } - - return false; -} - - -int ConsoleSessionImpl::pendingEvents() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return eventQueue.size(); -} - - -uint32_t ConsoleSessionImpl::getAgentCount() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return agents.size(); -} - - -Agent ConsoleSessionImpl::getAgent(uint32_t i) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - uint32_t count = 0; - for (map<string, Agent>::const_iterator iter = agents.begin(); iter != agents.end(); iter++) - if (count++ == i) - return iter->second; - throw IndexOutOfRange(); -} - - -Subscription ConsoleSessionImpl::subscribe(const Query&, const string&, const string&) -{ - return Subscription(); -} - - -Subscription ConsoleSessionImpl::subscribe(const string&, const string&, const string&) -{ - return Subscription(); -} - - -void ConsoleSessionImpl::enqueueEvent(const ConsoleEvent& event) -{ - qpid::sys::Mutex::ScopedLock l(lock); - enqueueEventLH(event); -} - - -void ConsoleSessionImpl::enqueueEventLH(const ConsoleEvent& event) -{ - bool notify = eventQueue.empty(); - eventQueue.push(event); - if (notify) - cond.notify(); -} - - -void ConsoleSessionImpl::dispatch(Message msg) -{ - const Variant::Map& properties(msg.getProperties()); - Variant::Map::const_iterator iter; - Variant::Map::const_iterator oiter; - - oiter = properties.find(protocol::HEADER_KEY_OPCODE); - iter = properties.find(protocol::HEADER_KEY_APP_ID); - if (iter == properties.end()) - iter = properties.find("app_id"); - if (iter != properties.end() && iter->second.asString() == protocol::HEADER_APP_ID_QMF && oiter != properties.end()) { - // - // Dispatch a QMFv2 formatted message - // - const string& opcode = oiter->second.asString(); - - iter = properties.find(protocol::HEADER_KEY_AGENT); - if (iter == properties.end()) { - QPID_LOG(trace, "Message received with no 'qmf.agent' header"); - return; - } - const string& agentName = iter->second.asString(); - - Agent agent; - { - qpid::sys::Mutex::ScopedLock l(lock); - map<string, Agent>::iterator aIter = agents.find(agentName); - if (aIter != agents.end()) { - agent = aIter->second; - AgentImplAccess::get(agent).touch(); - } - } - - if (msg.getContentType() == "amqp/map" && - (opcode == protocol::HEADER_OPCODE_AGENT_HEARTBEAT_INDICATION || opcode == protocol::HEADER_OPCODE_AGENT_LOCATE_RESPONSE)) { - // - // This is the one case where it's ok (necessary actually) to receive a QMFv2 - // message from an unknown agent (how else are they going to get known?) - // - Variant::Map content; - decode(msg, content); - handleAgentUpdate(agentName, content, msg); - return; - } - - if (!agent.isValid()) - return; - - AgentImpl& agentImpl(AgentImplAccess::get(agent)); - - if (msg.getContentType() == "amqp/map") { - Variant::Map content; - decode(msg, content); - - if (opcode == protocol::HEADER_OPCODE_EXCEPTION) agentImpl.handleException(content, msg); - else if (opcode == protocol::HEADER_OPCODE_METHOD_RESPONSE) agentImpl.handleMethodResponse(content, msg); - else - QPID_LOG(error, "Received a map-formatted QMFv2 message with opcode=" << opcode); - - return; - } - - if (msg.getContentType() == "amqp/list") { - Variant::List content; - decode(msg, content); - - if (opcode == protocol::HEADER_OPCODE_QUERY_RESPONSE) agentImpl.handleQueryResponse(content, msg); - else if (opcode == protocol::HEADER_OPCODE_DATA_INDICATION) agentImpl.handleDataIndication(content, msg); - else - QPID_LOG(error, "Received a list-formatted QMFv2 message with opcode=" << opcode); - - return; - } - } else { - // - // Dispatch a QMFv1 formatted message - // - const string& body(msg.getContent()); - if (body.size() < 8) - return; - qpid::management::Buffer buffer(const_cast<char*>(body.c_str()), body.size()); - - if (buffer.getOctet() != 'A') return; - if (buffer.getOctet() != 'M') return; - if (buffer.getOctet() != '2') return; - char v1Opcode(buffer.getOctet()); - uint32_t seq(buffer.getLong()); - - if (v1Opcode == 's') handleV1SchemaResponse(buffer, seq, msg); - else { - QPID_LOG(trace, "Unknown or Unsupported QMFv1 opcode: " << v1Opcode); - } - } -} - - -void ConsoleSessionImpl::sendBrokerLocate() -{ - Message msg; - Variant::Map& headers(msg.getProperties()); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_REQUEST; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_AGENT_LOCATE_REQUEST; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - msg.setReplyTo(replyAddress); - msg.setCorrelationId("broker-locate"); - msg.setSubject("broker"); - - Sender sender = session.createSender(directBase + ";{create:never,node:{type:topic}}"); - sender.send(msg); - sender.close(); - - QPID_LOG(trace, "SENT AgentLocate to broker"); -} - - -void ConsoleSessionImpl::sendAgentLocate() -{ - Message msg; - Variant::Map& headers(msg.getProperties()); - static const string subject("console.request.agent_locate"); - - headers[protocol::HEADER_KEY_METHOD] = protocol::HEADER_METHOD_REQUEST; - headers[protocol::HEADER_KEY_OPCODE] = protocol::HEADER_OPCODE_AGENT_LOCATE_REQUEST; - headers[protocol::HEADER_KEY_APP_ID] = protocol::HEADER_APP_ID_QMF; - - msg.setReplyTo(replyAddress); - msg.setCorrelationId("agent-locate"); - msg.setSubject(subject); - encode(agentQuery.getPredicate(), msg); - - topicSender.send(msg); - - QPID_LOG(trace, "SENT AgentLocate to=" << topicSender.getName() << "/" << subject); -} - - -void ConsoleSessionImpl::handleAgentUpdate(const string& agentName, const Variant::Map& content, const Message& msg) -{ - Variant::Map::const_iterator iter; - Agent agent; - uint32_t epoch(0); - string cid(msg.getCorrelationId()); - - iter = content.find("_values"); - if (iter == content.end()) - return; - const Variant::Map& in_attrs(iter->second.asMap()); - Variant::Map attrs; - - // - // Copy the map from the message to "attrs". Translate any old-style - // keys to their new key values in the process. - // - for (iter = in_attrs.begin(); iter != in_attrs.end(); iter++) { - if (iter->first == "epoch") - attrs[protocol::AGENT_ATTR_EPOCH] = iter->second; - else if (iter->first == "timestamp") - attrs[protocol::AGENT_ATTR_TIMESTAMP] = iter->second; - else if (iter->first == "heartbeat_interval") - attrs[protocol::AGENT_ATTR_HEARTBEAT_INTERVAL] = iter->second; - else - attrs[iter->first] = iter->second; - } - - iter = attrs.find(protocol::AGENT_ATTR_EPOCH); - if (iter != attrs.end()) - epoch = iter->second.asUint32(); - - if (cid == "broker-locate") { - qpid::sys::Mutex::ScopedLock l(lock); - auto_ptr<AgentImpl> impl(new AgentImpl(agentName, epoch, *this)); - for (iter = attrs.begin(); iter != attrs.end(); iter++) - if (iter->first != protocol::AGENT_ATTR_EPOCH) - impl->setAttribute(iter->first, iter->second); - agent = Agent(impl.release()); - connectedBrokerAgent = agent; - if (!agentQuery || agentQuery.matchesPredicate(attrs)) { - connectedBrokerInAgentList = true; - agents[agentName] = agent; - - // - // Enqueue a notification of the new agent. - // - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_ADD)); - eventImpl->setAgent(agent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - } - return; - } - - // - // Check this agent against the agent filter. Exit if it doesn't match. - // (only if this isn't the connected broker agent) - // - if (agentQuery && (!agentQuery.matchesPredicate(attrs))) - return; - - QPID_LOG(trace, "RCVD AgentHeartbeat from an agent matching our filter: " << agentName); - - { - qpid::sys::Mutex::ScopedLock l(lock); - map<string, Agent>::iterator aIter = agents.find(agentName); - if (aIter == agents.end()) { - // - // This is a new agent. We have no current record of its existence. - // - auto_ptr<AgentImpl> impl(new AgentImpl(agentName, epoch, *this)); - for (iter = attrs.begin(); iter != attrs.end(); iter++) - if (iter->first != protocol::AGENT_ATTR_EPOCH) - impl->setAttribute(iter->first, iter->second); - agent = Agent(impl.release()); - agents[agentName] = agent; - - // - // Enqueue a notification of the new agent. - // - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_ADD)); - eventImpl->setAgent(agent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - } else { - // - // This is a refresh of an agent we are already tracking. - // - bool detectedRestart(false); - agent = aIter->second; - AgentImpl& impl(AgentImplAccess::get(agent)); - impl.touch(); - if (impl.getEpoch() != epoch) { - // - // The agent has restarted since the last time we heard from it. - // Enqueue a notification. - // - impl.setEpoch(epoch); - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_RESTART)); - eventImpl->setAgent(agent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - detectedRestart = true; - } - - iter = attrs.find(protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP); - if (iter != attrs.end()) { - uint64_t ts(iter->second.asUint64()); - if (ts > impl.getAttribute(protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP).asUint64()) { - // - // The agent has added new schema entries since we last heard from it. - // Update the attribute and, if this doesn't accompany a restart, enqueue a notification. - // - if (!detectedRestart) { - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_SCHEMA_UPDATE)); - eventImpl->setAgent(agent); - enqueueEventLH(ConsoleEvent(eventImpl.release())); - } - impl.setAttribute(protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP, iter->second); - } - } - } - } -} - - -void ConsoleSessionImpl::handleV1SchemaResponse(qpid::management::Buffer& buffer, uint32_t, const Message&) -{ - QPID_LOG(trace, "RCVD V1SchemaResponse"); - Schema schema(new SchemaImpl(buffer)); - schemaCache->declareSchema(schema); -} - - -void ConsoleSessionImpl::periodicProcessing(uint64_t seconds) -{ - // - // The granularity of this timer is seconds. Don't waste time looking for work if - // it's been less than a second since we last visited. - // - if (seconds == lastVisit) - return; - lastVisit = seconds; - - // - // Handle the aging of agent records - // - if (lastAgePass == 0) - lastAgePass = seconds; - if (seconds - lastAgePass >= 60) { - lastAgePass = seconds; - map<string, Agent> toDelete; - qpid::sys::Mutex::ScopedLock l(lock); - - for (map<string, Agent>::iterator iter = agents.begin(); iter != agents.end(); iter++) - if ((iter->second.getName() != connectedBrokerAgent.getName()) && - (AgentImplAccess::get(iter->second).age() > maxAgentAgeMinutes)) - toDelete[iter->first] = iter->second; - - for (map<string, Agent>::iterator iter = toDelete.begin(); iter != toDelete.end(); iter++) { - agents.erase(iter->first); - auto_ptr<ConsoleEventImpl> eventImpl(new ConsoleEventImpl(CONSOLE_AGENT_DEL, AGENT_DEL_AGED)); - eventImpl->setAgent(iter->second); - enqueueEventLH(eventImpl.release()); - } - } -} - - -void ConsoleSessionImpl::run() -{ - QPID_LOG(debug, "ConsoleSession thread started"); - - try { - while (!threadCanceled) { - periodicProcessing((uint64_t) qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now()) / - qpid::sys::TIME_SEC); - - Receiver rx; - bool valid = session.nextReceiver(rx, Duration::SECOND); - if (threadCanceled) - break; - if (valid) { - try { - dispatch(rx.fetch()); - } catch (qpid::types::Exception& e) { - QPID_LOG(error, "Exception caught in message dispatch: " << e.what()); - } - session.acknowledge(); - } - } - } catch (qpid::types::Exception& e) { - QPID_LOG(error, "Exception caught in message thread - exiting: " << e.what()); - enqueueEvent(ConsoleEvent(new ConsoleEventImpl(CONSOLE_THREAD_FAILED))); - } - - QPID_LOG(debug, "ConsoleSession thread exiting"); -} - diff --git a/cpp/src/qmf/ConsoleSessionImpl.h b/cpp/src/qmf/ConsoleSessionImpl.h deleted file mode 100644 index 411b3f016a..0000000000 --- a/cpp/src/qmf/ConsoleSessionImpl.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef _QMF_CONSOLE_SESSION_IMPL_H_ -#define _QMF_CONSOLE_SESSION_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/ConsoleSession.h" -#include "qmf/AgentImpl.h" -#include "qmf/SchemaId.h" -#include "qmf/Schema.h" -#include "qmf/ConsoleEventImpl.h" -#include "qmf/SchemaCache.h" -#include "qmf/Query.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Condition.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Address.h" -#include "qpid/management/Buffer.h" -#include "qpid/types/Variant.h" -#include <map> -#include <queue> - -namespace qmf { - class ConsoleSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable { - public: - ~ConsoleSessionImpl(); - - // - // Methods from API handle - // - ConsoleSessionImpl(qpid::messaging::Connection& c, const std::string& o); - void setDomain(const std::string& d) { domain = d; } - void setAgentFilter(const std::string& f); - void open(); - void close(); - bool nextEvent(ConsoleEvent& e, qpid::messaging::Duration t); - int pendingEvents() const; - uint32_t getAgentCount() const; - Agent getAgent(uint32_t i) const; - Agent getConnectedBrokerAgent() const { return connectedBrokerAgent; } - Subscription subscribe(const Query&, const std::string& agentFilter, const std::string& options); - Subscription subscribe(const std::string&, const std::string& agentFilter, const std::string& options); - - protected: - mutable qpid::sys::Mutex lock; - qpid::sys::Condition cond; - qpid::messaging::Connection connection; - qpid::messaging::Session session; - qpid::messaging::Sender directSender; - qpid::messaging::Sender topicSender; - std::string domain; - uint32_t maxAgentAgeMinutes; - bool listenOnDirect; - bool strictSecurity; - Query agentQuery; - bool opened; - std::queue<ConsoleEvent> eventQueue; - qpid::sys::Thread* thread; - bool threadCanceled; - uint64_t lastVisit; - uint64_t lastAgePass; - std::map<std::string, Agent> agents; - Agent connectedBrokerAgent; - bool connectedBrokerInAgentList; - qpid::messaging::Address replyAddress; - std::string directBase; - std::string topicBase; - boost::shared_ptr<SchemaCache> schemaCache; - - void enqueueEvent(const ConsoleEvent&); - void enqueueEventLH(const ConsoleEvent&); - void dispatch(qpid::messaging::Message); - void sendBrokerLocate(); - void sendAgentLocate(); - void handleAgentUpdate(const std::string&, const qpid::types::Variant::Map&, const qpid::messaging::Message&); - void handleV1SchemaResponse(qpid::management::Buffer&, uint32_t, const qpid::messaging::Message&); - void periodicProcessing(uint64_t); - void run(); - - friend class AgentImpl; - }; -} - -#endif diff --git a/cpp/src/qmf/Data.cpp b/cpp/src/qmf/Data.cpp deleted file mode 100644 index c503bab445..0000000000 --- a/cpp/src/qmf/Data.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/DataImpl.h" -#include "qmf/DataAddrImpl.h" -#include "qmf/SchemaImpl.h" -#include "qmf/SchemaIdImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/SchemaProperty.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef<Data> PI; - -Data::Data(DataImpl* impl) { PI::ctor(*this, impl); } -Data::Data(const Data& s) : qmf::Handle<DataImpl>() { PI::copy(*this, s); } -Data::~Data() { PI::dtor(*this); } -Data& Data::operator=(const Data& s) { return PI::assign(*this, s); } - -Data::Data(const Schema& s) { PI::ctor(*this, new DataImpl(s)); } -void Data::setAddr(const DataAddr& a) { impl->setAddr(a); } -void Data::setProperty(const string& k, const qpid::types::Variant& v) { impl->setProperty(k, v); } -void Data::overwriteProperties(const qpid::types::Variant::Map& m) { impl->overwriteProperties(m); } -bool Data::hasSchema() const { return impl->hasSchema(); } -bool Data::hasAddr() const { return impl->hasAddr(); } -const SchemaId& Data::getSchemaId() const { return impl->getSchemaId(); } -const DataAddr& Data::getAddr() const { return impl->getAddr(); } -const Variant& Data::getProperty(const string& k) const { return impl->getProperty(k); } -const Variant::Map& Data::getProperties() const { return impl->getProperties(); } -bool Data::hasAgent() const { return impl->hasAgent(); } -const Agent& Data::getAgent() const { return impl->getAgent(); } - - -void DataImpl::overwriteProperties(const Variant::Map& m) { - for (Variant::Map::const_iterator iter = m.begin(); iter != m.end(); iter++) - properties[iter->first] = iter->second; -} - -const Variant& DataImpl::getProperty(const string& k) const { - Variant::Map::const_iterator iter = properties.find(k); - if (iter == properties.end()) - throw KeyNotFound(k); - return iter->second; -} - - -DataImpl::DataImpl(const qpid::types::Variant::Map& map, const Agent& a) -{ - Variant::Map::const_iterator iter; - - agent = a; - - iter = map.find("_values"); - if (iter != map.end()) - properties = iter->second.asMap(); - - iter = map.find("_object_id"); - if (iter != map.end()) - dataAddr = DataAddr(new DataAddrImpl(iter->second.asMap())); - - iter = map.find("_schema_id"); - if (iter != map.end()) - schemaId = SchemaId(new SchemaIdImpl(iter->second.asMap())); -} - - -Variant::Map DataImpl::asMap() const -{ - Variant::Map result; - - result["_values"] = properties; - - if (hasAddr()) { - const DataAddrImpl& aImpl(DataAddrImplAccess::get(getAddr())); - result["_object_id"] = aImpl.asMap(); - } - - if (hasSchema()) { - const SchemaIdImpl& sImpl(SchemaIdImplAccess::get(getSchemaId())); - result["_schema_id"] = sImpl.asMap(); - } - - return result; -} - - -void DataImpl::setProperty(const std::string& k, const qpid::types::Variant& v) -{ - if (schema.isValid()) { - // - // If we have a valid schema, make sure that the property is included in the - // schema and that the variant type is compatible with the schema type. - // - if (!SchemaImplAccess::get(schema).isValidProperty(k, v)) - throw QmfException("Property '" + k + "' either not in the schema or value is of incompatible type"); - } - properties[k] = v; -} - - -DataImpl& DataImplAccess::get(Data& item) -{ - return *item.impl; -} - - -const DataImpl& DataImplAccess::get(const Data& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/DataAddr.cpp b/cpp/src/qmf/DataAddr.cpp deleted file mode 100644 index fb51d5787f..0000000000 --- a/cpp/src/qmf/DataAddr.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/DataAddrImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/DataAddr.h" -#include <iostream> - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef<DataAddr> PI; - -DataAddr::DataAddr(DataAddrImpl* impl) { PI::ctor(*this, impl); } -DataAddr::DataAddr(const DataAddr& s) : qmf::Handle<DataAddrImpl>() { PI::copy(*this, s); } -DataAddr::~DataAddr() { PI::dtor(*this); } -DataAddr& DataAddr::operator=(const DataAddr& s) { return PI::assign(*this, s); } - -bool DataAddr::operator==(const DataAddr& o) { return *impl == *o.impl; } -bool DataAddr::operator<(const DataAddr& o) { return *impl < *o.impl; } - -DataAddr::DataAddr(const qpid::types::Variant::Map& m) { PI::ctor(*this, new DataAddrImpl(m)); } -DataAddr::DataAddr(const string& n, const string& a, uint32_t e) { PI::ctor(*this, new DataAddrImpl(n, a, e)); } -const string& DataAddr::getName() const { return impl->getName(); } -const string& DataAddr::getAgentName() const { return impl->getAgentName(); } -uint32_t DataAddr::getAgentEpoch() const { return impl->getAgentEpoch(); } -Variant::Map DataAddr::asMap() const { return impl->asMap(); } - -bool DataAddrImpl::operator==(const DataAddrImpl& other) -{ - return - agentName == other.agentName && - name == other.name && - agentEpoch == other.agentEpoch; -} - - -bool DataAddrImpl::operator<(const DataAddrImpl& other) -{ - if (agentName < other.agentName) return true; - if (agentName > other.agentName) return false; - if (name < other.name) return true; - if (name > other.name) return false; - return agentEpoch < other.agentEpoch; -} - - -DataAddrImpl::DataAddrImpl(const Variant::Map& map) -{ - Variant::Map::const_iterator iter; - - iter = map.find("_agent_name"); - if (iter != map.end()) - agentName = iter->second.asString(); - - iter = map.find("_object_name"); - if (iter != map.end()) - name = iter->second.asString(); - - iter = map.find("_agent_epoch"); - if (iter != map.end()) - agentEpoch = (uint32_t) iter->second.asUint64(); -} - - -Variant::Map DataAddrImpl::asMap() const -{ - Variant::Map result; - - result["_agent_name"] = agentName; - result["_object_name"] = name; - if (agentEpoch > 0) - result["_agent_epoch"] = agentEpoch; - return result; -} - - -DataAddrImpl& DataAddrImplAccess::get(DataAddr& item) -{ - return *item.impl; -} - - -const DataAddrImpl& DataAddrImplAccess::get(const DataAddr& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/DataAddrImpl.h b/cpp/src/qmf/DataAddrImpl.h deleted file mode 100644 index 3f9cae9453..0000000000 --- a/cpp/src/qmf/DataAddrImpl.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef _QMF_DATA_ADDR_IMPL_H_ -#define _QMF_DATA_ADDR_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/types/Variant.h" -#include "qmf/DataAddr.h" - -namespace qmf { - class DataAddrImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only methods - // - void setName(const std::string& n) { name = n; } - void setAgent(const std::string& n, uint32_t e=0) { agentName = n; agentEpoch = e; } - - // - // Methods from API handle - // - bool operator==(const DataAddrImpl&); - bool operator<(const DataAddrImpl&); - DataAddrImpl(const qpid::types::Variant::Map&); - DataAddrImpl(const std::string& _name, const std::string& _agentName, uint32_t _agentEpoch=0) : - agentName(_agentName), name(_name), agentEpoch(_agentEpoch) {} - const std::string& getName() const { return name; } - const std::string& getAgentName() const { return agentName; } - uint32_t getAgentEpoch() const { return agentEpoch; } - qpid::types::Variant::Map asMap() const; - - private: - std::string agentName; - std::string name; - uint32_t agentEpoch; - }; - - struct DataAddrImplAccess - { - static DataAddrImpl& get(DataAddr&); - static const DataAddrImpl& get(const DataAddr&); - }; - - struct DataAddrCompare { - bool operator() (const DataAddr& lhs, const DataAddr& rhs) const - { - if (lhs.getName() != rhs.getName()) - return lhs.getName() < rhs.getName(); - return lhs.getAgentName() < rhs.getAgentName(); - } - }; -} - -#endif diff --git a/cpp/src/qmf/DataImpl.h b/cpp/src/qmf/DataImpl.h deleted file mode 100644 index 4ac3197da0..0000000000 --- a/cpp/src/qmf/DataImpl.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _QMF_DATA_IMPL_H_ -#define _QMF_DATA_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/Data.h" -#include "qmf/SchemaId.h" -#include "qmf/Schema.h" -#include "qmf/DataAddr.h" -#include "qmf/Agent.h" -#include "qmf/AgentSubscription.h" -#include "qpid/types/Variant.h" - -namespace qmf { - class DataImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - DataImpl(const qpid::types::Variant::Map&, const Agent&); - qpid::types::Variant::Map asMap() const; - DataImpl() {} - void addSubscription(boost::shared_ptr<AgentSubscription>); - void delSubscription(uint64_t); - qpid::types::Variant::Map publishSubscription(uint64_t); - const Schema& getSchema() const { return schema; } - - // - // Methods from API handle - // - DataImpl(const Schema& s) : schema(s) {} - void setAddr(const DataAddr& a) { dataAddr = a; } - void setProperty(const std::string& k, const qpid::types::Variant& v); - void overwriteProperties(const qpid::types::Variant::Map& m); - bool hasSchema() const { return schemaId.isValid() || schema.isValid(); } - bool hasAddr() const { return dataAddr.isValid(); } - const SchemaId& getSchemaId() const { if (schema.isValid()) return schema.getSchemaId(); else return schemaId; } - const DataAddr& getAddr() const { return dataAddr; } - const qpid::types::Variant& getProperty(const std::string& k) const; - const qpid::types::Variant::Map& getProperties() const { return properties; } - bool hasAgent() const { return agent.isValid(); } - const Agent& getAgent() const { return agent; } - - private: - struct Subscr { - boost::shared_ptr<AgentSubscription> subscription; - qpid::types::Variant::Map deltas; - }; - std::map<uint64_t, boost::shared_ptr<Subscr> > subscriptions; - - SchemaId schemaId; - Schema schema; - DataAddr dataAddr; - qpid::types::Variant::Map properties; - Agent agent; - }; - - struct DataImplAccess - { - static DataImpl& get(Data&); - static const DataImpl& get(const Data&); - }; -} - -#endif diff --git a/cpp/src/qmf/Expression.cpp b/cpp/src/qmf/Expression.cpp deleted file mode 100644 index 7d48678c15..0000000000 --- a/cpp/src/qmf/Expression.cpp +++ /dev/null @@ -1,441 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/exceptions.h" -#include "qmf/Expression.h" -#include <iostream> - -using namespace std; -using namespace qmf; -using namespace qpid::types; - -Expression::Expression(const Variant::List& expr) -{ - static int level(0); - level++; - Variant::List::const_iterator iter(expr.begin()); - string op(iter->asString()); - iter++; - - if (op == "not") logicalOp = LOGICAL_NOT; - else if (op == "and") logicalOp = LOGICAL_AND; - else if (op == "or") logicalOp = LOGICAL_OR; - else { - logicalOp = LOGICAL_ID; - if (op == "eq") boolOp = BOOL_EQ; - else if (op == "ne") boolOp = BOOL_NE; - else if (op == "lt") boolOp = BOOL_LT; - else if (op == "le") boolOp = BOOL_LE; - else if (op == "gt") boolOp = BOOL_GT; - else if (op == "ge") boolOp = BOOL_GE; - else if (op == "re_match") boolOp = BOOL_RE_MATCH; - else if (op == "exists") boolOp = BOOL_EXISTS; - else if (op == "true") boolOp = BOOL_TRUE; - else if (op == "false") boolOp = BOOL_FALSE; - else - throw QmfException("Invalid operator in predicate expression"); - } - - if (logicalOp == LOGICAL_ID) { - switch (boolOp) { - case BOOL_EQ: - case BOOL_NE: - case BOOL_LT: - case BOOL_LE: - case BOOL_GT: - case BOOL_GE: - case BOOL_RE_MATCH: - // - // Binary operator: get two operands. - // - operandCount = 2; - break; - - case BOOL_EXISTS: - // - // Unary operator: get one operand. - // - operandCount = 1; - break; - - case BOOL_TRUE: - case BOOL_FALSE: - // - // Literal operator: no operands. - // - operandCount = 0; - break; - } - - for (int idx = 0; idx < operandCount; idx++) { - if (iter == expr.end()) - throw QmfException("Too few operands for operation: " + op); - if (iter->getType() == VAR_STRING) { - quoted[idx] = false; - operands[idx] = *iter; - } else if (iter->getType() == VAR_LIST) { - const Variant::List& sublist(iter->asList()); - Variant::List::const_iterator subIter(sublist.begin()); - if (subIter != sublist.end() && subIter->asString() == "quote") { - quoted[idx] = true; - subIter++; - if (subIter != sublist.end()) { - operands[idx] = *subIter; - subIter++; - if (subIter != sublist.end()) - throw QmfException("Extra tokens at end of 'quote'"); - } - } else - throw QmfException("Expected '[quote, <token>]'"); - } else - throw QmfException("Expected string or list as operand for: " + op); - iter++; - } - - if (iter != expr.end()) - throw QmfException("Too many operands for operation: " + op); - - } else { - // - // This is a logical expression, collect sub-expressions - // - while (iter != expr.end()) { - if (iter->getType() != VAR_LIST) - throw QmfException("Operands of " + op + " must be lists"); - expressionList.push_back(boost::shared_ptr<Expression>(new Expression(iter->asList()))); - iter++; - } - } - level--; -} - - -bool Expression::evaluate(const Variant::Map& data) const -{ - list<boost::shared_ptr<Expression> >::const_iterator iter; - - switch (logicalOp) { - case LOGICAL_ID: - return boolEval(data); - - case LOGICAL_NOT: - for (iter = expressionList.begin(); iter != expressionList.end(); iter++) - if ((*iter)->evaluate(data)) - return false; - return true; - - case LOGICAL_AND: - for (iter = expressionList.begin(); iter != expressionList.end(); iter++) - if (!(*iter)->evaluate(data)) - return false; - return true; - - case LOGICAL_OR: - for (iter = expressionList.begin(); iter != expressionList.end(); iter++) - if ((*iter)->evaluate(data)) - return true; - return false; - } - - return false; -} - - -bool Expression::boolEval(const Variant::Map& data) const -{ - Variant val[2]; - bool exists[2]; - - for (int idx = 0; idx < operandCount; idx++) { - if (quoted[idx]) { - exists[idx] = true; - val[idx] = operands[idx]; - } else { - Variant::Map::const_iterator mIter(data.find(operands[idx].asString())); - if (mIter == data.end()) { - exists[idx] = false; - } else { - exists[idx] = true; - val[idx] = mIter->second; - } - } - } - - switch (boolOp) { - case BOOL_EQ: return (exists[0] && exists[1] && (val[0].asString() == val[1].asString())); - case BOOL_NE: return (exists[0] && exists[1] && (val[0].asString() != val[1].asString())); - case BOOL_LT: return (exists[0] && exists[1] && lessThan(val[0], val[1])); - case BOOL_LE: return (exists[0] && exists[1] && lessEqual(val[0], val[1])); - case BOOL_GT: return (exists[0] && exists[1] && greaterThan(val[0], val[1])); - case BOOL_GE: return (exists[0] && exists[1] && greaterEqual(val[0], val[1])); - case BOOL_RE_MATCH: return false; // TODO - case BOOL_EXISTS: return exists[0]; - case BOOL_TRUE: return true; - case BOOL_FALSE: return false; - } - - return false; -} - -bool Expression::lessThan(const Variant& left, const Variant& right) const -{ - switch (left.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - return left.asInt64() < right.asInt64(); - case VAR_STRING: - try { - return left.asInt64() < right.asInt64(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_FLOAT: case VAR_DOUBLE: - switch (right.getType()) { - case VAR_FLOAT: case VAR_DOUBLE: - return left.asDouble() < right.asDouble(); - case VAR_STRING: - try { - return left.asDouble() < right.asDouble(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_STRING: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - try { - return left.asInt64() < right.asInt64(); - } catch (std::exception&) {} - break; - - case VAR_FLOAT: case VAR_DOUBLE: - try { - return left.asDouble() < right.asDouble(); - } catch (std::exception&) {} - break; - - case VAR_STRING: - return left.asString() < right.asString(); - default: - break; - } - default: - break; - } - - return false; -} - - -bool Expression::lessEqual(const Variant& left, const Variant& right) const -{ - switch (left.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - return left.asInt64() <= right.asInt64(); - case VAR_STRING: - try { - return left.asInt64() <= right.asInt64(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_FLOAT: case VAR_DOUBLE: - switch (right.getType()) { - case VAR_FLOAT: case VAR_DOUBLE: - return left.asDouble() <= right.asDouble(); - case VAR_STRING: - try { - return left.asDouble() <= right.asDouble(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_STRING: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - try { - return left.asInt64() <= right.asInt64(); - } catch (std::exception&) {} - break; - - case VAR_FLOAT: case VAR_DOUBLE: - try { - return left.asDouble() <= right.asDouble(); - } catch (std::exception&) {} - break; - - case VAR_STRING: - return left.asString() <= right.asString(); - default: - break; - } - default: - break; - } - - return false; -} - - -bool Expression::greaterThan(const Variant& left, const Variant& right) const -{ - switch (left.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - return left.asInt64() > right.asInt64(); - case VAR_STRING: - try { - return left.asInt64() > right.asInt64(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_FLOAT: case VAR_DOUBLE: - switch (right.getType()) { - case VAR_FLOAT: case VAR_DOUBLE: - return left.asDouble() > right.asDouble(); - case VAR_STRING: - try { - return left.asDouble() > right.asDouble(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_STRING: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - try { - return left.asInt64() > right.asInt64(); - } catch (std::exception&) {} - break; - - case VAR_FLOAT: case VAR_DOUBLE: - try { - return left.asDouble() > right.asDouble(); - } catch (std::exception&) {} - break; - - case VAR_STRING: - return left.asString() > right.asString(); - default: - break; - } - default: - break; - } - - return false; -} - - -bool Expression::greaterEqual(const Variant& left, const Variant& right) const -{ - switch (left.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - return left.asInt64() >= right.asInt64(); - case VAR_STRING: - try { - return left.asInt64() >= right.asInt64(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_FLOAT: case VAR_DOUBLE: - switch (right.getType()) { - case VAR_FLOAT: case VAR_DOUBLE: - return left.asDouble() >= right.asDouble(); - case VAR_STRING: - try { - return left.asDouble() >= right.asDouble(); - } catch (std::exception&) {} - break; - default: - break; - } - break; - - case VAR_STRING: - switch (right.getType()) { - case VAR_UINT8: case VAR_UINT16: case VAR_UINT32: case VAR_UINT64: - case VAR_INT8: case VAR_INT16: case VAR_INT32: case VAR_INT64: - try { - return left.asInt64() >= right.asInt64(); - } catch (std::exception&) {} - break; - - case VAR_FLOAT: case VAR_DOUBLE: - try { - return left.asDouble() >= right.asDouble(); - } catch (std::exception&) {} - break; - - case VAR_STRING: - return left.asString() >= right.asString(); - default: - break; - } - default: - break; - } - - return false; -} - - diff --git a/cpp/src/qmf/Expression.h b/cpp/src/qmf/Expression.h deleted file mode 100644 index 6fbfdbc4ba..0000000000 --- a/cpp/src/qmf/Expression.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef _QMF_EXPRESSION_H_ -#define _QMF_EXPRESSION_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/types/Variant.h" -#include <string> -#include <list> -#include <boost/shared_ptr.hpp> - -namespace qmf { - - enum LogicalOp { - LOGICAL_ID = 1, - LOGICAL_NOT = 2, - LOGICAL_AND = 3, - LOGICAL_OR = 4 - }; - - enum BooleanOp { - BOOL_EQ = 1, - BOOL_NE = 2, - BOOL_LT = 3, - BOOL_LE = 4, - BOOL_GT = 5, - BOOL_GE = 6, - BOOL_RE_MATCH = 7, - BOOL_EXISTS = 8, - BOOL_TRUE = 9, - BOOL_FALSE = 10 - }; - - class Expression { - public: - Expression(const qpid::types::Variant::List& expr); - bool evaluate(const qpid::types::Variant::Map& data) const; - private: - LogicalOp logicalOp; - BooleanOp boolOp; - int operandCount; - qpid::types::Variant operands[2]; - bool quoted[2]; - std::list<boost::shared_ptr<Expression> > expressionList; - - bool boolEval(const qpid::types::Variant::Map& data) const; - bool lessThan(const qpid::types::Variant& left, const qpid::types::Variant& right) const; - bool lessEqual(const qpid::types::Variant& left, const qpid::types::Variant& right) const; - bool greaterThan(const qpid::types::Variant& left, const qpid::types::Variant& right) const; - bool greaterEqual(const qpid::types::Variant& left, const qpid::types::Variant& right) const; - }; - -} - -#endif - diff --git a/cpp/src/qmf/Hash.cpp b/cpp/src/qmf/Hash.cpp deleted file mode 100644 index 86738dda2f..0000000000 --- a/cpp/src/qmf/Hash.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/Hash.h" - -using namespace qmf; - -Hash::Hash() -{ - data[0] = 0x5A5A5A5A5A5A5A5ALL; - data[1] = 0x5A5A5A5A5A5A5A5ALL; -} - -void Hash::update(const char* s, uint32_t len) -{ - uint64_t* first = &data[0]; - uint64_t* second = &data[1]; - - for (uint32_t idx = 0; idx < len; idx++) { - uint64_t recycle = ((*second & 0xff00000000000000LL) >> 56); - *second = *second << 8; - *second |= ((*first & 0xFF00000000000000LL) >> 56); - *first = *first << 8; - *first = *first + (uint64_t) s[idx] + recycle; - } -} - diff --git a/cpp/src/qmf/Hash.h b/cpp/src/qmf/Hash.h deleted file mode 100644 index e1eff84117..0000000000 --- a/cpp/src/qmf/Hash.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef QMF_HASH_H -#define QMF_HASH_H -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" -#include "qpid/types/Uuid.h" -#include <string> - -namespace qmf { - class Hash { - public: - Hash(); - qpid::types::Uuid asUuid() const { return qpid::types::Uuid((unsigned char*) data); } - void update(const char* s, uint32_t len); - void update(uint8_t v) { update((char*) &v, sizeof(v)); } - void update(uint32_t v) { update((char*) &v, sizeof(v)); } - void update(const std::string& v) { update(const_cast<char*>(v.c_str()), v.size()); } - void update(bool v) { update(uint8_t(v ? 1 : 0)); } - - private: - uint64_t data[2]; - }; -} - -#endif diff --git a/cpp/src/qmf/PrivateImplRef.h b/cpp/src/qmf/PrivateImplRef.h deleted file mode 100644 index 960cbb2e09..0000000000 --- a/cpp/src/qmf/PrivateImplRef.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef QMF_PRIVATEIMPL_H -#define QMF_PRIVATEIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/ImportExport.h" -#include "qpid/RefCounted.h" -#include <boost/intrusive_ptr.hpp> - -namespace qmf { - -/** - * Helper class to implement a class with a private, reference counted - * implementation and reference semantics. - * - * Such classes are used in the public API to hide implementation, they - * should. Example of use: - * - * === Foo.h - * - * template <class T> PrivateImplRef; - * class FooImpl; - * - * Foo : public Handle<FooImpl> { - * public: - * Foo(FooImpl* = 0); - * Foo(const Foo&); - * ~Foo(); - * Foo& operator=(const Foo&); - * - * int fooDo(); // and other Foo functions... - * - * private: - * typedef FooImpl Impl; - * Impl* impl; - * friend class PrivateImplRef<Foo>; - * - * === Foo.cpp - * - * typedef PrivateImplRef<Foo> PI; - * Foo::Foo(FooImpl* p) { PI::ctor(*this, p); } - * Foo::Foo(const Foo& c) : Handle<FooImpl>() { PI::copy(*this, c); } - * Foo::~Foo() { PI::dtor(*this); } - * Foo& Foo::operator=(const Foo& c) { return PI::assign(*this, c); } - * - * int foo::fooDo() { return impl->fooDo(); } - * - */ -template <class T> class PrivateImplRef { - public: - typedef typename T::Impl Impl; - typedef boost::intrusive_ptr<Impl> intrusive_ptr; - - /** Get the implementation pointer from a handle */ - static intrusive_ptr get(const T& t) { return intrusive_ptr(t.impl); } - - /** Set the implementation pointer in a handle */ - static void set(T& t, const intrusive_ptr& p) { - if (t.impl == p) return; - if (t.impl) boost::intrusive_ptr_release(t.impl); - t.impl = p.get(); - if (t.impl) boost::intrusive_ptr_add_ref(t.impl); - } - - // Helper functions to implement the ctor, dtor, copy, assign - static void ctor(T& t, Impl* p) { t.impl = p; if (p) boost::intrusive_ptr_add_ref(p); } - static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); } - static void dtor(T& t) { if(t.impl) boost::intrusive_ptr_release(t.impl); } - static T& assign(T& t, const T& x) { set(t, get(x)); return t;} -}; - -} // namespace qmf - -#endif /*!QMF_PRIVATEIMPL_H*/ diff --git a/cpp/src/qmf/Query.cpp b/cpp/src/qmf/Query.cpp deleted file mode 100644 index ee8ca38e59..0000000000 --- a/cpp/src/qmf/Query.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/QueryImpl.h" -#include "qmf/DataAddrImpl.h" -#include "qmf/SchemaIdImpl.h" -#include "qpid/messaging/AddressParser.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef<Query> PI; - -Query::Query(QueryImpl* impl) { PI::ctor(*this, impl); } -Query::Query(const Query& s) : qmf::Handle<QueryImpl>() { PI::copy(*this, s); } -Query::~Query() { PI::dtor(*this); } -Query& Query::operator=(const Query& s) { return PI::assign(*this, s); } - -Query::Query(QueryTarget t, const string& pr) { PI::ctor(*this, new QueryImpl(t, pr)); } -Query::Query(QueryTarget t, const string& c, const string& p, const string& pr) { PI::ctor(*this, new QueryImpl(t, c, p, pr)); } -Query::Query(QueryTarget t, const SchemaId& s, const string& pr) { PI::ctor(*this, new QueryImpl(t, s, pr)); } -Query::Query(const DataAddr& a) { PI::ctor(*this, new QueryImpl(a)); } - -QueryTarget Query::getTarget() const { return impl->getTarget(); } -const DataAddr& Query::getDataAddr() const { return impl->getDataAddr(); } -const SchemaId& Query::getSchemaId() const { return impl->getSchemaId(); } -void Query::setPredicate(const Variant::List& pr) { impl->setPredicate(pr); } -const Variant::List& Query::getPredicate() const { return impl->getPredicate(); } -bool Query::matchesPredicate(const qpid::types::Variant::Map& map) const { return impl->matchesPredicate(map); } - - -QueryImpl::QueryImpl(const Variant::Map& map) : predicateCompiled(false) -{ - Variant::Map::const_iterator iter; - - iter = map.find("_what"); - if (iter == map.end()) - throw QmfException("Query missing _what element"); - - const string& targetString(iter->second.asString()); - if (targetString == "OBJECT") target = QUERY_OBJECT; - else if (targetString == "OBJECT_ID") target = QUERY_OBJECT_ID; - else if (targetString == "SCHEMA") target = QUERY_SCHEMA; - else if (targetString == "SCHEMA_ID") target = QUERY_SCHEMA_ID; - else - throw QmfException("Query with invalid _what value: " + targetString); - - iter = map.find("_object_id"); - if (iter != map.end()) { - auto_ptr<DataAddrImpl> addrImpl(new DataAddrImpl(iter->second.asMap())); - dataAddr = DataAddr(addrImpl.release()); - } - - iter = map.find("_schema_id"); - if (iter != map.end()) { - auto_ptr<SchemaIdImpl> sidImpl(new SchemaIdImpl(iter->second.asMap())); - schemaId = SchemaId(sidImpl.release()); - } - - iter = map.find("_where"); - if (iter != map.end()) - predicate = iter->second.asList(); -} - - -Variant::Map QueryImpl::asMap() const -{ - Variant::Map map; - string targetString; - - switch (target) { - case QUERY_OBJECT : targetString = "OBJECT"; break; - case QUERY_OBJECT_ID : targetString = "OBJECT_ID"; break; - case QUERY_SCHEMA : targetString = "SCHEMA"; break; - case QUERY_SCHEMA_ID : targetString = "SCHEMA_ID"; break; - } - - map["_what"] = targetString; - - if (dataAddr.isValid()) - map["_object_id"] = DataAddrImplAccess::get(dataAddr).asMap(); - - if (schemaId.isValid()) - map["_schema_id"] = SchemaIdImplAccess::get(schemaId).asMap(); - - if (!predicate.empty()) - map["_where"] = predicate; - - return map; -} - - -bool QueryImpl::matchesPredicate(const qpid::types::Variant::Map& data) const -{ - if (predicate.empty()) - return true; - - if (!predicateCompiled) { - expression.reset(new Expression(predicate)); - predicateCompiled = true; - } - - return expression->evaluate(data); -} - - -void QueryImpl::parsePredicate(const string& pred) -{ - if (pred.empty()) - return; - - if (pred[0] == '[') { - // - // Parse this as an AddressParser list. - // - qpid::messaging::AddressParser parser(pred); - parser.parseList(predicate); - } else - throw QmfException("Invalid predicate format"); -} - - -QueryImpl& QueryImplAccess::get(Query& item) -{ - return *item.impl; -} - - -const QueryImpl& QueryImplAccess::get(const Query& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/QueryImpl.h b/cpp/src/qmf/QueryImpl.h deleted file mode 100644 index 27ec427684..0000000000 --- a/cpp/src/qmf/QueryImpl.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _QMF_QUERY_IMPL_H_ -#define _QMF_QUERY_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/Query.h" -#include "qmf/DataAddr.h" -#include "qmf/SchemaId.h" -#include "qmf/Expression.h" -#include "qpid/types/Variant.h" -#include <boost/shared_ptr.hpp> - -namespace qmf { - class QueryImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - QueryImpl(const qpid::types::Variant::Map&); - qpid::types::Variant::Map asMap() const; - - // - // Methods from API handle - // - QueryImpl(QueryTarget t, const std::string& pr) : target(t), predicateCompiled(false) { parsePredicate(pr); } - QueryImpl(QueryTarget t, const std::string& c, const std::string& p, const std::string& pr) : - target(t), schemaId(SCHEMA_TYPE_DATA, p, c), predicateCompiled(false) { parsePredicate(pr); } - QueryImpl(QueryTarget t, const SchemaId& s, const std::string& pr) : - target(t), schemaId(s), predicateCompiled(false) { parsePredicate(pr); } - QueryImpl(const DataAddr& a) : target(QUERY_OBJECT), dataAddr(a), predicateCompiled(false) {} - - QueryTarget getTarget() const { return target; } - const DataAddr& getDataAddr() const { return dataAddr; } - const SchemaId& getSchemaId() const { return schemaId; } - void setPredicate(const qpid::types::Variant::List& pr) { predicate = pr; } - const qpid::types::Variant::List& getPredicate() const { return predicate; } - bool matchesPredicate(const qpid::types::Variant::Map& map) const; - - private: - QueryTarget target; - SchemaId schemaId; - DataAddr dataAddr; - qpid::types::Variant::List predicate; - mutable bool predicateCompiled; - mutable boost::shared_ptr<Expression> expression; - - void parsePredicate(const std::string& s); - }; - - struct QueryImplAccess - { - static QueryImpl& get(Query&); - static const QueryImpl& get(const Query&); - }; -} - -#endif - diff --git a/cpp/src/qmf/Schema.cpp b/cpp/src/qmf/Schema.cpp deleted file mode 100644 index 872aad724c..0000000000 --- a/cpp/src/qmf/Schema.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/SchemaImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaIdImpl.h" -#include "qmf/SchemaPropertyImpl.h" -#include "qmf/SchemaMethodImpl.h" -#include "qmf/Hash.h" -#include "qpid/log/Statement.h" -#include "qpid/management/Buffer.h" -#include <list> - -using namespace std; -using qpid::types::Variant; -using namespace qmf; - -typedef PrivateImplRef<Schema> PI; - -Schema::Schema(SchemaImpl* impl) { PI::ctor(*this, impl); } -Schema::Schema(const Schema& s) : qmf::Handle<SchemaImpl>() { PI::copy(*this, s); } -Schema::~Schema() { PI::dtor(*this); } -Schema& Schema::operator=(const Schema& s) { return PI::assign(*this, s); } - -Schema::Schema(int t, const string& p, const string& c) { PI::ctor(*this, new SchemaImpl(t, p, c)); } -const SchemaId& Schema::getSchemaId() const { return impl->getSchemaId(); } -void Schema::finalize() { impl->finalize(); } -bool Schema::isFinalized() const { return impl->isFinalized(); } -void Schema::addProperty(const SchemaProperty& p) { impl->addProperty(p); } -void Schema::addMethod(const SchemaMethod& m) { impl->addMethod(m); } -void Schema::setDesc(const string& d) { impl->setDesc(d); } -const string& Schema::getDesc() const { return impl->getDesc(); } -void Schema::setDefaultSeverity(int s) { impl->setDefaultSeverity(s); } -int Schema::getDefaultSeverity() const { return impl->getDefaultSeverity(); } -uint32_t Schema::getPropertyCount() const { return impl->getPropertyCount(); } -SchemaProperty Schema::getProperty(uint32_t i) const { return impl->getProperty(i); } -uint32_t Schema::getMethodCount() const { return impl->getMethodCount(); } -SchemaMethod Schema::getMethod(uint32_t i) const { return impl->getMethod(i); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -SchemaImpl::SchemaImpl(const Variant::Map& map) : finalized(false) -{ - Variant::Map::const_iterator iter; - Variant::List::const_iterator lIter; - - iter = map.find("_schema_id"); - if (iter == map.end()) - throw QmfException("Schema map missing _schema_id element"); - schemaId = SchemaId(new SchemaIdImpl(iter->second.asMap())); - - iter = map.find("_desc"); - if (iter != map.end()) - description = iter->second.asString(); - - iter = map.find("_default_severity"); - if (iter != map.end()) - defaultSeverity = int(iter->second.asUint32()); - - iter = map.find("_properties"); - if (iter != map.end()) { - const Variant::List& props(iter->second.asList()); - for (lIter = props.begin(); lIter != props.end(); lIter++) - addProperty(SchemaProperty(new SchemaPropertyImpl(lIter->asMap()))); - } - - iter = map.find("_methods"); - if (iter != map.end()) { - const Variant::List& meths(iter->second.asList()); - for (lIter = meths.begin(); lIter != meths.end(); lIter++) - addMethod(SchemaMethod(new SchemaMethodImpl(lIter->asMap()))); - } - - finalized = true; -} - - -Variant::Map SchemaImpl::asMap() const -{ - Variant::Map map; - Variant::List propList; - Variant::List methList; - - checkNotFinal(); - - map["_schema_id"] = SchemaIdImplAccess::get(schemaId).asMap(); - if (!description.empty()) - map["_desc"] = description; - if (schemaId.getType() == SCHEMA_TYPE_EVENT) - map["_default_severity"] = uint32_t(defaultSeverity); - - for (list<SchemaProperty>::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++) - propList.push_back(SchemaPropertyImplAccess::get(*pIter).asMap()); - - for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) - methList.push_back(SchemaMethodImplAccess::get(*mIter).asMap()); - - map["_properties"] = propList; - map["_methods"] = methList; - return map; -} - - -SchemaImpl::SchemaImpl(qpid::management::Buffer& buffer) : finalized(false) -{ - int schemaType; - string packageName; - string className; - uint8_t hash[16]; - - schemaType = int(buffer.getOctet()); - buffer.getShortString(packageName); - buffer.getShortString(className); - buffer.getBin128(hash); - schemaId = SchemaId(schemaType, packageName, className); - schemaId.setHash(qpid::types::Uuid(hash)); - - if (schemaType == SCHEMA_TYPE_DATA) { - uint16_t propCount(buffer.getShort()); - uint16_t statCount(buffer.getShort()); - uint16_t methCount(buffer.getShort()); - for (uint16_t idx = 0; idx < propCount + statCount; idx++) - addProperty(new SchemaPropertyImpl(buffer)); - for (uint16_t idx = 0; idx < methCount; idx++) - addMethod(new SchemaMethodImpl(buffer)); - } - - finalized = true; -} - - -string SchemaImpl::asV1Content(uint32_t sequence) const -{ -#define RAW_BUF_SIZE 65536 - char rawBuf[RAW_BUF_SIZE]; - qpid::management::Buffer buffer(rawBuf, RAW_BUF_SIZE); - - // - // Encode the QMFv1 Header - // - buffer.putOctet('A'); - buffer.putOctet('M'); - buffer.putOctet('2'); - buffer.putOctet('s'); - buffer.putLong(sequence); - - // - // Encode the common schema information - // - buffer.putOctet(uint8_t(schemaId.getType())); - buffer.putShortString(schemaId.getPackageName()); - buffer.putShortString(schemaId.getName()); - buffer.putBin128(schemaId.getHash().data()); - - if (schemaId.getType() == SCHEMA_TYPE_DATA) { - buffer.putShort(properties.size()); - buffer.putShort(0); - buffer.putShort(methods.size()); - for (list<SchemaProperty>::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++) - SchemaPropertyImplAccess::get(*pIter).encodeV1(buffer, false, false); - for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) - SchemaMethodImplAccess::get(*mIter).encodeV1(buffer); - } else { - buffer.putShort(properties.size()); - for (list<SchemaProperty>::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++) - SchemaPropertyImplAccess::get(*pIter).encodeV1(buffer, true, false); - } - - return string(rawBuf, buffer.getPosition()); -} - - -bool SchemaImpl::isValidProperty(const std::string& k, const Variant& v) const -{ - for (list<SchemaProperty>::const_iterator iter = properties.begin(); iter != properties.end(); iter++) - if (iter->getName() == k) - return (isCompatibleType(iter->getType(), v.getType())); - return false; -} - - -bool SchemaImpl::isValidMethodInArg(const std::string& m, const std::string& k, const Variant& v) const -{ - for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) { - if (mIter->getName() == m) { - uint32_t count(mIter->getArgumentCount()); - for (uint32_t i = 0; i < count; i++) { - const SchemaProperty prop(mIter->getArgument(i)); - if (prop.getName() == k) { - if (prop.getDirection() == DIR_IN || prop.getDirection() == DIR_IN_OUT) - return (isCompatibleType(prop.getType(), v.getType())); - else - return false; - } - } - } - } - return false; -} - - -bool SchemaImpl::isValidMethodOutArg(const std::string& m, const std::string& k, const Variant& v) const -{ - for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) { - if (mIter->getName() == m) { - uint32_t count(mIter->getArgumentCount()); - for (uint32_t i = 0; i < count; i++) { - const SchemaProperty prop(mIter->getArgument(i)); - if (prop.getName() == k) { - if (prop.getDirection() == DIR_OUT || prop.getDirection() == DIR_IN_OUT) - return (isCompatibleType(prop.getType(), v.getType())); - else - return false; - } - } - } - } - return false; -} - - -void SchemaImpl::finalize() -{ - Hash hash; - - hash.update((uint8_t) schemaId.getType()); - hash.update(schemaId.getPackageName()); - hash.update(schemaId.getName()); - - for (list<SchemaProperty>::const_iterator pIter = properties.begin(); pIter != properties.end(); pIter++) - SchemaPropertyImplAccess::get(*pIter).updateHash(hash); - for (list<SchemaMethod>::const_iterator mIter = methods.begin(); mIter != methods.end(); mIter++) - SchemaMethodImplAccess::get(*mIter).updateHash(hash); - - schemaId.setHash(hash.asUuid()); - QPID_LOG(debug, "Schema Finalized: " << schemaId.getPackageName() << ":" << schemaId.getName() << ":" << - schemaId.getHash()); - - finalized = true; -} - - -SchemaProperty SchemaImpl::getProperty(uint32_t i) const -{ - uint32_t count = 0; - for (list<SchemaProperty>::const_iterator iter = properties.begin(); iter != properties.end(); iter++) - if (count++ == i) - return *iter; - throw IndexOutOfRange(); -} - - -SchemaMethod SchemaImpl::getMethod(uint32_t i) const -{ - uint32_t count = 0; - for (list<SchemaMethod>::const_iterator iter = methods.begin(); iter != methods.end(); iter++) - if (count++ == i) - return *iter; - throw IndexOutOfRange(); -} - -void SchemaImpl::checkFinal() const -{ - if (finalized) - throw QmfException("Modification of a finalized schema is forbidden"); -} - - -void SchemaImpl::checkNotFinal() const -{ - if (!finalized) - throw QmfException("Schema is not yet finalized/registered"); -} - - -bool SchemaImpl::isCompatibleType(int qmfType, qpid::types::VariantType qpidType) const -{ - bool typeValid(false); - - switch (qpidType) { - case qpid::types::VAR_VOID: - if (qmfType == SCHEMA_DATA_VOID) - typeValid = true; - break; - case qpid::types::VAR_BOOL: - if (qmfType == SCHEMA_DATA_BOOL) - typeValid = true; - break; - case qpid::types::VAR_UINT8: - case qpid::types::VAR_UINT16: - case qpid::types::VAR_UINT32: - case qpid::types::VAR_UINT64: - case qpid::types::VAR_INT8: - case qpid::types::VAR_INT16: - case qpid::types::VAR_INT32: - case qpid::types::VAR_INT64: - if (qmfType == SCHEMA_DATA_INT) - typeValid = true; - break; - case qpid::types::VAR_FLOAT: - case qpid::types::VAR_DOUBLE: - if (qmfType == SCHEMA_DATA_FLOAT) - typeValid = true; - break; - case qpid::types::VAR_STRING: - if (qmfType == SCHEMA_DATA_STRING) - typeValid = true; - break; - case qpid::types::VAR_MAP: - if (qmfType == SCHEMA_DATA_MAP) - typeValid = true; - break; - case qpid::types::VAR_LIST: - if (qmfType == SCHEMA_DATA_LIST) - typeValid = true; - break; - case qpid::types::VAR_UUID: - if (qmfType == SCHEMA_DATA_UUID) - typeValid = true; - break; - } - - return typeValid; -} - - -SchemaImpl& SchemaImplAccess::get(Schema& item) -{ - return *item.impl; -} - - -const SchemaImpl& SchemaImplAccess::get(const Schema& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/SchemaCache.cpp b/cpp/src/qmf/SchemaCache.cpp deleted file mode 100644 index 74ca4044fd..0000000000 --- a/cpp/src/qmf/SchemaCache.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/SchemaCache.h" -#include "qmf/exceptions.h" - -using namespace std; -using namespace qmf; - -bool SchemaCache::declareSchemaId(const SchemaId& id) -{ - qpid::sys::Mutex::ScopedLock l(lock); - SchemaMap::const_iterator iter = schemata.find(id); - if (iter == schemata.end()) { - schemata[id] = Schema(); - return false; - } - return true; -} - - -void SchemaCache::declareSchema(const Schema& schema) -{ - qpid::sys::Mutex::ScopedLock l(lock); - SchemaMap::const_iterator iter = schemata.find(schema.getSchemaId()); - if (iter == schemata.end() || !iter->second.isValid()) { - schemata[schema.getSchemaId()] = schema; - - // - // If there are any threads blocking in SchemaCache::getSchema waiting for - // this schema, unblock them all now. - // - CondMap::iterator cIter = conditions.find(schema.getSchemaId()); - if (cIter != conditions.end()) - cIter->second->notifyAll(); - } -} - - -bool SchemaCache::haveSchema(const SchemaId& id) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - SchemaMap::const_iterator iter = schemata.find(id); - return iter != schemata.end() && iter->second.isValid(); -} - - -const Schema& SchemaCache::getSchema(const SchemaId& id, qpid::messaging::Duration timeout) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - SchemaMap::const_iterator iter = schemata.find(id); - if (iter != schemata.end() && iter->second.isValid()) - return iter->second; - - // - // The desired schema is not in the cache. Assume that the caller knows this and has - // sent a schema request to the remote agent and now wishes to wait until the schema - // information arrives. - // - CondMap::iterator cIter = conditions.find(id); - if (cIter == conditions.end()) - conditions[id] = boost::shared_ptr<qpid::sys::Condition>(new qpid::sys::Condition()); - - uint64_t milliseconds = timeout.getMilliseconds(); - conditions[id]->wait(lock, qpid::sys::AbsTime(qpid::sys::now(), - qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC))); - iter = schemata.find(id); - if (iter != schemata.end() && iter->second.isValid()) - return iter->second; - - throw QmfException("Schema lookup timed out"); -} - diff --git a/cpp/src/qmf/SchemaCache.h b/cpp/src/qmf/SchemaCache.h deleted file mode 100644 index a1f104233f..0000000000 --- a/cpp/src/qmf/SchemaCache.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef QMF_SCHEMA_CACHE_H -#define QMF_SCHEMA_CACHE_H -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/SchemaIdImpl.h" -#include "qmf/Schema.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Condition.h" -#include "qpid/messaging/Duration.h" -#include <string> -#include <map> -#include <boost/shared_ptr.hpp> - -namespace qmf { - - class SchemaCache { - public: - SchemaCache() {} - ~SchemaCache() {} - - bool declareSchemaId(const SchemaId&); - void declareSchema(const Schema&); - bool haveSchema(const SchemaId&) const; - const Schema& getSchema(const SchemaId&, qpid::messaging::Duration) const; - - private: - mutable qpid::sys::Mutex lock; - typedef std::map<SchemaId, Schema, SchemaIdCompare> SchemaMap; - typedef std::map<SchemaId, boost::shared_ptr<qpid::sys::Condition>, SchemaIdCompare> CondMap; - SchemaMap schemata; - mutable CondMap conditions; - }; - -} - -#endif - diff --git a/cpp/src/qmf/SchemaId.cpp b/cpp/src/qmf/SchemaId.cpp deleted file mode 100644 index 25fa9915ae..0000000000 --- a/cpp/src/qmf/SchemaId.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/SchemaIdImpl.h" -#include "qmf/PrivateImplRef.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef<SchemaId> PI; - -SchemaId::SchemaId(SchemaIdImpl* impl) { PI::ctor(*this, impl); } -SchemaId::SchemaId(const SchemaId& s) : qmf::Handle<SchemaIdImpl>() { PI::copy(*this, s); } -SchemaId::~SchemaId() { PI::dtor(*this); } -SchemaId& SchemaId::operator=(const SchemaId& s) { return PI::assign(*this, s); } - -SchemaId::SchemaId(int t, const string& p, const string& n) { PI::ctor(*this, new SchemaIdImpl(t, p, n)); } -void SchemaId::setHash(const qpid::types::Uuid& h) { impl->setHash(h); } -int SchemaId::getType() const { return impl->getType(); } -const string& SchemaId::getPackageName() const { return impl->getPackageName(); } -const string& SchemaId::getName() const { return impl->getName(); } -const qpid::types::Uuid& SchemaId::getHash() const { return impl->getHash(); } - - -SchemaIdImpl::SchemaIdImpl(const Variant::Map& map) -{ - Variant::Map::const_iterator iter; - - iter = map.find("_package_name"); - if (iter != map.end()) - package = iter->second.asString(); - - iter = map.find("_class_name"); - if (iter != map.end()) - name = iter->second.asString(); - - iter = map.find("_type"); - if (iter != map.end()) { - const string& stype = iter->second.asString(); - if (stype == "_data") - sType = SCHEMA_TYPE_DATA; - else if (stype == "_event") - sType = SCHEMA_TYPE_EVENT; - } - - iter = map.find("_hash"); - if (iter != map.end()) - hash = iter->second.asUuid(); -} - - -Variant::Map SchemaIdImpl::asMap() const -{ - Variant::Map result; - - result["_package_name"] = package; - result["_class_name"] = name; - if (sType == SCHEMA_TYPE_DATA) - result["_type"] = "_data"; - else - result["_type"] = "_event"; - if (!hash.isNull()) - result["_hash"] = hash; - return result; -} - - -SchemaIdImpl& SchemaIdImplAccess::get(SchemaId& item) -{ - return *item.impl; -} - - -const SchemaIdImpl& SchemaIdImplAccess::get(const SchemaId& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/SchemaIdImpl.h b/cpp/src/qmf/SchemaIdImpl.h deleted file mode 100644 index ae1a3d8d3b..0000000000 --- a/cpp/src/qmf/SchemaIdImpl.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef _QMF_SCHEMA_ID_IMPL_H_ -#define _QMF_SCHEMA_ID_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/SchemaId.h" -#include "qpid/types/Variant.h" -#include "qpid/types/Uuid.h" -#include <string> - -namespace qmf { - class SchemaIdImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - SchemaIdImpl(const qpid::types::Variant::Map&); - qpid::types::Variant::Map asMap() const; - - // - // Methods from API handle - // - SchemaIdImpl(int t, const std::string& p, const std::string& n) : sType(t), package(p), name(n) {} - void setHash(const qpid::types::Uuid& h) { hash = h; } - int getType() const { return sType; } - const std::string& getPackageName() const { return package; } - const std::string& getName() const { return name; } - const qpid::types::Uuid& getHash() const { return hash; } - - private: - int sType; - std::string package; - std::string name; - qpid::types::Uuid hash; - }; - - struct SchemaIdImplAccess - { - static SchemaIdImpl& get(SchemaId&); - static const SchemaIdImpl& get(const SchemaId&); - }; - - struct SchemaIdCompare { - bool operator() (const SchemaId& lhs, const SchemaId& rhs) const - { - if (lhs.getName() != rhs.getName()) - return lhs.getName() < rhs.getName(); - if (lhs.getPackageName() != rhs.getPackageName()) - return lhs.getPackageName() < rhs.getPackageName(); - return lhs.getHash() < rhs.getHash(); - } - }; - - struct SchemaIdCompareNoHash { - bool operator() (const SchemaId& lhs, const SchemaId& rhs) const - { - if (lhs.getName() != rhs.getName()) - return lhs.getName() < rhs.getName(); - return lhs.getPackageName() < rhs.getPackageName(); - } - }; -} - -#endif diff --git a/cpp/src/qmf/SchemaImpl.h b/cpp/src/qmf/SchemaImpl.h deleted file mode 100644 index 1c88f87808..0000000000 --- a/cpp/src/qmf/SchemaImpl.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _QMF_SCHEMAIMPL_H_ -#define _QMF_SCHEMAIMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaId.h" -#include "qmf/Schema.h" -#include "qmf/SchemaProperty.h" -#include "qmf/SchemaMethod.h" -#include <list> - -namespace qpid { -namespace management { - class Buffer; -}} - -namespace qmf { - class SchemaImpl : public virtual qpid::RefCounted { - public: - // - // Impl-only public methods - // - SchemaImpl(const qpid::types::Variant::Map& m); - qpid::types::Variant::Map asMap() const; - SchemaImpl(qpid::management::Buffer& v1Buffer); - std::string asV1Content(uint32_t sequence) const; - bool isValidProperty(const std::string& k, const qpid::types::Variant& v) const; - bool isValidMethodInArg(const std::string& m, const std::string& k, const qpid::types::Variant& v) const; - bool isValidMethodOutArg(const std::string& m, const std::string& k, const qpid::types::Variant& v) const; - - // - // Methods from API handle - // - SchemaImpl(int t, const std::string& p, const std::string& c) : schemaId(t, p, c), finalized(false) {} - const SchemaId& getSchemaId() const { checkNotFinal(); return schemaId; } - - void finalize(); - bool isFinalized() const { return finalized; } - void addProperty(const SchemaProperty& p) { checkFinal(); properties.push_back(p); } - void addMethod(const SchemaMethod& m) { checkFinal(); methods.push_back(m); } - - void setDesc(const std::string& d) { description = d; } - const std::string& getDesc() const { return description; } - - void setDefaultSeverity(int s) { checkFinal(); defaultSeverity = s; } - int getDefaultSeverity() const { return defaultSeverity; } - - uint32_t getPropertyCount() const { return properties.size(); } - SchemaProperty getProperty(uint32_t i) const; - - uint32_t getMethodCount() const { return methods.size(); } - SchemaMethod getMethod(uint32_t i) const; - private: - SchemaId schemaId; - int defaultSeverity; - std::string description; - bool finalized; - std::list<SchemaProperty> properties; - std::list<SchemaMethod> methods; - - void checkFinal() const; - void checkNotFinal() const; - bool isCompatibleType(int qmfType, qpid::types::VariantType qpidType) const; - }; - - struct SchemaImplAccess - { - static SchemaImpl& get(Schema&); - static const SchemaImpl& get(const Schema&); - }; -} - -#endif diff --git a/cpp/src/qmf/SchemaMethod.cpp b/cpp/src/qmf/SchemaMethod.cpp deleted file mode 100644 index e267878238..0000000000 --- a/cpp/src/qmf/SchemaMethod.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/SchemaMethodImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/Hash.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/management/Buffer.h" - -using namespace std; -using qpid::types::Variant; -using namespace qmf; - -typedef PrivateImplRef<SchemaMethod> PI; - -SchemaMethod::SchemaMethod(SchemaMethodImpl* impl) { PI::ctor(*this, impl); } -SchemaMethod::SchemaMethod(const SchemaMethod& s) : qmf::Handle<SchemaMethodImpl>() { PI::copy(*this, s); } -SchemaMethod::~SchemaMethod() { PI::dtor(*this); } -SchemaMethod& SchemaMethod::operator=(const SchemaMethod& s) { return PI::assign(*this, s); } - -SchemaMethod::SchemaMethod(const string& n, const string& o) { PI::ctor(*this, new SchemaMethodImpl(n, o)); } -void SchemaMethod::setDesc(const string& d) { impl->setDesc(d); } -void SchemaMethod::addArgument(const SchemaProperty& p) { impl->addArgument(p); } -const string& SchemaMethod::getName() const { return impl->getName(); } -const string& SchemaMethod::getDesc() const { return impl->getDesc(); } -uint32_t SchemaMethod::getArgumentCount() const { return impl->getArgumentCount(); } -SchemaProperty SchemaMethod::getArgument(uint32_t i) const { return impl->getArgument(i); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -SchemaMethodImpl::SchemaMethodImpl(const string& n, const string& options) : name(n) -{ - if (!options.empty()) { - qpid::messaging::AddressParser parser = qpid::messaging::AddressParser(options); - Variant::Map optMap; - Variant::Map::iterator iter; - - parser.parseMap(optMap); - iter = optMap.find("desc"); - if (iter != optMap.end()) { - desc = iter->second.asString(); - optMap.erase(iter); - } - - if (!optMap.empty()) - throw QmfException("Unrecognized option: " + optMap.begin()->first); - } -} - - -SchemaMethodImpl::SchemaMethodImpl(const qpid::types::Variant::Map& map) -{ - Variant::Map::const_iterator iter; - Variant::List::const_iterator lIter; - - iter = map.find("_name"); - if (iter == map.end()) - throw QmfException("SchemaMethod without a _name element"); - name = iter->second.asString(); - - iter = map.find("_desc"); - if (iter != map.end()) - desc = iter->second.asString(); - - iter = map.find("_arguments"); - if (iter != map.end()) { - const Variant::List& argList(iter->second.asList()); - for (lIter = argList.begin(); lIter != argList.end(); lIter++) - addArgument(SchemaProperty(new SchemaPropertyImpl(lIter->asMap()))); - } -} - - -Variant::Map SchemaMethodImpl::asMap() const -{ - Variant::Map map; - Variant::List argList; - - map["_name"] = name; - - if (!desc.empty()) - map["_desc"] = desc; - - for (list<SchemaProperty>::const_iterator iter = arguments.begin(); iter != arguments.end(); iter++) - argList.push_back(SchemaPropertyImplAccess::get(*iter).asMap()); - map["_arguments"] = argList; - - return map; -} - - -SchemaMethodImpl::SchemaMethodImpl(qpid::management::Buffer& buffer) -{ - Variant::Map::const_iterator iter; - Variant::Map argMap; - - buffer.getMap(argMap); - - iter = argMap.find("name"); - if (iter == argMap.end()) - throw QmfException("Received V1 Method without a name"); - name = iter->second.asString(); - - iter = argMap.find("desc"); - if (iter != argMap.end()) - desc = iter->second.asString(); - - iter = argMap.find("argCount"); - if (iter == argMap.end()) - throw QmfException("Received V1 Method without argCount"); - - int64_t count = iter->second.asInt64(); - for (int idx = 0; idx < count; idx++) { - SchemaProperty arg(new SchemaPropertyImpl(buffer)); - addArgument(arg); - } -} - - -SchemaProperty SchemaMethodImpl::getArgument(uint32_t i) const -{ - uint32_t count = 0; - for (list<SchemaProperty>::const_iterator iter = arguments.begin(); iter != arguments.end(); iter++) - if (count++ == i) - return *iter; - - throw IndexOutOfRange(); -} - - -void SchemaMethodImpl::updateHash(Hash& hash) const -{ - hash.update(name); - hash.update(desc); - for (list<SchemaProperty>::const_iterator iter = arguments.begin(); iter != arguments.end(); iter++) - SchemaPropertyImplAccess::get(*iter).updateHash(hash); -} - - -void SchemaMethodImpl::encodeV1(qpid::management::Buffer& buffer) const -{ - Variant::Map map; - - map["name"] = name; - map["argCount"] = (uint64_t) arguments.size(); - if (!desc.empty()) - map["desc"] = desc; - - buffer.putMap(map); - - for (list<SchemaProperty>::const_iterator iter = arguments.begin(); iter != arguments.end(); iter++) - SchemaPropertyImplAccess::get(*iter).encodeV1(buffer, true, true); -} - - -SchemaMethodImpl& SchemaMethodImplAccess::get(SchemaMethod& item) -{ - return *item.impl; -} - - -const SchemaMethodImpl& SchemaMethodImplAccess::get(const SchemaMethod& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/SchemaMethodImpl.h b/cpp/src/qmf/SchemaMethodImpl.h deleted file mode 100644 index 930d48509c..0000000000 --- a/cpp/src/qmf/SchemaMethodImpl.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _QMF_SCHEMA_METHOD_IMPL_H_ -#define _QMF_SCHEMA_METHOD_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaMethod.h" -#include "qmf/SchemaPropertyImpl.h" -#include "qpid/management/Buffer.h" -#include <list> -#include <string> - -namespace qpid { -namespace management { - class Buffer; -}} - -namespace qmf { - class Hash; - class SchemaMethodImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - SchemaMethodImpl(const qpid::types::Variant::Map& m); - SchemaMethodImpl(qpid::management::Buffer& v1Buffer); - qpid::types::Variant::Map asMap() const; - void updateHash(Hash&) const; - void encodeV1(qpid::management::Buffer&) const; - - // - // Methods from API handle - // - SchemaMethodImpl(const std::string& n, const std::string& options); - - void setDesc(const std::string& d) { desc = d; } - void addArgument(const SchemaProperty& p) { arguments.push_back(p); } - const std::string& getName() const { return name; } - const std::string& getDesc() const { return desc; } - uint32_t getArgumentCount() const { return arguments.size(); } - SchemaProperty getArgument(uint32_t i) const; - - private: - std::string name; - std::string desc; - std::list<SchemaProperty> arguments; - }; - - struct SchemaMethodImplAccess - { - static SchemaMethodImpl& get(SchemaMethod&); - static const SchemaMethodImpl& get(const SchemaMethod&); - }; -} - -#endif diff --git a/cpp/src/qmf/SchemaProperty.cpp b/cpp/src/qmf/SchemaProperty.cpp deleted file mode 100644 index 106127261b..0000000000 --- a/cpp/src/qmf/SchemaProperty.cpp +++ /dev/null @@ -1,434 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/SchemaPropertyImpl.h" -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaProperty.h" -#include "qmf/Hash.h" -#include "qpid/messaging/AddressParser.h" -#include <list> -#include <iostream> - -using namespace std; -using qpid::types::Variant; -using namespace qmf; - -typedef PrivateImplRef<SchemaProperty> PI; - -SchemaProperty::SchemaProperty(SchemaPropertyImpl* impl) { PI::ctor(*this, impl); } -SchemaProperty::SchemaProperty(const SchemaProperty& s) : qmf::Handle<SchemaPropertyImpl>() { PI::copy(*this, s); } -SchemaProperty::~SchemaProperty() { PI::dtor(*this); } -SchemaProperty& SchemaProperty::operator=(const SchemaProperty& s) { return PI::assign(*this, s); } - -SchemaProperty::SchemaProperty(const string& n, int t, const string& o) { PI::ctor(*this, new SchemaPropertyImpl(n, t, o)); } - -void SchemaProperty::setAccess(int a) { impl->setAccess(a); } -void SchemaProperty::setIndex(bool i) { impl->setIndex(i); } -void SchemaProperty::setOptional(bool o) { impl->setOptional(o); } -void SchemaProperty::setUnit(const string& u) { impl->setUnit(u); } -void SchemaProperty::setDesc(const string& d) { impl->setDesc(d); } -void SchemaProperty::setSubtype(const string& s) { impl->setSubtype(s); } -void SchemaProperty::setDirection(int d) { impl->setDirection(d); } - -const string& SchemaProperty::getName() const { return impl->getName(); } -int SchemaProperty::getType() const { return impl->getType(); } -int SchemaProperty::getAccess() const { return impl->getAccess(); } -bool SchemaProperty::isIndex() const { return impl->isIndex(); } -bool SchemaProperty::isOptional() const { return impl->isOptional(); } -const string& SchemaProperty::getUnit() const { return impl->getUnit(); } -const string& SchemaProperty::getDesc() const { return impl->getDesc(); } -const string& SchemaProperty::getSubtype() const { return impl->getSubtype(); } -int SchemaProperty::getDirection() const { return impl->getDirection(); } - -//======================================================================================== -// Impl Method Bodies -//======================================================================================== - -SchemaPropertyImpl::SchemaPropertyImpl(const string& n, int t, const string options) : - name(n), dataType(t), access(ACCESS_READ_ONLY), index(false), - optional(false), direction(DIR_IN) -{ - if (!options.empty()) { - qpid::messaging::AddressParser parser = qpid::messaging::AddressParser(options); - Variant::Map optMap; - Variant::Map::iterator iter; - - parser.parseMap(optMap); - - iter = optMap.find("access"); - if (iter != optMap.end()) { - const string& v(iter->second.asString()); - if (v == "RC") access = ACCESS_READ_CREATE; - else if (v == "RO") access = ACCESS_READ_ONLY; - else if (v == "RW") access = ACCESS_READ_WRITE; - else - throw QmfException("Invalid value for 'access' option. Expected RC, RO, or RW"); - optMap.erase(iter); - } - - iter = optMap.find("index"); - if (iter != optMap.end()) { - index = iter->second.asBool(); - optMap.erase(iter); - } - - iter = optMap.find("optional"); - if (iter != optMap.end()) { - optional = iter->second.asBool(); - optMap.erase(iter); - } - - iter = optMap.find("unit"); - if (iter != optMap.end()) { - unit = iter->second.asString(); - optMap.erase(iter); - } - - iter = optMap.find("desc"); - if (iter != optMap.end()) { - desc = iter->second.asString(); - optMap.erase(iter); - } - - iter = optMap.find("subtype"); - if (iter != optMap.end()) { - subtype = iter->second.asString(); - optMap.erase(iter); - } - - iter = optMap.find("dir"); - if (iter != optMap.end()) { - const string& v(iter->second.asString()); - if (v == "IN") direction = DIR_IN; - else if (v == "OUT") direction = DIR_OUT; - else if (v == "INOUT") direction = DIR_IN_OUT; - else - throw QmfException("Invalid value for 'dir' option. Expected IN, OUT, or INOUT"); - optMap.erase(iter); - } - - if (!optMap.empty()) - throw QmfException("Unexpected option: " + optMap.begin()->first); - } -} - - -SchemaPropertyImpl::SchemaPropertyImpl(const Variant::Map& map) : - access(ACCESS_READ_ONLY), index(false), optional(false), direction(DIR_IN) -{ - Variant::Map::const_iterator iter; - - iter = map.find("_name"); - if (iter == map.end()) - throw QmfException("SchemaProperty without a _name element"); - name = iter->second.asString(); - - iter = map.find("_type"); - if (iter == map.end()) - throw QmfException("SchemaProperty without a _type element"); - const string& ts(iter->second.asString()); - if (ts == "TYPE_VOID") dataType = SCHEMA_DATA_VOID; - else if (ts == "TYPE_BOOL") dataType = SCHEMA_DATA_BOOL; - else if (ts == "TYPE_INT") dataType = SCHEMA_DATA_INT; - else if (ts == "TYPE_FLOAT") dataType = SCHEMA_DATA_FLOAT; - else if (ts == "TYPE_STRING") dataType = SCHEMA_DATA_STRING; - else if (ts == "TYPE_MAP") dataType = SCHEMA_DATA_MAP; - else if (ts == "TYPE_LIST") dataType = SCHEMA_DATA_LIST; - else if (ts == "TYPE_UUID") dataType = SCHEMA_DATA_UUID; - else - throw QmfException("SchemaProperty with an invalid type code: " + ts); - - iter = map.find("_access"); - if (iter != map.end()) { - const string& as(iter->second.asString()); - if (as == "RO") access = ACCESS_READ_ONLY; - else if (as == "RC") access = ACCESS_READ_CREATE; - else if (as == "RW") access = ACCESS_READ_WRITE; - else - throw QmfException("SchemaProperty with an invalid access code: " + as); - } - - iter = map.find("_unit"); - if (iter != map.end()) - unit = iter->second.asString(); - - iter = map.find("_dir"); - if (iter != map.end()) { - const string& ds(iter->second.asString()); - if (ds == "I") direction = DIR_IN; - else if (ds == "O") direction = DIR_OUT; - else if (ds == "IO") direction = DIR_IN_OUT; - else - throw QmfException("SchemaProperty with an invalid direction code: " + ds); - } - - iter = map.find("_desc"); - if (iter != map.end()) - desc = iter->second.asString(); - - iter = map.find("_index"); - if (iter != map.end()) - index = iter->second.asBool(); - - iter = map.find("_subtype"); - if (iter != map.end()) - subtype = iter->second.asString(); -} - - -Variant::Map SchemaPropertyImpl::asMap() const -{ - Variant::Map map; - string ts; - - map["_name"] = name; - - switch (dataType) { - case SCHEMA_DATA_VOID: ts = "TYPE_VOID"; break; - case SCHEMA_DATA_BOOL: ts = "TYPE_BOOL"; break; - case SCHEMA_DATA_INT: ts = "TYPE_INT"; break; - case SCHEMA_DATA_FLOAT: ts = "TYPE_FLOAT"; break; - case SCHEMA_DATA_STRING: ts = "TYPE_STRING"; break; - case SCHEMA_DATA_MAP: ts = "TYPE_MAP"; break; - case SCHEMA_DATA_LIST: ts = "TYPE_LIST"; break; - case SCHEMA_DATA_UUID: ts = "TYPE_UUID"; break; - } - map["_type"] = ts; - - switch (access) { - case ACCESS_READ_ONLY: ts = "RO"; break; - case ACCESS_READ_CREATE: ts = "RC"; break; - case ACCESS_READ_WRITE: ts = "RW"; break; - } - map["_access"] = ts; - - if (!unit.empty()) - map["_unit"] = unit; - - switch (direction) { - case DIR_IN: ts = "I"; break; - case DIR_OUT: ts = "O"; break; - case DIR_IN_OUT: ts = "IO"; break; - } - map["_dir"] = ts; - - if (!desc.empty()) - map["_desc"] = desc; - - if (index) - map["_index"] = true; - - if (!subtype.empty()) - map["_subtype"] = subtype; - - return map; -} - - -SchemaPropertyImpl::SchemaPropertyImpl(qpid::management::Buffer& buffer) : - access(ACCESS_READ_ONLY), index(false), optional(false), direction(DIR_IN) -{ - Variant::Map::const_iterator iter; - Variant::Map pmap; - - buffer.getMap(pmap); - iter = pmap.find("name"); - if (iter == pmap.end()) - throw QmfException("Received V1 Schema property without a name"); - name = iter->second.asString(); - - iter = pmap.find("type"); - if (iter == pmap.end()) - throw QmfException("Received V1 Schema property without a type"); - fromV1TypeCode(iter->second.asInt8()); - - iter = pmap.find("unit"); - if (iter != pmap.end()) - unit = iter->second.asString(); - - iter = pmap.find("desc"); - if (iter != pmap.end()) - desc = iter->second.asString(); - - iter = pmap.find("access"); - if (iter != pmap.end()) { - int8_t val = iter->second.asInt8(); - if (val < 1 || val > 3) - throw QmfException("Received V1 Schema property with invalid 'access' code"); - access = val; - } - - iter = pmap.find("index"); - if (iter != pmap.end()) - index = iter->second.asInt64() != 0; - - iter = pmap.find("optional"); - if (iter != pmap.end()) - optional = iter->second.asInt64() != 0; - - iter = pmap.find("dir"); - if (iter != pmap.end()) { - string dirStr(iter->second.asString()); - if (dirStr == "I") direction = DIR_IN; - else if (dirStr == "O") direction = DIR_OUT; - else if (dirStr == "IO") direction = DIR_IN_OUT; - else - throw QmfException("Received V1 Schema property with invalid 'dir' code"); - } -} - - -void SchemaPropertyImpl::updateHash(Hash& hash) const -{ - hash.update(name); - hash.update((uint8_t) dataType); - hash.update(subtype); - hash.update((uint8_t) access); - hash.update(index); - hash.update(optional); - hash.update(unit); - hash.update(desc); - hash.update((uint8_t) direction); -} - - -void SchemaPropertyImpl::encodeV1(qpid::management::Buffer& buffer, bool isArg, bool isMethodArg) const -{ - Variant::Map pmap; - - pmap["name"] = name; - pmap["type"] = v1TypeCode(); - if (!unit.empty()) - pmap["unit"] = unit; - if (!desc.empty()) - pmap["desc"] = desc; - if (!isArg) { - pmap["access"] = access; - pmap["index"] = index ? 1 : 0; - pmap["optional"] = optional ? 1 : 0; - } else { - if (isMethodArg) { - string dirStr; - switch (direction) { - case DIR_IN : dirStr = "I"; break; - case DIR_OUT : dirStr = "O"; break; - case DIR_IN_OUT : dirStr = "IO"; break; - } - pmap["dir"] = dirStr; - } - } - - buffer.putMap(pmap); -} - - -uint8_t SchemaPropertyImpl::v1TypeCode() const -{ - switch (dataType) { - case SCHEMA_DATA_VOID: return 1; - case SCHEMA_DATA_BOOL: return 11; - case SCHEMA_DATA_INT: - if (subtype == "timestamp") return 8; - if (subtype == "duration") return 9; - return 19; - case SCHEMA_DATA_FLOAT: return 13; - case SCHEMA_DATA_STRING: return 7; - case SCHEMA_DATA_LIST: return 21; - case SCHEMA_DATA_UUID: return 14; - case SCHEMA_DATA_MAP: - if (subtype == "reference") return 10; - if (subtype == "data") return 20; - return 15; - } - - return 1; -} - -void SchemaPropertyImpl::fromV1TypeCode(int8_t code) -{ - switch (code) { - case 1: // U8 - case 2: // U16 - case 3: // U32 - case 4: // U64 - dataType = SCHEMA_DATA_INT; - break; - case 6: // SSTR - case 7: // LSTR - dataType = SCHEMA_DATA_STRING; - break; - case 8: // ABSTIME - dataType = SCHEMA_DATA_INT; - subtype = "timestamp"; - break; - case 9: // DELTATIME - dataType = SCHEMA_DATA_INT; - subtype = "duration"; - break; - case 10: // REF - dataType = SCHEMA_DATA_MAP; - subtype = "reference"; - break; - case 11: // BOOL - dataType = SCHEMA_DATA_BOOL; - break; - case 12: // FLOAT - case 13: // DOUBLE - dataType = SCHEMA_DATA_FLOAT; - break; - case 14: // UUID - dataType = SCHEMA_DATA_UUID; - break; - case 15: // FTABLE - dataType = SCHEMA_DATA_MAP; - break; - case 16: // S8 - case 17: // S16 - case 18: // S32 - case 19: // S64 - dataType = SCHEMA_DATA_INT; - break; - case 20: // OBJECT - dataType = SCHEMA_DATA_MAP; - subtype = "data"; - break; - case 21: // LIST - case 22: // ARRAY - dataType = SCHEMA_DATA_LIST; - break; - default: - throw QmfException("Received V1 schema with an unknown data type"); - } -} - - -SchemaPropertyImpl& SchemaPropertyImplAccess::get(SchemaProperty& item) -{ - return *item.impl; -} - - -const SchemaPropertyImpl& SchemaPropertyImplAccess::get(const SchemaProperty& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/SchemaPropertyImpl.h b/cpp/src/qmf/SchemaPropertyImpl.h deleted file mode 100644 index cdfc29066f..0000000000 --- a/cpp/src/qmf/SchemaPropertyImpl.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef _QMF_SCHEMA_PROPERTY_IMPL_H_ -#define _QMF_SCHEMA_PROPERTY_IMPL_H_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/SchemaTypes.h" -#include "qmf/SchemaProperty.h" -#include "qpid/types/Variant.h" -#include "qpid/management/Buffer.h" - -namespace qpid { -namespace management { - class Buffer; -}} - -namespace qmf { - class Hash; - class SchemaPropertyImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - SchemaPropertyImpl(const qpid::types::Variant::Map& m); - SchemaPropertyImpl(qpid::management::Buffer& v1Buffer); - qpid::types::Variant::Map asMap() const; - void updateHash(Hash&) const; - void encodeV1(qpid::management::Buffer&, bool isArg, bool isMethodArg) const; - - // - // Methods from API handle - // - SchemaPropertyImpl(const std::string& n, int t, const std::string o); - void setAccess(int a) { access = a; } - void setIndex(bool i) { index = i; } - void setOptional(bool o) { optional = o; } - void setUnit(const std::string& u) { unit = u; } - void setDesc(const std::string& d) { desc = d; } - void setSubtype(const std::string& s) { subtype = s; } - void setDirection(int d) { direction = d; } - - const std::string& getName() const { return name; } - int getType() const { return dataType; } - int getAccess() const { return access; } - bool isIndex() const { return index; } - bool isOptional() const { return optional; } - const std::string& getUnit() const { return unit; } - const std::string& getDesc() const { return desc; } - const std::string& getSubtype() const { return subtype; } - int getDirection() const { return direction; } - - private: - std::string name; - int dataType; - std::string subtype; - int access; - bool index; - bool optional; - std::string unit; - std::string desc; - int direction; - - uint8_t v1TypeCode() const; - void fromV1TypeCode(int8_t); - }; - - struct SchemaPropertyImplAccess - { - static SchemaPropertyImpl& get(SchemaProperty&); - static const SchemaPropertyImpl& get(const SchemaProperty&); - }; -} - -#endif diff --git a/cpp/src/qmf/Subscription.cpp b/cpp/src/qmf/Subscription.cpp deleted file mode 100644 index 73afc8c79d..0000000000 --- a/cpp/src/qmf/Subscription.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qmf/PrivateImplRef.h" -#include "qmf/exceptions.h" -#include "qmf/SubscriptionImpl.h" -#include "qmf/DataImpl.h" - -using namespace std; -using namespace qmf; -using qpid::types::Variant; - -typedef PrivateImplRef<Subscription> PI; - -Subscription::Subscription(SubscriptionImpl* impl) { PI::ctor(*this, impl); } -Subscription::Subscription(const Subscription& s) : qmf::Handle<SubscriptionImpl>() { PI::copy(*this, s); } -Subscription::~Subscription() { PI::dtor(*this); } -Subscription& Subscription::operator=(const Subscription& s) { return PI::assign(*this, s); } - -void Subscription::cancel() { impl->cancel(); } -bool Subscription::isActive() const { return impl->isActive(); } -void Subscription::lock() { impl->lock(); } -void Subscription::unlock() { impl->unlock(); } -uint32_t Subscription::getDataCount() const { return impl->getDataCount(); } -Data Subscription::getData(uint32_t i) const { return impl->getData(i); } - - -void SubscriptionImpl::cancel() -{ -} - - -bool SubscriptionImpl::isActive() const -{ - return false; -} - - -void SubscriptionImpl::lock() -{ -} - - -void SubscriptionImpl::unlock() -{ -} - - -uint32_t SubscriptionImpl::getDataCount() const -{ - return 0; -} - - -Data SubscriptionImpl::getData(uint32_t) const -{ - return Data(); -} - - -SubscriptionImpl& SubscriptionImplAccess::get(Subscription& item) -{ - return *item.impl; -} - - -const SubscriptionImpl& SubscriptionImplAccess::get(const Subscription& item) -{ - return *item.impl; -} diff --git a/cpp/src/qmf/SubscriptionImpl.h b/cpp/src/qmf/SubscriptionImpl.h deleted file mode 100644 index 053e3cd00e..0000000000 --- a/cpp/src/qmf/SubscriptionImpl.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _QMF_SUBSCRIPTION_IMPL_H_ -#define _QMF_SUBSCRIPTION_IMPL_H_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qmf/Subscription.h" - -namespace qmf { - class SubscriptionImpl : public virtual qpid::RefCounted { - public: - // - // Public impl-only methods - // - SubscriptionImpl(int p) : placeholder(p) {} - ~SubscriptionImpl(); - - // - // Methods from API handle - // - void cancel(); - bool isActive() const; - void lock(); - void unlock(); - uint32_t getDataCount() const; - Data getData(uint32_t) const; - - private: - int placeholder; - }; - - struct SubscriptionImplAccess - { - static SubscriptionImpl& get(Subscription&); - static const SubscriptionImpl& get(const Subscription&); - }; -} - -#endif diff --git a/cpp/src/qmf/agentCapability.h b/cpp/src/qmf/agentCapability.h deleted file mode 100644 index 6a3f6f8534..0000000000 --- a/cpp/src/qmf/agentCapability.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef QMF_AGENT_CAPABILITY_H -#define QMF_AGENT_CAPABILITY_H -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -namespace qmf { - - /** - * Legacy (Qpid 0.7 C++ Agent, 0.7 Broker Agent) capabilities - */ - const uint32_t AGENT_CAPABILITY_LEGACY = 0; - - /** - * Qpid 0.8 QMFv2 capabilities - */ - const uint32_t AGENT_CAPABILITY_0_8 = 1; - const uint32_t AGENT_CAPABILITY_V2_SCHEMA = 1; - const uint32_t AGENT_CAPABILITY_AGENT_PREDICATE = 1; -} - -#endif diff --git a/cpp/src/qmf/constants.cpp b/cpp/src/qmf/constants.cpp deleted file mode 100644 index 6e2fd935a9..0000000000 --- a/cpp/src/qmf/constants.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "constants.h" - -using namespace std; -using namespace qmf; - -/** - * Header key strings - */ -const string protocol::HEADER_KEY_APP_ID = "x-amqp-0-10.app-id"; -const string protocol::HEADER_KEY_METHOD = "method"; -const string protocol::HEADER_KEY_OPCODE = "qmf.opcode"; -const string protocol::HEADER_KEY_AGENT = "qmf.agent"; -const string protocol::HEADER_KEY_CONTENT = "qmf.content"; -const string protocol::HEADER_KEY_PARTIAL = "partial"; - -/** - * Header values per-key - */ -const string protocol::HEADER_APP_ID_QMF = "qmf2"; - -const string protocol::HEADER_METHOD_REQUEST = "request"; -const string protocol::HEADER_METHOD_RESPONSE = "response"; -const string protocol::HEADER_METHOD_INDICATION = "indication"; - -const string protocol::HEADER_OPCODE_EXCEPTION = "_exception"; -const string protocol::HEADER_OPCODE_AGENT_LOCATE_REQUEST = "_agent_locate_request"; -const string protocol::HEADER_OPCODE_AGENT_LOCATE_RESPONSE = "_agent_locate_response"; -const string protocol::HEADER_OPCODE_AGENT_HEARTBEAT_INDICATION = "_agent_heartbeat_indication"; -const string protocol::HEADER_OPCODE_QUERY_REQUEST = "_query_request"; -const string protocol::HEADER_OPCODE_QUERY_RESPONSE = "_query_response"; -const string protocol::HEADER_OPCODE_SUBSCRIBE_REQUEST = "_subscribe_request"; -const string protocol::HEADER_OPCODE_SUBSCRIBE_RESPONSE = "_subscribe_response"; -const string protocol::HEADER_OPCODE_SUBSCRIBE_CANCEL_INDICATION = "_subscribe_cancel_indication"; -const string protocol::HEADER_OPCODE_SUBSCRIBE_REFRESH_INDICATION = "_subscribe_refresh_indication"; -const string protocol::HEADER_OPCODE_DATA_INDICATION = "_data_indication"; -const string protocol::HEADER_OPCODE_METHOD_REQUEST = "_method_request"; -const string protocol::HEADER_OPCODE_METHOD_RESPONSE = "_method_response"; - -const string protocol::HEADER_CONTENT_SCHEMA_ID = "_schema_id"; -const string protocol::HEADER_CONTENT_SCHEMA_CLASS = "_schema_class"; -const string protocol::HEADER_CONTENT_OBJECT_ID = "_object_id"; -const string protocol::HEADER_CONTENT_DATA = "_data"; -const string protocol::HEADER_CONTENT_EVENT = "_event"; -const string protocol::HEADER_CONTENT_QUERY = "_query"; - -/** - * Keywords for Agent attributes - */ -const string protocol::AGENT_ATTR_VENDOR = "_vendor"; -const string protocol::AGENT_ATTR_PRODUCT = "_product"; -const string protocol::AGENT_ATTR_INSTANCE = "_instance"; -const string protocol::AGENT_ATTR_NAME = "_name"; -const string protocol::AGENT_ATTR_TIMESTAMP = "_timestamp"; -const string protocol::AGENT_ATTR_HEARTBEAT_INTERVAL = "_heartbeat_interval"; -const string protocol::AGENT_ATTR_EPOCH = "_epoch"; -const string protocol::AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP = "_schema_updated"; diff --git a/cpp/src/qmf/constants.h b/cpp/src/qmf/constants.h deleted file mode 100644 index 79beaaf1ca..0000000000 --- a/cpp/src/qmf/constants.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QMF_CONSTANTS_H -#define QMF_CONSTANTS_H -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> - -namespace qmf { - - struct protocol { - /** - * Header key strings - */ - static const std::string HEADER_KEY_APP_ID; - static const std::string HEADER_KEY_METHOD; - static const std::string HEADER_KEY_OPCODE; - static const std::string HEADER_KEY_AGENT; - static const std::string HEADER_KEY_CONTENT; - static const std::string HEADER_KEY_PARTIAL; - - /** - * Header values per-key - */ - static const std::string HEADER_APP_ID_QMF; - - static const std::string HEADER_METHOD_REQUEST; - static const std::string HEADER_METHOD_RESPONSE; - static const std::string HEADER_METHOD_INDICATION; - - static const std::string HEADER_OPCODE_EXCEPTION; - static const std::string HEADER_OPCODE_AGENT_LOCATE_REQUEST; - static const std::string HEADER_OPCODE_AGENT_LOCATE_RESPONSE; - static const std::string HEADER_OPCODE_AGENT_HEARTBEAT_INDICATION; - static const std::string HEADER_OPCODE_QUERY_REQUEST; - static const std::string HEADER_OPCODE_QUERY_RESPONSE; - static const std::string HEADER_OPCODE_SUBSCRIBE_REQUEST; - static const std::string HEADER_OPCODE_SUBSCRIBE_RESPONSE; - static const std::string HEADER_OPCODE_SUBSCRIBE_CANCEL_INDICATION; - static const std::string HEADER_OPCODE_SUBSCRIBE_REFRESH_INDICATION; - static const std::string HEADER_OPCODE_DATA_INDICATION; - static const std::string HEADER_OPCODE_METHOD_REQUEST; - static const std::string HEADER_OPCODE_METHOD_RESPONSE; - - static const std::string HEADER_CONTENT_SCHEMA_ID; - static const std::string HEADER_CONTENT_SCHEMA_CLASS; - static const std::string HEADER_CONTENT_OBJECT_ID; - static const std::string HEADER_CONTENT_DATA; - static const std::string HEADER_CONTENT_EVENT; - static const std::string HEADER_CONTENT_QUERY; - - /** - * Keywords for Agent attributes - */ - static const std::string AGENT_ATTR_VENDOR; - static const std::string AGENT_ATTR_PRODUCT; - static const std::string AGENT_ATTR_INSTANCE; - static const std::string AGENT_ATTR_NAME; - static const std::string AGENT_ATTR_TIMESTAMP; - static const std::string AGENT_ATTR_HEARTBEAT_INTERVAL; - static const std::string AGENT_ATTR_EPOCH; - static const std::string AGENT_ATTR_SCHEMA_UPDATED_TIMESTAMP; - }; -} - -#endif diff --git a/cpp/src/qmf/engine/Agent.cpp b/cpp/src/qmf/engine/Agent.cpp deleted file mode 100644 index 1f08dded94..0000000000 --- a/cpp/src/qmf/engine/Agent.cpp +++ /dev/null @@ -1,915 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/Agent.h" -#include "qmf/engine/MessageImpl.h" -#include "qmf/engine/SchemaImpl.h" -#include "qmf/engine/Typecode.h" -#include "qmf/engine/EventImpl.h" -#include "qmf/engine/ObjectImpl.h" -#include "qmf/engine/ObjectIdImpl.h" -#include "qmf/engine/QueryImpl.h" -#include "qmf/engine/ValueImpl.h" -#include "qmf/engine/Protocol.h" -#include <qpid/framing/Buffer.h> -#include <qpid/framing/Uuid.h> -#include <qpid/framing/FieldTable.h> -#include <qpid/framing/FieldValue.h> -#include <qpid/sys/Mutex.h> -#include <qpid/log/Statement.h> -#include <qpid/sys/Time.h> -#include <string.h> -#include <string> -#include <deque> -#include <map> -#include <iostream> -#include <fstream> -#include <boost/shared_ptr.hpp> -#include <boost/noncopyable.hpp> - -using namespace std; -using namespace qmf::engine; -using namespace qpid::framing; -using namespace qpid::sys; - -namespace qmf { -namespace engine { - - struct AgentEventImpl { - typedef boost::shared_ptr<AgentEventImpl> Ptr; - AgentEvent::EventKind kind; - uint32_t sequence; - string authUserId; - string authToken; - string name; - Object* object; - boost::shared_ptr<ObjectId> objectId; - boost::shared_ptr<Query> query; - boost::shared_ptr<Value> arguments; - string exchange; - string bindingKey; - const SchemaObjectClass* objectClass; - - AgentEventImpl(AgentEvent::EventKind k) : - kind(k), sequence(0), object(0), objectClass(0) {} - ~AgentEventImpl() {} - AgentEvent copy(); - }; - - struct AgentQueryContext { - typedef boost::shared_ptr<AgentQueryContext> Ptr; - uint32_t sequence; - string exchange; - string key; - const SchemaMethod* schemaMethod; - AgentQueryContext() : schemaMethod(0) {} - }; - - class AgentImpl : public boost::noncopyable { - public: - AgentImpl(char* label, bool internalStore); - ~AgentImpl(); - - void setStoreDir(const char* path); - void setTransferDir(const char* path); - void handleRcvMessage(Message& message); - bool getXmtMessage(Message& item) const; - void popXmt(); - bool getEvent(AgentEvent& event) const; - void popEvent(); - void newSession(); - void startProtocol(); - void heartbeat(); - void methodResponse(uint32_t sequence, uint32_t status, char* text, const Value& arguments); - void queryResponse(uint32_t sequence, Object& object, bool prop, bool stat); - void queryComplete(uint32_t sequence); - void registerClass(SchemaObjectClass* cls); - void registerClass(SchemaEventClass* cls); - const ObjectId* addObject(Object& obj, uint64_t persistId); - const ObjectId* allocObjectId(uint64_t persistId); - const ObjectId* allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi); - void raiseEvent(Event& event); - - private: - mutable Mutex lock; - Mutex addLock; - string label; - string queueName; - string storeDir; - string transferDir; - bool internalStore; - uint64_t nextTransientId; - Uuid systemId; - uint32_t requestedBrokerBank; - uint32_t requestedAgentBank; - uint32_t assignedBrokerBank; - uint32_t assignedAgentBank; - AgentAttachment attachment; - uint16_t bootSequence; - uint64_t nextObjectId; - uint32_t nextContextNum; - deque<AgentEventImpl::Ptr> eventQueue; - deque<MessageImpl::Ptr> xmtQueue; - map<uint32_t, AgentQueryContext::Ptr> contextMap; - bool attachComplete; - - static const char* QMF_EXCHANGE; - static const char* DIR_EXCHANGE; - static const char* BROKER_KEY; - static const uint32_t MERR_UNKNOWN_METHOD = 2; - static const uint32_t MERR_UNKNOWN_PACKAGE = 8; - static const uint32_t MERR_UNKNOWN_CLASS = 9; - static const uint32_t MERR_INTERNAL_ERROR = 10; -# define MA_BUFFER_SIZE 65536 - char outputBuffer[MA_BUFFER_SIZE]; - - struct AgentClassKey { - string name; - uint8_t hash[16]; - AgentClassKey(const string& n, const uint8_t* h) : name(n) { - memcpy(hash, h, 16); - } - AgentClassKey(Buffer& buffer) { - buffer.getShortString(name); - buffer.getBin128(hash); - } - string repr() { - return name; - } - }; - - struct AgentClassKeyComp { - bool operator() (const AgentClassKey& lhs, const AgentClassKey& rhs) const - { - if (lhs.name != rhs.name) - return lhs.name < rhs.name; - else - for (int i = 0; i < 16; i++) - if (lhs.hash[i] != rhs.hash[i]) - return lhs.hash[i] < rhs.hash[i]; - return false; - } - }; - - typedef map<AgentClassKey, SchemaObjectClass*, AgentClassKeyComp> ObjectClassMap; - typedef map<AgentClassKey, SchemaEventClass*, AgentClassKeyComp> EventClassMap; - - struct ClassMaps { - ObjectClassMap objectClasses; - EventClassMap eventClasses; - }; - - map<string, ClassMaps> packages; - - AgentEventImpl::Ptr eventDeclareQueue(const string& queueName); - AgentEventImpl::Ptr eventBind(const string& exchange, const string& queue, const string& key); - AgentEventImpl::Ptr eventSetupComplete(); - AgentEventImpl::Ptr eventQuery(uint32_t num, const string& userId, const string& package, const string& cls, - boost::shared_ptr<ObjectId> oid); - AgentEventImpl::Ptr eventMethod(uint32_t num, const string& userId, const string& method, - boost::shared_ptr<ObjectId> oid, boost::shared_ptr<Value> argMap, - const SchemaObjectClass* objectClass); - void sendBufferLH(Buffer& buf, const string& destination, const string& routingKey); - - void sendPackageIndicationLH(const string& packageName); - void sendClassIndicationLH(ClassKind kind, const string& packageName, const AgentClassKey& key); - void sendCommandCompleteLH(const string& exchange, const string& key, uint32_t seq, - uint32_t code = 0, const string& text = "OK"); - void sendMethodErrorLH(uint32_t sequence, const string& key, uint32_t code, const string& text=""); - void handleAttachResponse(Buffer& inBuffer); - void handlePackageRequest(Buffer& inBuffer); - void handleClassQuery(Buffer& inBuffer); - void handleSchemaRequest(Buffer& inBuffer, uint32_t sequence, - const string& replyToExchange, const string& replyToKey); - void handleGetQuery(Buffer& inBuffer, uint32_t sequence, const string& replyTo, const string& userId); - void handleMethodRequest(Buffer& inBuffer, uint32_t sequence, const string& replyTo, const string& userId); - void handleConsoleAddedIndication(); - }; -} -} - -const char* AgentImpl::QMF_EXCHANGE = "qpid.management"; -const char* AgentImpl::DIR_EXCHANGE = "amq.direct"; -const char* AgentImpl::BROKER_KEY = "broker"; - -#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());} - -AgentEvent AgentEventImpl::copy() -{ - AgentEvent item; - - ::memset(&item, 0, sizeof(AgentEvent)); - item.kind = kind; - item.sequence = sequence; - item.object = object; - item.objectId = objectId.get(); - item.query = query.get(); - item.arguments = arguments.get(); - item.objectClass = objectClass; - - STRING_REF(authUserId); - STRING_REF(authToken); - STRING_REF(name); - STRING_REF(exchange); - STRING_REF(bindingKey); - - return item; -} - -AgentImpl::AgentImpl(char* _label, bool i) : - label(_label), queueName("qmfa-"), internalStore(i), nextTransientId(1), - requestedBrokerBank(0), requestedAgentBank(0), - assignedBrokerBank(0), assignedAgentBank(0), - bootSequence(1), nextObjectId(1), nextContextNum(1), attachComplete(false) -{ - queueName += Uuid(true).str(); -} - -AgentImpl::~AgentImpl() -{ -} - -void AgentImpl::setStoreDir(const char* path) -{ - Mutex::ScopedLock _lock(lock); - if (path) - storeDir = path; - else - storeDir.clear(); -} - -void AgentImpl::setTransferDir(const char* path) -{ - Mutex::ScopedLock _lock(lock); - if (path) - transferDir = path; - else - transferDir.clear(); -} - -void AgentImpl::handleRcvMessage(Message& message) -{ - Buffer inBuffer(message.body, message.length); - uint8_t opcode; - uint32_t sequence; - string replyToExchange(message.replyExchange ? message.replyExchange : ""); - string replyToKey(message.replyKey ? message.replyKey : ""); - string userId(message.userId ? message.userId : ""); - - while (Protocol::checkHeader(inBuffer, &opcode, &sequence)) { - if (opcode == Protocol::OP_ATTACH_RESPONSE) handleAttachResponse(inBuffer); - else if (opcode == Protocol::OP_SCHEMA_REQUEST) handleSchemaRequest(inBuffer, sequence, replyToExchange, replyToKey); - else if (opcode == Protocol::OP_CONSOLE_ADDED_INDICATION) handleConsoleAddedIndication(); - else if (opcode == Protocol::OP_GET_QUERY) handleGetQuery(inBuffer, sequence, replyToKey, userId); - else if (opcode == Protocol::OP_METHOD_REQUEST) handleMethodRequest(inBuffer, sequence, replyToKey, userId); - else { - QPID_LOG(error, "AgentImpl::handleRcvMessage invalid opcode=" << opcode); - break; - } - } -} - -bool AgentImpl::getXmtMessage(Message& item) const -{ - Mutex::ScopedLock _lock(lock); - if (xmtQueue.empty()) - return false; - item = xmtQueue.front()->copy(); - return true; -} - -void AgentImpl::popXmt() -{ - Mutex::ScopedLock _lock(lock); - if (!xmtQueue.empty()) - xmtQueue.pop_front(); -} - -bool AgentImpl::getEvent(AgentEvent& event) const -{ - Mutex::ScopedLock _lock(lock); - if (eventQueue.empty()) - return false; - event = eventQueue.front()->copy(); - return true; -} - -void AgentImpl::popEvent() -{ - Mutex::ScopedLock _lock(lock); - if (!eventQueue.empty()) - eventQueue.pop_front(); -} - -void AgentImpl::newSession() -{ - Mutex::ScopedLock _lock(lock); - eventQueue.clear(); - xmtQueue.clear(); - eventQueue.push_back(eventDeclareQueue(queueName)); - eventQueue.push_back(eventBind("amq.direct", queueName, queueName)); - eventQueue.push_back(eventSetupComplete()); -} - -void AgentImpl::startProtocol() -{ - Mutex::ScopedLock _lock(lock); - char rawbuffer[512]; - Buffer buffer(rawbuffer, 512); - - Protocol::encodeHeader(buffer, Protocol::OP_ATTACH_REQUEST); - buffer.putShortString(label); - systemId.encode(buffer); - buffer.putLong(requestedBrokerBank); - buffer.putLong(requestedAgentBank); - sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY); - QPID_LOG(trace, "SENT AttachRequest: reqBroker=" << requestedBrokerBank << - " reqAgent=" << requestedAgentBank); -} - -void AgentImpl::heartbeat() -{ - Mutex::ScopedLock _lock(lock); - Buffer buffer(outputBuffer, MA_BUFFER_SIZE); - - Protocol::encodeHeader(buffer, Protocol::OP_HEARTBEAT_INDICATION); - buffer.putLongLong(uint64_t(Duration(EPOCH, now()))); - stringstream key; - key << "console.heartbeat." << assignedBrokerBank << "." << assignedAgentBank; - sendBufferLH(buffer, QMF_EXCHANGE, key.str()); - QPID_LOG(trace, "SENT HeartbeatIndication"); -} - -void AgentImpl::methodResponse(uint32_t sequence, uint32_t status, char* text, const Value& argMap) -{ - Mutex::ScopedLock _lock(lock); - map<uint32_t, AgentQueryContext::Ptr>::iterator iter = contextMap.find(sequence); - if (iter == contextMap.end()) - return; - AgentQueryContext::Ptr context = iter->second; - contextMap.erase(iter); - - char* buf(outputBuffer); - uint32_t bufLen(114 + strlen(text)); // header(8) + status(4) + mstring(2 + size) + margin(100) - bool allocated(false); - - if (status == 0) { - for (vector<const SchemaArgument*>::const_iterator aIter = context->schemaMethod->impl->arguments.begin(); - aIter != context->schemaMethod->impl->arguments.end(); aIter++) { - const SchemaArgument* schemaArg = *aIter; - if (schemaArg->getDirection() == DIR_OUT || schemaArg->getDirection() == DIR_IN_OUT) { - if (argMap.keyInMap(schemaArg->getName())) { - const Value* val = argMap.byKey(schemaArg->getName()); - bufLen += val->impl->encodedSize(); - } else { - Value val(schemaArg->getType()); - bufLen += val.impl->encodedSize(); - } - } - } - } - - if (bufLen > MA_BUFFER_SIZE) { - buf = (char*) malloc(bufLen); - allocated = true; - } - - Buffer buffer(buf, bufLen); - Protocol::encodeHeader(buffer, Protocol::OP_METHOD_RESPONSE, context->sequence); - buffer.putLong(status); - buffer.putMediumString(text); - if (status == 0) { - for (vector<const SchemaArgument*>::const_iterator aIter = context->schemaMethod->impl->arguments.begin(); - aIter != context->schemaMethod->impl->arguments.end(); aIter++) { - const SchemaArgument* schemaArg = *aIter; - if (schemaArg->getDirection() == DIR_OUT || schemaArg->getDirection() == DIR_IN_OUT) { - if (argMap.keyInMap(schemaArg->getName())) { - const Value* val = argMap.byKey(schemaArg->getName()); - val->impl->encode(buffer); - } else { - Value val(schemaArg->getType()); - val.impl->encode(buffer); - } - } - } - } - sendBufferLH(buffer, context->exchange, context->key); - if (allocated) - free(buf); - QPID_LOG(trace, "SENT MethodResponse seq=" << context->sequence << " status=" << status << " text=" << text); -} - -void AgentImpl::queryResponse(uint32_t sequence, Object& object, bool prop, bool stat) -{ - Mutex::ScopedLock _lock(lock); - map<uint32_t, AgentQueryContext::Ptr>::iterator iter = contextMap.find(sequence); - if (iter == contextMap.end()) - return; - AgentQueryContext::Ptr context = iter->second; - - Buffer buffer(outputBuffer, MA_BUFFER_SIZE); - Protocol::encodeHeader(buffer, Protocol::OP_OBJECT_INDICATION, context->sequence); - - object.impl->encodeSchemaKey(buffer); - object.impl->encodeManagedObjectData(buffer); - if (prop) - object.impl->encodeProperties(buffer); - if (stat) - object.impl->encodeStatistics(buffer); - - sendBufferLH(buffer, context->exchange, context->key); - QPID_LOG(trace, "SENT ContentIndication seq=" << context->sequence); -} - -void AgentImpl::queryComplete(uint32_t sequence) -{ - Mutex::ScopedLock _lock(lock); - map<uint32_t, AgentQueryContext::Ptr>::iterator iter = contextMap.find(sequence); - if (iter == contextMap.end()) - return; - - AgentQueryContext::Ptr context = iter->second; - contextMap.erase(iter); - sendCommandCompleteLH(context->exchange, context->key, context->sequence, 0, "OK"); -} - -void AgentImpl::registerClass(SchemaObjectClass* cls) -{ - Mutex::ScopedLock _lock(lock); - bool newPackage = false; - - map<string, ClassMaps>::iterator iter = packages.find(cls->getClassKey()->getPackageName()); - if (iter == packages.end()) { - packages[cls->getClassKey()->getPackageName()] = ClassMaps(); - iter = packages.find(cls->getClassKey()->getPackageName()); - newPackage = true; - } - - AgentClassKey key(cls->getClassKey()->getClassName(), cls->getClassKey()->getHash()); - iter->second.objectClasses[key] = cls; - - // Indicate this new schema if connected. - - if (attachComplete) { - - if (newPackage) { - sendPackageIndicationLH(iter->first); - } - sendClassIndicationLH(CLASS_OBJECT, iter->first, key); - } -} - -void AgentImpl::registerClass(SchemaEventClass* cls) -{ - Mutex::ScopedLock _lock(lock); - bool newPackage = false; - - map<string, ClassMaps>::iterator iter = packages.find(cls->getClassKey()->getPackageName()); - if (iter == packages.end()) { - packages[cls->getClassKey()->getPackageName()] = ClassMaps(); - iter = packages.find(cls->getClassKey()->getPackageName()); - newPackage = true; - } - - AgentClassKey key(cls->getClassKey()->getClassName(), cls->getClassKey()->getHash()); - iter->second.eventClasses[key] = cls; - - // Indicate this new schema if connected. - - if (attachComplete) { - - if (newPackage) { - sendPackageIndicationLH(iter->first); - } - sendClassIndicationLH(CLASS_EVENT, iter->first, key); - } -} - -const ObjectId* AgentImpl::addObject(Object&, uint64_t) -{ - Mutex::ScopedLock _lock(lock); - return 0; -} - -const ObjectId* AgentImpl::allocObjectId(uint64_t persistId) -{ - Mutex::ScopedLock _lock(lock); - uint16_t sequence = persistId ? 0 : bootSequence; - uint64_t objectNum = persistId ? persistId : nextObjectId++; - - ObjectId* oid = ObjectIdImpl::factory(&attachment, 0, sequence, objectNum); - return oid; -} - -const ObjectId* AgentImpl::allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi) -{ - return allocObjectId(((uint64_t) persistIdHi) << 32 | (uint64_t) persistIdLo); -} - -void AgentImpl::raiseEvent(Event& event) -{ - Mutex::ScopedLock _lock(lock); - Buffer buffer(outputBuffer, MA_BUFFER_SIZE); - Protocol::encodeHeader(buffer, Protocol::OP_EVENT_INDICATION); - - event.impl->encodeSchemaKey(buffer); - buffer.putLongLong(uint64_t(Duration(EPOCH, now()))); - event.impl->encode(buffer); - string key(event.impl->getRoutingKey(assignedBrokerBank, assignedAgentBank)); - - sendBufferLH(buffer, QMF_EXCHANGE, key); - QPID_LOG(trace, "SENT EventIndication"); -} - -AgentEventImpl::Ptr AgentImpl::eventDeclareQueue(const string& name) -{ - AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::DECLARE_QUEUE)); - event->name = name; - - return event; -} - -AgentEventImpl::Ptr AgentImpl::eventBind(const string& exchange, const string& queue, - const string& key) -{ - AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::BIND)); - event->name = queue; - event->exchange = exchange; - event->bindingKey = key; - - return event; -} - -AgentEventImpl::Ptr AgentImpl::eventSetupComplete() -{ - AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::SETUP_COMPLETE)); - return event; -} - -AgentEventImpl::Ptr AgentImpl::eventQuery(uint32_t num, const string& userId, const string& package, - const string& cls, boost::shared_ptr<ObjectId> oid) -{ - AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::GET_QUERY)); - event->sequence = num; - event->authUserId = userId; - if (oid.get()) - event->query.reset(new Query(oid.get())); - else - event->query.reset(new Query(cls.c_str(), package.c_str())); - return event; -} - -AgentEventImpl::Ptr AgentImpl::eventMethod(uint32_t num, const string& userId, const string& method, - boost::shared_ptr<ObjectId> oid, boost::shared_ptr<Value> argMap, - const SchemaObjectClass* objectClass) -{ - AgentEventImpl::Ptr event(new AgentEventImpl(AgentEvent::METHOD_CALL)); - event->sequence = num; - event->authUserId = userId; - event->name = method; - event->objectId = oid; - event->arguments = argMap; - event->objectClass = objectClass; - return event; -} - -void AgentImpl::sendBufferLH(Buffer& buf, const string& destination, const string& routingKey) -{ - uint32_t length = buf.getPosition(); - MessageImpl::Ptr message(new MessageImpl); - - buf.reset(); - buf.getRawData(message->body, length); - message->destination = destination; - message->routingKey = routingKey; - message->replyExchange = "amq.direct"; - message->replyKey = queueName; - - xmtQueue.push_back(message); -} - -void AgentImpl::sendPackageIndicationLH(const string& packageName) -{ - Buffer buffer(outputBuffer, MA_BUFFER_SIZE); - Protocol::encodeHeader(buffer, Protocol::OP_PACKAGE_INDICATION); - buffer.putShortString(packageName); - sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY); - QPID_LOG(trace, "SENT PackageIndication: package_name=" << packageName); -} - -void AgentImpl::sendClassIndicationLH(ClassKind kind, const string& packageName, const AgentClassKey& key) -{ - Buffer buffer(outputBuffer, MA_BUFFER_SIZE); - Protocol::encodeHeader(buffer, Protocol::OP_CLASS_INDICATION); - buffer.putOctet((int) kind); - buffer.putShortString(packageName); - buffer.putShortString(key.name); - buffer.putBin128(const_cast<uint8_t*>(key.hash)); // const_cast needed for older Qpid libraries - sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY); - QPID_LOG(trace, "SENT ClassIndication: package_name=" << packageName << " class_name=" << key.name); -} - -void AgentImpl::sendCommandCompleteLH(const string& exchange, const string& replyToKey, - uint32_t sequence, uint32_t code, const string& text) -{ - Buffer buffer(outputBuffer, MA_BUFFER_SIZE); - Protocol::encodeHeader(buffer, Protocol::OP_COMMAND_COMPLETE, sequence); - buffer.putLong(code); - buffer.putShortString(text); - sendBufferLH(buffer, exchange, replyToKey); - QPID_LOG(trace, "SENT CommandComplete: seq=" << sequence << " code=" << code << " text=" << text); -} - -void AgentImpl::sendMethodErrorLH(uint32_t sequence, const string& key, uint32_t code, const string& text) -{ - Buffer buffer(outputBuffer, MA_BUFFER_SIZE); - Protocol::encodeHeader(buffer, Protocol::OP_METHOD_RESPONSE, sequence); - buffer.putLong(code); - - string fulltext; - switch (code) { - case MERR_UNKNOWN_PACKAGE: fulltext = "Unknown Package"; break; - case MERR_UNKNOWN_CLASS: fulltext = "Unknown Class"; break; - case MERR_UNKNOWN_METHOD: fulltext = "Unknown Method"; break; - case MERR_INTERNAL_ERROR: fulltext = "Internal Error"; break; - default: fulltext = "Unspecified Error"; break; - } - - if (!text.empty()) { - fulltext += " ("; - fulltext += text; - fulltext += ")"; - } - - buffer.putMediumString(fulltext); - sendBufferLH(buffer, DIR_EXCHANGE, key); - QPID_LOG(trace, "SENT MethodResponse: errorCode=" << code << " text=" << fulltext); -} - -void AgentImpl::handleAttachResponse(Buffer& inBuffer) -{ - Mutex::ScopedLock _lock(lock); - - assignedBrokerBank = inBuffer.getLong(); - assignedAgentBank = inBuffer.getLong(); - - QPID_LOG(trace, "RCVD AttachResponse: broker=" << assignedBrokerBank << " agent=" << assignedAgentBank); - - if ((assignedBrokerBank != requestedBrokerBank) || - (assignedAgentBank != requestedAgentBank)) { - if (requestedAgentBank == 0) { - QPID_LOG(notice, "Initial object-id bank assigned: " << assignedBrokerBank << "." << - assignedAgentBank); - } else { - QPID_LOG(warning, "Collision in object-id! New bank assigned: " << assignedBrokerBank << - "." << assignedAgentBank); - } - //storeData(); // TODO - requestedBrokerBank = assignedBrokerBank; - requestedAgentBank = assignedAgentBank; - } - - attachment.setBanks(assignedBrokerBank, assignedAgentBank); - - // Bind to qpid.management to receive commands - stringstream key; - key << "agent." << assignedBrokerBank << "." << assignedAgentBank; - eventQueue.push_back(eventBind(QMF_EXCHANGE, queueName, key.str())); - - // Send package indications for all local packages - for (map<string, ClassMaps>::iterator pIter = packages.begin(); - pIter != packages.end(); - pIter++) { - sendPackageIndicationLH(pIter->first); - - // Send class indications for all local classes - ClassMaps cMap = pIter->second; - for (ObjectClassMap::iterator cIter = cMap.objectClasses.begin(); - cIter != cMap.objectClasses.end(); cIter++) - sendClassIndicationLH(CLASS_OBJECT, pIter->first, cIter->first); - for (EventClassMap::iterator cIter = cMap.eventClasses.begin(); - cIter != cMap.eventClasses.end(); cIter++) - sendClassIndicationLH(CLASS_EVENT, pIter->first, cIter->first); - } - - attachComplete = true; -} - -void AgentImpl::handlePackageRequest(Buffer&) -{ - Mutex::ScopedLock _lock(lock); -} - -void AgentImpl::handleClassQuery(Buffer&) -{ - Mutex::ScopedLock _lock(lock); -} - -void AgentImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence, - const string& replyExchange, const string& replyKey) -{ - Mutex::ScopedLock _lock(lock); - string rExchange(replyExchange); - string rKey(replyKey); - string packageName; - inBuffer.getShortString(packageName); - AgentClassKey key(inBuffer); - - if (rExchange.empty()) - rExchange = QMF_EXCHANGE; - if (rKey.empty()) - rKey = BROKER_KEY; - - QPID_LOG(trace, "RCVD SchemaRequest: package=" << packageName << " class=" << key.name); - - map<string, ClassMaps>::iterator pIter = packages.find(packageName); - if (pIter == packages.end()) { - sendCommandCompleteLH(rExchange, rKey, sequence, 1, "package not found"); - return; - } - - ClassMaps cMap = pIter->second; - ObjectClassMap::iterator ocIter = cMap.objectClasses.find(key); - if (ocIter != cMap.objectClasses.end()) { - SchemaObjectClass* oImpl = ocIter->second; - Buffer buffer(outputBuffer, MA_BUFFER_SIZE); - Protocol::encodeHeader(buffer, Protocol::OP_SCHEMA_RESPONSE, sequence); - oImpl->impl->encode(buffer); - sendBufferLH(buffer, rExchange, rKey); - QPID_LOG(trace, "SENT SchemaResponse: (object) package=" << packageName << " class=" << key.name); - return; - } - - EventClassMap::iterator ecIter = cMap.eventClasses.find(key); - if (ecIter != cMap.eventClasses.end()) { - SchemaEventClass* eImpl = ecIter->second; - Buffer buffer(outputBuffer, MA_BUFFER_SIZE); - Protocol::encodeHeader(buffer, Protocol::OP_SCHEMA_RESPONSE, sequence); - eImpl->impl->encode(buffer); - sendBufferLH(buffer, rExchange, rKey); - QPID_LOG(trace, "SENT SchemaResponse: (event) package=" << packageName << " class=" << key.name); - return; - } - - sendCommandCompleteLH(rExchange, rKey, sequence, 1, "class not found"); -} - -void AgentImpl::handleGetQuery(Buffer& inBuffer, uint32_t sequence, const string& replyTo, const string& userId) -{ - Mutex::ScopedLock _lock(lock); - FieldTable ft; - FieldTable::ValuePtr value; - map<string, ClassMaps>::const_iterator pIter = packages.end(); - string pname; - string cname; - string oidRepr; - boost::shared_ptr<ObjectId> oid; - - ft.decode(inBuffer); - - QPID_LOG(trace, "RCVD GetQuery: seq=" << sequence << " map=" << ft); - - value = ft.get("_package"); - if (value.get() && value->convertsTo<string>()) { - pname = value->get<string>(); - pIter = packages.find(pname); - if (pIter == packages.end()) { - sendCommandCompleteLH(DIR_EXCHANGE, replyTo, sequence); - return; - } - } - - value = ft.get("_class"); - if (value.get() && value->convertsTo<string>()) { - cname = value->get<string>(); - // TODO - check for validity of class (in package or any package) - if (pIter == packages.end()) { - } else { - - } - } - - value = ft.get("_objectid"); - if (value.get() && value->convertsTo<string>()) { - oidRepr = value->get<string>(); - oid.reset(new ObjectId()); - oid->impl->fromString(oidRepr); - } - - AgentQueryContext::Ptr context(new AgentQueryContext); - uint32_t contextNum = nextContextNum++; - context->sequence = sequence; - context->exchange = DIR_EXCHANGE; - context->key = replyTo; - contextMap[contextNum] = context; - - eventQueue.push_back(eventQuery(contextNum, userId, pname, cname, oid)); -} - -void AgentImpl::handleMethodRequest(Buffer& buffer, uint32_t sequence, const string& replyTo, const string& userId) -{ - Mutex::ScopedLock _lock(lock); - string pname; - string method; - boost::shared_ptr<ObjectId> oid(ObjectIdImpl::factory(buffer)); - buffer.getShortString(pname); - AgentClassKey classKey(buffer); - buffer.getShortString(method); - - QPID_LOG(trace, "RCVD MethodRequest seq=" << sequence << " method=" << method); - - map<string, ClassMaps>::const_iterator pIter = packages.find(pname); - if (pIter == packages.end()) { - sendMethodErrorLH(sequence, replyTo, MERR_UNKNOWN_PACKAGE, pname); - return; - } - - ObjectClassMap::const_iterator cIter = pIter->second.objectClasses.find(classKey); - if (cIter == pIter->second.objectClasses.end()) { - sendMethodErrorLH(sequence, replyTo, MERR_UNKNOWN_CLASS, classKey.repr()); - return; - } - - const SchemaObjectClass* schema = cIter->second; - vector<const SchemaMethod*>::const_iterator mIter = schema->impl->methods.begin(); - for (; mIter != schema->impl->methods.end(); mIter++) { - if ((*mIter)->getName() == method) - break; - } - - if (mIter == schema->impl->methods.end()) { - sendMethodErrorLH(sequence, replyTo, MERR_UNKNOWN_METHOD, method); - return; - } - - const SchemaMethod* schemaMethod = *mIter; - boost::shared_ptr<Value> argMap(new Value(TYPE_MAP)); - Value* value; - for (vector<const SchemaArgument*>::const_iterator aIter = schemaMethod->impl->arguments.begin(); - aIter != schemaMethod->impl->arguments.end(); aIter++) { - const SchemaArgument* schemaArg = *aIter; - if (schemaArg->getDirection() == DIR_IN || schemaArg->getDirection() == DIR_IN_OUT) - value = ValueImpl::factory(schemaArg->getType(), buffer); - else - value = ValueImpl::factory(schemaArg->getType()); - argMap->insert(schemaArg->getName(), value); - } - - AgentQueryContext::Ptr context(new AgentQueryContext); - uint32_t contextNum = nextContextNum++; - context->sequence = sequence; - context->exchange = DIR_EXCHANGE; - context->key = replyTo; - context->schemaMethod = schemaMethod; - contextMap[contextNum] = context; - - eventQueue.push_back(eventMethod(contextNum, userId, method, oid, argMap, schema)); -} - -void AgentImpl::handleConsoleAddedIndication() -{ - Mutex::ScopedLock _lock(lock); -} - -//================================================================== -// Wrappers -//================================================================== - -Agent::Agent(char* label, bool internalStore) { impl = new AgentImpl(label, internalStore); } -Agent::~Agent() { delete impl; } -void Agent::setStoreDir(const char* path) { impl->setStoreDir(path); } -void Agent::setTransferDir(const char* path) { impl->setTransferDir(path); } -void Agent::handleRcvMessage(Message& message) { impl->handleRcvMessage(message); } -bool Agent::getXmtMessage(Message& item) const { return impl->getXmtMessage(item); } -void Agent::popXmt() { impl->popXmt(); } -bool Agent::getEvent(AgentEvent& event) const { return impl->getEvent(event); } -void Agent::popEvent() { impl->popEvent(); } -void Agent::newSession() { impl->newSession(); } -void Agent::startProtocol() { impl->startProtocol(); } -void Agent::heartbeat() { impl->heartbeat(); } -void Agent::methodResponse(uint32_t sequence, uint32_t status, char* text, const Value& arguments) { impl->methodResponse(sequence, status, text, arguments); } -void Agent::queryResponse(uint32_t sequence, Object& object, bool prop, bool stat) { impl->queryResponse(sequence, object, prop, stat); } -void Agent::queryComplete(uint32_t sequence) { impl->queryComplete(sequence); } -void Agent::registerClass(SchemaObjectClass* cls) { impl->registerClass(cls); } -void Agent::registerClass(SchemaEventClass* cls) { impl->registerClass(cls); } -const ObjectId* Agent::addObject(Object& obj, uint64_t persistId) { return impl->addObject(obj, persistId); } -const ObjectId* Agent::allocObjectId(uint64_t persistId) { return impl->allocObjectId(persistId); } -const ObjectId* Agent::allocObjectId(uint32_t persistIdLo, uint32_t persistIdHi) { return impl->allocObjectId(persistIdLo, persistIdHi); } -void Agent::raiseEvent(Event& event) { impl->raiseEvent(event); } - diff --git a/cpp/src/qmf/engine/BrokerProxyImpl.cpp b/cpp/src/qmf/engine/BrokerProxyImpl.cpp deleted file mode 100644 index 5fc71979fd..0000000000 --- a/cpp/src/qmf/engine/BrokerProxyImpl.cpp +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/BrokerProxyImpl.h" -#include "qmf/engine/ConsoleImpl.h" -#include "qmf/engine/Protocol.h" -#include "qpid/Address.h" -#include "qpid/sys/SystemInfo.h" -#include <qpid/log/Statement.h> -#include <qpid/StringUtils.h> -#include <string.h> -#include <iostream> -#include <fstream> - -using namespace std; -using namespace qmf::engine; -using namespace qpid::framing; -using namespace qpid::sys; - -namespace { - const char* QMF_EXCHANGE = "qpid.management"; - const char* DIR_EXCHANGE = "amq.direct"; - const char* BROKER_KEY = "broker"; - const char* BROKER_PACKAGE = "org.apache.qpid.broker"; - const char* AGENT_CLASS = "agent"; - const char* BROKER_AGENT_KEY = "agent.1.0"; -} - -const Object* QueryResponseImpl::getObject(uint32_t idx) const -{ - vector<ObjectPtr>::const_iterator iter = results.begin(); - - while (idx > 0) { - if (iter == results.end()) - return 0; - iter++; - idx--; - } - - return iter->get(); -} - -#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());} - -BrokerEvent BrokerEventImpl::copy() -{ - BrokerEvent item; - - ::memset(&item, 0, sizeof(BrokerEvent)); - item.kind = kind; - - STRING_REF(name); - STRING_REF(exchange); - STRING_REF(bindingKey); - item.context = context; - item.queryResponse = queryResponse.get(); - item.methodResponse = methodResponse.get(); - - return item; -} - -BrokerProxyImpl::BrokerProxyImpl(BrokerProxy& pub, Console& _console) : publicObject(pub), console(_console) -{ - stringstream qn; - qpid::Address addr; - - SystemInfo::getLocalHostname(addr); - qn << "qmfc-" << SystemInfo::getProcessName() << "-" << addr << "-" << SystemInfo::getProcessId(); - queueName = qn.str(); - - seqMgr.setUnsolicitedContext(SequenceContext::Ptr(new StaticContext(*this))); -} - -void BrokerProxyImpl::sessionOpened(SessionHandle& /*sh*/) -{ - Mutex::ScopedLock _lock(lock); - agentList.clear(); - eventQueue.clear(); - xmtQueue.clear(); - eventQueue.push_back(eventDeclareQueue(queueName)); - eventQueue.push_back(eventBind(DIR_EXCHANGE, queueName, queueName)); - eventQueue.push_back(eventSetupComplete()); - - // TODO: Store session handle -} - -void BrokerProxyImpl::sessionClosed() -{ - Mutex::ScopedLock _lock(lock); - agentList.clear(); - eventQueue.clear(); - xmtQueue.clear(); -} - -void BrokerProxyImpl::startProtocol() -{ - AgentProxyPtr agent(AgentProxyImpl::factory(console, publicObject, 0, "Agent embedded in broker")); - { - Mutex::ScopedLock _lock(lock); - char rawbuffer[512]; - Buffer buffer(rawbuffer, 512); - - agentList[0] = agent; - - requestsOutstanding = 1; - topicBound = false; - uint32_t sequence(seqMgr.reserve()); - Protocol::encodeHeader(buffer, Protocol::OP_BROKER_REQUEST, sequence); - sendBufferLH(buffer, QMF_EXCHANGE, BROKER_KEY); - QPID_LOG(trace, "SENT BrokerRequest seq=" << sequence); - } - - console.impl->eventAgentAdded(agent); -} - -void BrokerProxyImpl::sendBufferLH(Buffer& buf, const string& destination, const string& routingKey) -{ - uint32_t length = buf.getPosition(); - MessageImpl::Ptr message(new MessageImpl); - - buf.reset(); - buf.getRawData(message->body, length); - message->destination = destination; - message->routingKey = routingKey; - message->replyExchange = DIR_EXCHANGE; - message->replyKey = queueName; - - xmtQueue.push_back(message); -} - -void BrokerProxyImpl::handleRcvMessage(Message& message) -{ - Buffer inBuffer(message.body, message.length); - uint8_t opcode; - uint32_t sequence; - - while (Protocol::checkHeader(inBuffer, &opcode, &sequence)) - seqMgr.dispatch(opcode, sequence, message.routingKey ? string(message.routingKey) : string(), inBuffer); -} - -bool BrokerProxyImpl::getXmtMessage(Message& item) const -{ - Mutex::ScopedLock _lock(lock); - if (xmtQueue.empty()) - return false; - item = xmtQueue.front()->copy(); - return true; -} - -void BrokerProxyImpl::popXmt() -{ - Mutex::ScopedLock _lock(lock); - if (!xmtQueue.empty()) - xmtQueue.pop_front(); -} - -bool BrokerProxyImpl::getEvent(BrokerEvent& event) const -{ - Mutex::ScopedLock _lock(lock); - if (eventQueue.empty()) - return false; - event = eventQueue.front()->copy(); - return true; -} - -void BrokerProxyImpl::popEvent() -{ - Mutex::ScopedLock _lock(lock); - if (!eventQueue.empty()) - eventQueue.pop_front(); -} - -uint32_t BrokerProxyImpl::agentCount() const -{ - Mutex::ScopedLock _lock(lock); - return agentList.size(); -} - -const AgentProxy* BrokerProxyImpl::getAgent(uint32_t idx) const -{ - Mutex::ScopedLock _lock(lock); - for (map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.begin(); - iter != agentList.end(); iter++) - if (idx-- == 0) - return iter->second.get(); - return 0; -} - -void BrokerProxyImpl::sendQuery(const Query& query, void* context, const AgentProxy* agent) -{ - SequenceContext::Ptr queryContext(new QueryContext(*this, context)); - Mutex::ScopedLock _lock(lock); - bool sent = false; - if (agent != 0) { - if (sendGetRequestLH(queryContext, query, agent)) - sent = true; - } else { - // TODO (optimization) only send queries to agents that have the requested class+package - for (map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.begin(); - iter != agentList.end(); iter++) { - if (sendGetRequestLH(queryContext, query, iter->second.get())) - sent = true; - } - } - - if (!sent) { - queryContext->reserve(); - queryContext->release(); - } -} - -bool BrokerProxyImpl::sendGetRequestLH(SequenceContext::Ptr queryContext, const Query& query, const AgentProxy* agent) -{ - if (query.impl->singleAgent()) { - if (query.impl->agentBank() != agent->getAgentBank()) - return false; - } - stringstream key; - Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE); - uint32_t sequence(seqMgr.reserve(queryContext)); - agent->impl->addSequence(sequence); - - Protocol::encodeHeader(outBuffer, Protocol::OP_GET_QUERY, sequence); - query.impl->encode(outBuffer); - key << "agent.1." << agent->impl->agentBank; - sendBufferLH(outBuffer, QMF_EXCHANGE, key.str()); - QPID_LOG(trace, "SENT GetQuery seq=" << sequence << " key=" << key.str()); - return true; -} - -string BrokerProxyImpl::encodeMethodArguments(const SchemaMethod* schema, const Value* argmap, Buffer& buffer) -{ - int argCount = schema->getArgumentCount(); - - if (argmap == 0 || !argmap->isMap()) - return string("Arguments must be in a map value"); - - for (int aIdx = 0; aIdx < argCount; aIdx++) { - const SchemaArgument* arg(schema->getArgument(aIdx)); - if (arg->getDirection() == DIR_IN || arg->getDirection() == DIR_IN_OUT) { - if (argmap->keyInMap(arg->getName())) { - const Value* argVal(argmap->byKey(arg->getName())); - if (argVal->getType() != arg->getType()) - return string("Argument is the wrong type: ") + arg->getName(); - argVal->impl->encode(buffer); - } else { - Value defaultValue(arg->getType()); - defaultValue.impl->encode(buffer); - } - } - } - - return string(); -} - -string BrokerProxyImpl::encodedSizeMethodArguments(const SchemaMethod* schema, const Value* argmap, uint32_t& size) -{ - int argCount = schema->getArgumentCount(); - - if (argmap == 0 || !argmap->isMap()) - return string("Arguments must be in a map value"); - - for (int aIdx = 0; aIdx < argCount; aIdx++) { - const SchemaArgument* arg(schema->getArgument(aIdx)); - if (arg->getDirection() == DIR_IN || arg->getDirection() == DIR_IN_OUT) { - if (argmap->keyInMap(arg->getName())) { - const Value* argVal(argmap->byKey(arg->getName())); - if (argVal->getType() != arg->getType()) - return string("Argument is the wrong type: ") + arg->getName(); - size += argVal->impl->encodedSize(); - } else { - Value defaultValue(arg->getType()); - size += defaultValue.impl->encodedSize(); - } - } - } - - return string(); -} - -void BrokerProxyImpl::sendMethodRequest(ObjectId* oid, const SchemaObjectClass* cls, - const string& methodName, const Value* args, void* userContext) -{ - int methodCount = cls->getMethodCount(); - int idx; - for (idx = 0; idx < methodCount; idx++) { - const SchemaMethod* method = cls->getMethod(idx); - if (string(method->getName()) == methodName) { - Mutex::ScopedLock _lock(lock); - SequenceContext::Ptr methodContext(new MethodContext(*this, userContext, method)); - stringstream key; - char* buf(outputBuffer); - uint32_t bufLen(1024); - bool allocated(false); - - string argErrorString = encodedSizeMethodArguments(method, args, bufLen); - if (!argErrorString.empty()) { - MethodResponsePtr argError(MethodResponseImpl::factory(1, argErrorString)); - eventQueue.push_back(eventMethodResponse(userContext, argError)); - return; - } - - if (bufLen > MA_BUFFER_SIZE) { - buf = (char*) malloc(bufLen); - allocated = true; - } - - Buffer outBuffer(buf, bufLen); - uint32_t sequence(seqMgr.reserve(methodContext)); - - Protocol::encodeHeader(outBuffer, Protocol::OP_METHOD_REQUEST, sequence); - oid->impl->encode(outBuffer); - cls->getClassKey()->impl->encode(outBuffer); - outBuffer.putShortString(methodName); - - encodeMethodArguments(method, args, outBuffer); - key << "agent.1." << oid->impl->getAgentBank(); - sendBufferLH(outBuffer, QMF_EXCHANGE, key.str()); - QPID_LOG(trace, "SENT MethodRequest seq=" << sequence << " method=" << methodName << " key=" << key.str()); - - if (allocated) - free(buf); - - return; - } - } - - MethodResponsePtr error(MethodResponseImpl::factory(1, string("Unknown method: ") + methodName)); - Mutex::ScopedLock _lock(lock); - eventQueue.push_back(eventMethodResponse(userContext, error)); -} - -void BrokerProxyImpl::addBinding(const string& exchange, const string& key) -{ - Mutex::ScopedLock _lock(lock); - eventQueue.push_back(eventBind(exchange, queueName, key)); -} - -BrokerEventImpl::Ptr BrokerProxyImpl::eventDeclareQueue(const string& queueName) -{ - BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::DECLARE_QUEUE)); - event->name = queueName; - return event; -} - -BrokerEventImpl::Ptr BrokerProxyImpl::eventBind(const string& exchange, const string& queue, const string& key) -{ - BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::BIND)); - event->name = queue; - event->exchange = exchange; - event->bindingKey = key; - - return event; -} - -BrokerEventImpl::Ptr BrokerProxyImpl::eventSetupComplete() -{ - BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::SETUP_COMPLETE)); - return event; -} - -BrokerEventImpl::Ptr BrokerProxyImpl::eventStable() -{ - QPID_LOG(trace, "Console Link to Broker Stable"); - BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::STABLE)); - return event; -} - -BrokerEventImpl::Ptr BrokerProxyImpl::eventQueryComplete(void* context, QueryResponsePtr response) -{ - BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::QUERY_COMPLETE)); - event->context = context; - event->queryResponse = response; - return event; -} - -BrokerEventImpl::Ptr BrokerProxyImpl::eventMethodResponse(void* context, MethodResponsePtr response) -{ - BrokerEventImpl::Ptr event(new BrokerEventImpl(BrokerEvent::METHOD_RESPONSE)); - event->context = context; - event->methodResponse = response; - return event; -} - -void BrokerProxyImpl::handleBrokerResponse(Buffer& inBuffer, uint32_t seq) -{ - brokerId.decode(inBuffer); - QPID_LOG(trace, "RCVD BrokerResponse seq=" << seq << " brokerId=" << brokerId); - Mutex::ScopedLock _lock(lock); - Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE); - uint32_t sequence(seqMgr.reserve()); - incOutstandingLH(); - Protocol::encodeHeader(outBuffer, Protocol::OP_PACKAGE_REQUEST, sequence); - sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY); - QPID_LOG(trace, "SENT PackageRequest seq=" << sequence); -} - -void BrokerProxyImpl::handlePackageIndication(Buffer& inBuffer, uint32_t seq) -{ - string package; - - inBuffer.getShortString(package); - QPID_LOG(trace, "RCVD PackageIndication seq=" << seq << " package=" << package); - console.impl->learnPackage(package); - - Mutex::ScopedLock _lock(lock); - Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE); - uint32_t sequence(seqMgr.reserve()); - incOutstandingLH(); - Protocol::encodeHeader(outBuffer, Protocol::OP_CLASS_QUERY, sequence); - outBuffer.putShortString(package); - sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY); - QPID_LOG(trace, "SENT ClassQuery seq=" << sequence << " package=" << package); -} - -void BrokerProxyImpl::handleCommandComplete(Buffer& inBuffer, uint32_t seq) -{ - string text; - uint32_t code = inBuffer.getLong(); - inBuffer.getShortString(text); - QPID_LOG(trace, "RCVD CommandComplete seq=" << seq << " code=" << code << " text=" << text); -} - -void BrokerProxyImpl::handleClassIndication(Buffer& inBuffer, uint32_t seq) -{ - uint8_t kind = inBuffer.getOctet(); - auto_ptr<SchemaClassKey> classKey(SchemaClassKeyImpl::factory(inBuffer)); - - QPID_LOG(trace, "RCVD ClassIndication seq=" << seq << " kind=" << (int) kind << " key=" << classKey->impl->str()); - - if (!console.impl->haveClass(classKey.get())) { - Mutex::ScopedLock _lock(lock); - incOutstandingLH(); - Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE); - uint32_t sequence(seqMgr.reserve()); - Protocol::encodeHeader(outBuffer, Protocol::OP_SCHEMA_REQUEST, sequence); - classKey->impl->encode(outBuffer); - sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_KEY); - QPID_LOG(trace, "SENT SchemaRequest seq=" << sequence <<" key=" << classKey->impl->str()); - } -} - -MethodResponsePtr BrokerProxyImpl::handleMethodResponse(Buffer& inBuffer, uint32_t seq, const SchemaMethod* schema) -{ - MethodResponsePtr response(MethodResponseImpl::factory(inBuffer, schema)); - - QPID_LOG(trace, "RCVD MethodResponse seq=" << seq << " status=" << response->getStatus() << " text=" << - response->getException()->asString()); - - return response; -} - -void BrokerProxyImpl::handleHeartbeatIndication(Buffer& inBuffer, uint32_t seq, const string& routingKey) -{ - vector<string> tokens = qpid::split(routingKey, "."); - uint32_t agentBank; - uint64_t timestamp; - - if (routingKey.empty() || tokens.size() != 4) - agentBank = 0; - else - agentBank = ::atoi(tokens[3].c_str()); - - timestamp = inBuffer.getLongLong(); - map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.find(agentBank); - if (iter != agentList.end()) { - console.impl->eventAgentHeartbeat(iter->second, timestamp); - } - QPID_LOG(trace, "RCVD HeartbeatIndication seq=" << seq << " agentBank=" << agentBank); -} - -void BrokerProxyImpl::handleEventIndication(Buffer& inBuffer, uint32_t seq) -{ - auto_ptr<SchemaClassKey> classKey(SchemaClassKeyImpl::factory(inBuffer)); - const SchemaEventClass *schema = console.impl->getEventClass(classKey.get()); - if (schema == 0) { - QPID_LOG(trace, "No Schema Found for EventIndication. seq=" << seq << " key=" << classKey->impl->str()); - return; - } - - EventPtr eptr(EventImpl::factory(schema, inBuffer)); - - console.impl->eventEventReceived(eptr); - QPID_LOG(trace, "RCVD EventIndication seq=" << seq << " key=" << classKey->impl->str()); -} - -void BrokerProxyImpl::handleSchemaResponse(Buffer& inBuffer, uint32_t seq) -{ - SchemaObjectClass* oClassPtr; - SchemaEventClass* eClassPtr; - uint8_t kind = inBuffer.getOctet(); - const SchemaClassKey* key; - if (kind == CLASS_OBJECT) { - oClassPtr = SchemaObjectClassImpl::factory(inBuffer); - console.impl->learnClass(oClassPtr); - key = oClassPtr->getClassKey(); - QPID_LOG(trace, "RCVD SchemaResponse seq=" << seq << " kind=object key=" << key->impl->str()); - - // - // If we have just learned about the org.apache.qpid.broker:agent class, send a get - // request for the current list of agents so we can have it on-hand before we declare - // this session "stable". - // - if (key->impl->getClassName() == AGENT_CLASS && key->impl->getPackageName() == BROKER_PACKAGE) { - Mutex::ScopedLock _lock(lock); - incOutstandingLH(); - Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE); - uint32_t sequence(seqMgr.reserve()); - Protocol::encodeHeader(outBuffer, Protocol::OP_GET_QUERY, sequence); - FieldTable ft; - ft.setString("_class", AGENT_CLASS); - ft.setString("_package", BROKER_PACKAGE); - ft.encode(outBuffer); - sendBufferLH(outBuffer, QMF_EXCHANGE, BROKER_AGENT_KEY); - QPID_LOG(trace, "SENT GetQuery seq=" << sequence << " key=" << BROKER_AGENT_KEY); - } - } else if (kind == CLASS_EVENT) { - eClassPtr = SchemaEventClassImpl::factory(inBuffer); - console.impl->learnClass(eClassPtr); - key = eClassPtr->getClassKey(); - QPID_LOG(trace, "RCVD SchemaResponse seq=" << seq << " kind=event key=" << key->impl->str()); - } - else { - QPID_LOG(error, "BrokerProxyImpl::handleSchemaResponse received unknown class kind: " << (int) kind); - } -} - -ObjectPtr BrokerProxyImpl::handleObjectIndication(Buffer& inBuffer, uint32_t seq, bool prop, bool stat) -{ - auto_ptr<SchemaClassKey> classKey(SchemaClassKeyImpl::factory(inBuffer)); - QPID_LOG(trace, "RCVD ObjectIndication seq=" << seq << " key=" << classKey->impl->str()); - - SchemaObjectClass* schema = console.impl->getSchema(classKey.get()); - if (schema == 0) { - QPID_LOG(trace, "No Schema Found for ObjectIndication. seq=" << seq << " key=" << classKey->impl->str()); - return ObjectPtr(); - } - - ObjectPtr optr(ObjectImpl::factory(schema, this, inBuffer, prop, stat, true)); - if (prop && classKey->impl->getPackageName() == BROKER_PACKAGE && classKey->impl->getClassName() == AGENT_CLASS) { - // - // We've intercepted information about a remote agent... update the agent list accordingly - // - updateAgentList(optr); - } - return optr; -} - -void BrokerProxyImpl::updateAgentList(ObjectPtr obj) -{ - Value* value = obj->getValue("agentBank"); - Mutex::ScopedLock _lock(lock); - if (value != 0 && value->isUint()) { - uint32_t agentBank = value->asUint(); - if (obj->isDeleted()) { - map<uint32_t, AgentProxyPtr>::iterator iter = agentList.find(agentBank); - if (iter != agentList.end()) { - AgentProxyPtr agent(iter->second); - console.impl->eventAgentDeleted(agent); - agentList.erase(agentBank); - QPID_LOG(trace, "Agent at bank " << agentBank << " removed from agent list"); - - // - // Release all sequence numbers for requests in-flight to this agent. - // Since the agent is no longer connected, these requests would not - // otherwise complete. - // - agent->impl->releaseInFlight(seqMgr); - } - } else { - Value* str = obj->getValue("label"); - string label; - if (str != 0 && str->isString()) - label = str->asString(); - map<uint32_t, AgentProxyPtr>::const_iterator iter = agentList.find(agentBank); - if (iter == agentList.end()) { - AgentProxyPtr agent(AgentProxyImpl::factory(console, publicObject, agentBank, label)); - agentList[agentBank] = agent; - console.impl->eventAgentAdded(agent); - QPID_LOG(trace, "Agent '" << label << "' found at bank " << agentBank); - } - } - } -} - -void BrokerProxyImpl::incOutstandingLH() -{ - requestsOutstanding++; -} - -void BrokerProxyImpl::decOutstanding() -{ - Mutex::ScopedLock _lock(lock); - requestsOutstanding--; - if (requestsOutstanding == 0 && !topicBound) { - topicBound = true; - for (vector<pair<string, string> >::const_iterator iter = console.impl->bindingList.begin(); - iter != console.impl->bindingList.end(); iter++) { - string exchange(iter->first.empty() ? QMF_EXCHANGE : iter->first); - string key(iter->second); - eventQueue.push_back(eventBind(exchange, queueName, key)); - } - eventQueue.push_back(eventStable()); - } -} - -MethodResponseImpl::MethodResponseImpl(const MethodResponseImpl& from) : - status(from.status), schema(from.schema) -{ - if (from.exception.get()) - exception.reset(new Value(*(from.exception))); - if (from.arguments.get()) - arguments.reset(new Value(*(from.arguments))); -} - -MethodResponseImpl::MethodResponseImpl(Buffer& buf, const SchemaMethod* s) : schema(s) -{ - string text; - - status = buf.getLong(); - buf.getMediumString(text); - exception.reset(new Value(TYPE_LSTR)); - exception->setString(text.c_str()); - - if (status != 0) - return; - - arguments.reset(new Value(TYPE_MAP)); - int argCount(schema->getArgumentCount()); - for (int idx = 0; idx < argCount; idx++) { - const SchemaArgument* arg = schema->getArgument(idx); - if (arg->getDirection() == DIR_OUT || arg->getDirection() == DIR_IN_OUT) { - Value* value(ValueImpl::factory(arg->getType(), buf)); - arguments->insert(arg->getName(), value); - } - } -} - -MethodResponseImpl::MethodResponseImpl(uint32_t s, const string& text) : schema(0) -{ - status = s; - exception.reset(new Value(TYPE_LSTR)); - exception->setString(text.c_str()); -} - -MethodResponse* MethodResponseImpl::factory(Buffer& buf, const SchemaMethod* schema) -{ - MethodResponseImpl* impl(new MethodResponseImpl(buf, schema)); - return new MethodResponse(impl); -} - -MethodResponse* MethodResponseImpl::factory(uint32_t status, const std::string& text) -{ - MethodResponseImpl* impl(new MethodResponseImpl(status, text)); - return new MethodResponse(impl); -} - -bool StaticContext::handleMessage(uint8_t opcode, uint32_t sequence, const string& routingKey, Buffer& buffer) -{ - ObjectPtr object; - bool completeContext = false; - - if (opcode == Protocol::OP_BROKER_RESPONSE) { - broker.handleBrokerResponse(buffer, sequence); - completeContext = true; - } - else if (opcode == Protocol::OP_COMMAND_COMPLETE) { - broker.handleCommandComplete(buffer, sequence); - completeContext = true; - } - else if (opcode == Protocol::OP_SCHEMA_RESPONSE) { - broker.handleSchemaResponse(buffer, sequence); - completeContext = true; - } - else if (opcode == Protocol::OP_PACKAGE_INDICATION) - broker.handlePackageIndication(buffer, sequence); - else if (opcode == Protocol::OP_CLASS_INDICATION) - broker.handleClassIndication(buffer, sequence); - else if (opcode == Protocol::OP_HEARTBEAT_INDICATION) - broker.handleHeartbeatIndication(buffer, sequence, routingKey); - else if (opcode == Protocol::OP_EVENT_INDICATION) - broker.handleEventIndication(buffer, sequence); - else if (opcode == Protocol::OP_PROPERTY_INDICATION) { - object = broker.handleObjectIndication(buffer, sequence, true, false); - broker.console.impl->eventObjectUpdate(object, true, false); - } - else if (opcode == Protocol::OP_STATISTIC_INDICATION) { - object = broker.handleObjectIndication(buffer, sequence, false, true); - broker.console.impl->eventObjectUpdate(object, false, true); - } - else if (opcode == Protocol::OP_OBJECT_INDICATION) { - object = broker.handleObjectIndication(buffer, sequence, true, true); - broker.console.impl->eventObjectUpdate(object, true, true); - } - else { - QPID_LOG(trace, "StaticContext::handleMessage invalid opcode: " << opcode); - completeContext = true; - } - - return completeContext; -} - -void QueryContext::reserve() -{ - Mutex::ScopedLock _lock(lock); - requestsOutstanding++; -} - -void QueryContext::release() -{ - { - Mutex::ScopedLock _lock(lock); - if (--requestsOutstanding > 0) - return; - } - - Mutex::ScopedLock _block(broker.lock); - broker.eventQueue.push_back(broker.eventQueryComplete(userContext, queryResponse)); -} - -bool QueryContext::handleMessage(uint8_t opcode, uint32_t sequence, const string& /*routingKey*/, Buffer& buffer) -{ - bool completeContext = false; - ObjectPtr object; - - if (opcode == Protocol::OP_COMMAND_COMPLETE) { - broker.handleCommandComplete(buffer, sequence); - completeContext = true; - - // - // Visit each agent and remove the sequence from that agent's in-flight list. - // This could be made more efficient because only one agent will have this sequence - // in its list. - // - map<uint32_t, AgentProxyPtr> copy; - { - Mutex::ScopedLock _block(broker.lock); - copy = broker.agentList; - } - for (map<uint32_t, AgentProxyPtr>::iterator iter = copy.begin(); iter != copy.end(); iter++) - iter->second->impl->delSequence(sequence); - } - else if (opcode == Protocol::OP_OBJECT_INDICATION) { - object = broker.handleObjectIndication(buffer, sequence, true, true); - if (object.get() != 0) - queryResponse->impl->results.push_back(object); - } - else { - QPID_LOG(trace, "QueryContext::handleMessage invalid opcode: " << opcode); - completeContext = true; - } - - return completeContext; -} - -void MethodContext::release() -{ - Mutex::ScopedLock _block(broker.lock); - broker.eventQueue.push_back(broker.eventMethodResponse(userContext, methodResponse)); -} - -bool MethodContext::handleMessage(uint8_t opcode, uint32_t sequence, const string& /*routingKey*/, Buffer& buffer) -{ - if (opcode == Protocol::OP_METHOD_RESPONSE) - methodResponse = broker.handleMethodResponse(buffer, sequence, schema); - else - QPID_LOG(trace, "QueryContext::handleMessage invalid opcode: " << opcode); - - return true; -} - - -//================================================================== -// Wrappers -//================================================================== - -AgentProxy::AgentProxy(AgentProxyImpl* i) : impl(i) {} -AgentProxy::AgentProxy(const AgentProxy& from) : impl(new AgentProxyImpl(*(from.impl))) {} -AgentProxy::~AgentProxy() { delete impl; } -const char* AgentProxy::getLabel() const { return impl->getLabel().c_str(); } -uint32_t AgentProxy::getBrokerBank() const { return impl->getBrokerBank(); } -uint32_t AgentProxy::getAgentBank() const { return impl->getAgentBank(); } - -BrokerProxy::BrokerProxy(Console& console) : impl(new BrokerProxyImpl(*this, console)) {} -BrokerProxy::~BrokerProxy() { delete impl; } -void BrokerProxy::sessionOpened(SessionHandle& sh) { impl->sessionOpened(sh); } -void BrokerProxy::sessionClosed() { impl->sessionClosed(); } -void BrokerProxy::startProtocol() { impl->startProtocol(); } -void BrokerProxy::handleRcvMessage(Message& message) { impl->handleRcvMessage(message); } -bool BrokerProxy::getXmtMessage(Message& item) const { return impl->getXmtMessage(item); } -void BrokerProxy::popXmt() { impl->popXmt(); } -bool BrokerProxy::getEvent(BrokerEvent& event) const { return impl->getEvent(event); } -void BrokerProxy::popEvent() { impl->popEvent(); } -uint32_t BrokerProxy::agentCount() const { return impl->agentCount(); } -const AgentProxy* BrokerProxy::getAgent(uint32_t idx) const { return impl->getAgent(idx); } -void BrokerProxy::sendQuery(const Query& query, void* context, const AgentProxy* agent) { impl->sendQuery(query, context, agent); } - -MethodResponse::MethodResponse(const MethodResponse& from) : impl(new MethodResponseImpl(*(from.impl))) {} -MethodResponse::MethodResponse(MethodResponseImpl* i) : impl(i) {} -MethodResponse::~MethodResponse() {} -uint32_t MethodResponse::getStatus() const { return impl->getStatus(); } -const Value* MethodResponse::getException() const { return impl->getException(); } -const Value* MethodResponse::getArgs() const { return impl->getArgs(); } - -QueryResponse::QueryResponse(QueryResponseImpl* i) : impl(i) {} -QueryResponse::~QueryResponse() {} -uint32_t QueryResponse::getStatus() const { return impl->getStatus(); } -const Value* QueryResponse::getException() const { return impl->getException(); } -uint32_t QueryResponse::getObjectCount() const { return impl->getObjectCount(); } -const Object* QueryResponse::getObject(uint32_t idx) const { return impl->getObject(idx); } - diff --git a/cpp/src/qmf/engine/BrokerProxyImpl.h b/cpp/src/qmf/engine/BrokerProxyImpl.h deleted file mode 100644 index 0542b67dbb..0000000000 --- a/cpp/src/qmf/engine/BrokerProxyImpl.h +++ /dev/null @@ -1,241 +0,0 @@ -#ifndef _QmfEngineBrokerProxyImpl_ -#define _QmfEngineBrokerProxyImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/Console.h" -#include "qmf/engine/ObjectImpl.h" -#include "qmf/engine/EventImpl.h" -#include "qmf/engine/SchemaImpl.h" -#include "qmf/engine/ValueImpl.h" -#include "qmf/engine/QueryImpl.h" -#include "qmf/engine/SequenceManager.h" -#include "qmf/engine/MessageImpl.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/Mutex.h" -#include "boost/shared_ptr.hpp" -#include "boost/noncopyable.hpp" -#include <memory> -#include <string> -#include <deque> -#include <map> -#include <set> -#include <vector> - -namespace qmf { -namespace engine { - - typedef boost::shared_ptr<MethodResponse> MethodResponsePtr; - struct MethodResponseImpl { - uint32_t status; - const SchemaMethod* schema; - std::auto_ptr<Value> exception; - std::auto_ptr<Value> arguments; - - MethodResponseImpl(const MethodResponseImpl& from); - MethodResponseImpl(qpid::framing::Buffer& buf, const SchemaMethod* schema); - MethodResponseImpl(uint32_t status, const std::string& text); - static MethodResponse* factory(qpid::framing::Buffer& buf, const SchemaMethod* schema); - static MethodResponse* factory(uint32_t status, const std::string& text); - ~MethodResponseImpl() {} - uint32_t getStatus() const { return status; } - const Value* getException() const { return exception.get(); } - const Value* getArgs() const { return arguments.get(); } - }; - - typedef boost::shared_ptr<QueryResponse> QueryResponsePtr; - struct QueryResponseImpl { - uint32_t status; - std::auto_ptr<Value> exception; - std::vector<ObjectPtr> results; - - QueryResponseImpl() : status(0) {} - static QueryResponse* factory() { - QueryResponseImpl* impl(new QueryResponseImpl()); - return new QueryResponse(impl); - } - ~QueryResponseImpl() {} - uint32_t getStatus() const { return status; } - const Value* getException() const { return exception.get(); } - uint32_t getObjectCount() const { return results.size(); } - const Object* getObject(uint32_t idx) const; - }; - - struct BrokerEventImpl { - typedef boost::shared_ptr<BrokerEventImpl> Ptr; - BrokerEvent::EventKind kind; - std::string name; - std::string exchange; - std::string bindingKey; - void* context; - QueryResponsePtr queryResponse; - MethodResponsePtr methodResponse; - - BrokerEventImpl(BrokerEvent::EventKind k) : kind(k), context(0) {} - ~BrokerEventImpl() {} - BrokerEvent copy(); - }; - - typedef boost::shared_ptr<AgentProxy> AgentProxyPtr; - struct AgentProxyImpl { - Console& console; - BrokerProxy& broker; - uint32_t agentBank; - std::string label; - std::set<uint32_t> inFlightSequences; - - AgentProxyImpl(Console& c, BrokerProxy& b, uint32_t ab, const std::string& l) : console(c), broker(b), agentBank(ab), label(l) {} - static AgentProxy* factory(Console& c, BrokerProxy& b, uint32_t ab, const std::string& l) { - AgentProxyImpl* impl(new AgentProxyImpl(c, b, ab, l)); - return new AgentProxy(impl); - } - ~AgentProxyImpl() {} - const std::string& getLabel() const { return label; } - uint32_t getBrokerBank() const { return 1; } - uint32_t getAgentBank() const { return agentBank; } - void addSequence(uint32_t seq) { inFlightSequences.insert(seq); } - void delSequence(uint32_t seq) { inFlightSequences.erase(seq); } - void releaseInFlight(SequenceManager& seqMgr) { - for (std::set<uint32_t>::iterator iter = inFlightSequences.begin(); iter != inFlightSequences.end(); iter++) - seqMgr.release(*iter); - inFlightSequences.clear(); - } - }; - - class BrokerProxyImpl : public boost::noncopyable { - public: - BrokerProxyImpl(BrokerProxy& pub, Console& _console); - ~BrokerProxyImpl() {} - - void sessionOpened(SessionHandle& sh); - void sessionClosed(); - void startProtocol(); - - void sendBufferLH(qpid::framing::Buffer& buf, const std::string& destination, const std::string& routingKey); - void handleRcvMessage(Message& message); - bool getXmtMessage(Message& item) const; - void popXmt(); - - bool getEvent(BrokerEvent& event) const; - void popEvent(); - - uint32_t agentCount() const; - const AgentProxy* getAgent(uint32_t idx) const; - void sendQuery(const Query& query, void* context, const AgentProxy* agent); - bool sendGetRequestLH(SequenceContext::Ptr queryContext, const Query& query, const AgentProxy* agent); - std::string encodeMethodArguments(const SchemaMethod* schema, const Value* args, qpid::framing::Buffer& buffer); - std::string encodedSizeMethodArguments(const SchemaMethod* schema, const Value* args, uint32_t& size); - void sendMethodRequest(ObjectId* oid, const SchemaObjectClass* cls, const std::string& method, const Value* args, void* context); - - void addBinding(const std::string& exchange, const std::string& key); - void staticRelease() { decOutstanding(); } - - private: - friend struct StaticContext; - friend struct QueryContext; - friend struct MethodContext; - BrokerProxy& publicObject; - mutable qpid::sys::Mutex lock; - Console& console; - std::string queueName; - qpid::framing::Uuid brokerId; - SequenceManager seqMgr; - uint32_t requestsOutstanding; - bool topicBound; - std::map<uint32_t, AgentProxyPtr> agentList; - std::deque<MessageImpl::Ptr> xmtQueue; - std::deque<BrokerEventImpl::Ptr> eventQueue; - -# define MA_BUFFER_SIZE 65536 - char outputBuffer[MA_BUFFER_SIZE]; - - BrokerEventImpl::Ptr eventDeclareQueue(const std::string& queueName); - BrokerEventImpl::Ptr eventBind(const std::string& exchange, const std::string& queue, const std::string& key); - BrokerEventImpl::Ptr eventSetupComplete(); - BrokerEventImpl::Ptr eventStable(); - BrokerEventImpl::Ptr eventQueryComplete(void* context, QueryResponsePtr response); - BrokerEventImpl::Ptr eventMethodResponse(void* context, MethodResponsePtr response); - - void handleBrokerResponse(qpid::framing::Buffer& inBuffer, uint32_t seq); - void handlePackageIndication(qpid::framing::Buffer& inBuffer, uint32_t seq); - void handleCommandComplete(qpid::framing::Buffer& inBuffer, uint32_t seq); - void handleClassIndication(qpid::framing::Buffer& inBuffer, uint32_t seq); - MethodResponsePtr handleMethodResponse(qpid::framing::Buffer& inBuffer, uint32_t seq, const SchemaMethod* schema); - void handleHeartbeatIndication(qpid::framing::Buffer& inBuffer, uint32_t seq, const std::string& routingKey); - void handleEventIndication(qpid::framing::Buffer& inBuffer, uint32_t seq); - void handleSchemaResponse(qpid::framing::Buffer& inBuffer, uint32_t seq); - ObjectPtr handleObjectIndication(qpid::framing::Buffer& inBuffer, uint32_t seq, bool prop, bool stat); - void updateAgentList(ObjectPtr obj); - void incOutstandingLH(); - void decOutstanding(); - }; - - // - // StaticContext is used to handle: - // - // 1) Responses to console-level requests (for schema info, etc.) - // 2) Unsolicited messages from agents (events, published updates, etc.) - // - struct StaticContext : public SequenceContext { - StaticContext(BrokerProxyImpl& b) : broker(b) {} - virtual ~StaticContext() {} - void reserve() {} - void release() { broker.staticRelease(); } - bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer); - BrokerProxyImpl& broker; - }; - - // - // QueryContext is used to track and handle responses associated with a single Get Query - // - struct QueryContext : public SequenceContext { - QueryContext(BrokerProxyImpl& b, void* u) : - broker(b), userContext(u), requestsOutstanding(0), queryResponse(QueryResponseImpl::factory()) {} - virtual ~QueryContext() {} - void reserve(); - void release(); - bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer); - - mutable qpid::sys::Mutex lock; - BrokerProxyImpl& broker; - void* userContext; - uint32_t requestsOutstanding; - QueryResponsePtr queryResponse; - }; - - struct MethodContext : public SequenceContext { - MethodContext(BrokerProxyImpl& b, void* u, const SchemaMethod* s) : broker(b), userContext(u), schema(s) {} - virtual ~MethodContext() {} - void reserve() {} - void release(); - bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer); - - BrokerProxyImpl& broker; - void* userContext; - const SchemaMethod* schema; - MethodResponsePtr methodResponse; - }; - -} -} - -#endif - diff --git a/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp b/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp deleted file mode 100644 index 22a65f28ca..0000000000 --- a/cpp/src/qmf/engine/ConnectionSettingsImpl.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/ConnectionSettingsImpl.h" -#include "qmf/engine/Typecode.h" - -using namespace std; -using namespace qmf::engine; -using namespace qpid; - -const string attrProtocol("protocol"); -const string attrHost("host"); -const string attrPort("port"); -const string attrVirtualhost("virtualhost"); -const string attrUsername("username"); -const string attrPassword("password"); -const string attrMechanism("mechanism"); -const string attrLocale("locale"); -const string attrHeartbeat("heartbeat"); -const string attrMaxChannels("maxChannels"); -const string attrMaxFrameSize("maxFrameSize"); -const string attrBounds("bounds"); -const string attrTcpNoDelay("tcpNoDelay"); -const string attrService("service"); -const string attrMinSsf("minSsf"); -const string attrMaxSsf("maxSsf"); -const string attrRetryDelayMin("retryDelayMin"); -const string attrRetryDelayMax("retryDelayMax"); -const string attrRetryDelayFactor("retryDelayFactor"); -const string attrSendUserId("sendUserId"); - -ConnectionSettingsImpl::ConnectionSettingsImpl() : - retryDelayMin(1), retryDelayMax(64), retryDelayFactor(2), sendUserId(true) -{ -} - -ConnectionSettingsImpl::ConnectionSettingsImpl(const string& /*url*/) : - retryDelayMin(1), retryDelayMax(64), retryDelayFactor(2), sendUserId(true) -{ - // TODO: Parse the URL -} - -bool ConnectionSettingsImpl::setAttr(const string& key, const Value& value) -{ - if (key == attrProtocol) clientSettings.protocol = value.asString(); - else if (key == attrHost) clientSettings.host = value.asString(); - else if (key == attrPort) clientSettings.port = value.asUint(); - else if (key == attrVirtualhost) clientSettings.virtualhost = value.asString(); - else if (key == attrUsername) clientSettings.username = value.asString(); - else if (key == attrPassword) clientSettings.password = value.asString(); - else if (key == attrMechanism) clientSettings.mechanism = value.asString(); - else if (key == attrLocale) clientSettings.locale = value.asString(); - else if (key == attrHeartbeat) clientSettings.heartbeat = value.asUint(); - else if (key == attrMaxChannels) clientSettings.maxChannels = value.asUint(); - else if (key == attrMaxFrameSize) clientSettings.maxFrameSize = value.asUint(); - else if (key == attrBounds) clientSettings.bounds = value.asUint(); - else if (key == attrTcpNoDelay) clientSettings.tcpNoDelay = value.asBool(); - else if (key == attrService) clientSettings.service = value.asString(); - else if (key == attrMinSsf) clientSettings.minSsf = value.asUint(); - else if (key == attrMaxSsf) clientSettings.maxSsf = value.asUint(); - - else if (key == attrRetryDelayMin) retryDelayMin = value.asUint(); - else if (key == attrRetryDelayMax) retryDelayMax = value.asUint(); - else if (key == attrRetryDelayFactor) retryDelayFactor = value.asUint(); - else if (key == attrSendUserId) sendUserId = value.asBool(); - else - return false; - return true; -} - -Value ConnectionSettingsImpl::getAttr(const string& key) const -{ - Value strval(TYPE_LSTR); - Value intval(TYPE_UINT32); - Value boolval(TYPE_BOOL); - - if (key == attrProtocol) { - strval.setString(clientSettings.protocol.c_str()); - return strval; - } - - if (key == attrHost) { - strval.setString(clientSettings.host.c_str()); - return strval; - } - - if (key == attrPort) { - intval.setUint(clientSettings.port); - return intval; - } - - if (key == attrVirtualhost) { - strval.setString(clientSettings.virtualhost.c_str()); - return strval; - } - - if (key == attrUsername) { - strval.setString(clientSettings.username.c_str()); - return strval; - } - - if (key == attrPassword) { - strval.setString(clientSettings.password.c_str()); - return strval; - } - - if (key == attrMechanism) { - strval.setString(clientSettings.mechanism.c_str()); - return strval; - } - - if (key == attrLocale) { - strval.setString(clientSettings.locale.c_str()); - return strval; - } - - if (key == attrHeartbeat) { - intval.setUint(clientSettings.heartbeat); - return intval; - } - - if (key == attrMaxChannels) { - intval.setUint(clientSettings.maxChannels); - return intval; - } - - if (key == attrMaxFrameSize) { - intval.setUint(clientSettings.maxFrameSize); - return intval; - } - - if (key == attrBounds) { - intval.setUint(clientSettings.bounds); - return intval; - } - - if (key == attrTcpNoDelay) { - boolval.setBool(clientSettings.tcpNoDelay); - return boolval; - } - - if (key == attrService) { - strval.setString(clientSettings.service.c_str()); - return strval; - } - - if (key == attrMinSsf) { - intval.setUint(clientSettings.minSsf); - return intval; - } - - if (key == attrMaxSsf) { - intval.setUint(clientSettings.maxSsf); - return intval; - } - - if (key == attrRetryDelayMin) { - intval.setUint(retryDelayMin); - return intval; - } - - if (key == attrRetryDelayMax) { - intval.setUint(retryDelayMax); - return intval; - } - - if (key == attrRetryDelayFactor) { - intval.setUint(retryDelayFactor); - return intval; - } - - if (key == attrSendUserId) { - boolval.setBool(sendUserId); - return boolval; - } - - return strval; -} - -const string& ConnectionSettingsImpl::getAttrString() const -{ - // TODO: build and return attribute string - return attrString; -} - -void ConnectionSettingsImpl::transportTcp(uint16_t port) -{ - clientSettings.protocol = "tcp"; - clientSettings.port = port; -} - -void ConnectionSettingsImpl::transportSsl(uint16_t port) -{ - clientSettings.protocol = "ssl"; - clientSettings.port = port; -} - -void ConnectionSettingsImpl::transportRdma(uint16_t port) -{ - clientSettings.protocol = "rdma"; - clientSettings.port = port; -} - -void ConnectionSettingsImpl::authAnonymous(const string& username) -{ - clientSettings.mechanism = "ANONYMOUS"; - clientSettings.username = username; -} - -void ConnectionSettingsImpl::authPlain(const string& username, const string& password) -{ - clientSettings.mechanism = "PLAIN"; - clientSettings.username = username; - clientSettings.password = password; -} - -void ConnectionSettingsImpl::authGssapi(const string& serviceName, uint32_t minSsf, uint32_t maxSsf) -{ - clientSettings.mechanism = "GSSAPI"; - clientSettings.service = serviceName; - clientSettings.minSsf = minSsf; - clientSettings.maxSsf = maxSsf; -} - -void ConnectionSettingsImpl::setRetry(int delayMin, int delayMax, int delayFactor) -{ - retryDelayMin = delayMin; - retryDelayMax = delayMax; - retryDelayFactor = delayFactor; -} - -const client::ConnectionSettings& ConnectionSettingsImpl::getClientSettings() const -{ - return clientSettings; -} - -void ConnectionSettingsImpl::getRetrySettings(int* min, int* max, int* factor) const -{ - *min = retryDelayMin; - *max = retryDelayMax; - *factor = retryDelayFactor; -} - -//================================================================== -// Wrappers -//================================================================== - -ConnectionSettings::ConnectionSettings(const ConnectionSettings& from) { impl = new ConnectionSettingsImpl(*from.impl); } -ConnectionSettings::ConnectionSettings() { impl = new ConnectionSettingsImpl(); } -ConnectionSettings::ConnectionSettings(const char* url) { impl = new ConnectionSettingsImpl(url); } -ConnectionSettings::~ConnectionSettings() { delete impl; } -bool ConnectionSettings::setAttr(const char* key, const Value& value) { return impl->setAttr(key, value); } -Value ConnectionSettings::getAttr(const char* key) const { return impl->getAttr(key); } -const char* ConnectionSettings::getAttrString() const { return impl->getAttrString().c_str(); } -void ConnectionSettings::transportTcp(uint16_t port) { impl->transportTcp(port); } -void ConnectionSettings::transportSsl(uint16_t port) { impl->transportSsl(port); } -void ConnectionSettings::transportRdma(uint16_t port) { impl->transportRdma(port); } -void ConnectionSettings::authAnonymous(const char* username) { impl->authAnonymous(username); } -void ConnectionSettings::authPlain(const char* username, const char* password) { impl->authPlain(username, password); } -void ConnectionSettings::authGssapi(const char* serviceName, uint32_t minSsf, uint32_t maxSsf) { impl->authGssapi(serviceName, minSsf, maxSsf); } -void ConnectionSettings::setRetry(int delayMin, int delayMax, int delayFactor) { impl->setRetry(delayMin, delayMax, delayFactor); } - diff --git a/cpp/src/qmf/engine/ConnectionSettingsImpl.h b/cpp/src/qmf/engine/ConnectionSettingsImpl.h deleted file mode 100644 index 98bf87868b..0000000000 --- a/cpp/src/qmf/engine/ConnectionSettingsImpl.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _QmfEngineConnectionSettingsImpl_ -#define _QmfEngineConnectionSettingsImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/ConnectionSettings.h" -#include "qmf/engine/Value.h" -#include "qpid/client/ConnectionSettings.h" -#include <string> -#include <map> - -namespace qmf { -namespace engine { - - class ConnectionSettingsImpl { - qpid::client::ConnectionSettings clientSettings; - mutable std::string attrString; - int retryDelayMin; - int retryDelayMax; - int retryDelayFactor; - bool sendUserId; - - public: - ConnectionSettingsImpl(); - ConnectionSettingsImpl(const std::string& url); - ~ConnectionSettingsImpl() {} - bool setAttr(const std::string& key, const Value& value); - Value getAttr(const std::string& key) const; - const std::string& getAttrString() const; - void transportTcp(uint16_t port); - void transportSsl(uint16_t port); - void transportRdma(uint16_t port); - void authAnonymous(const std::string& username); - void authPlain(const std::string& username, const std::string& password); - void authGssapi(const std::string& serviceName, uint32_t minSsf, uint32_t maxSsf); - void setRetry(int delayMin, int delayMax, int delayFactor); - - const qpid::client::ConnectionSettings& getClientSettings() const; - void getRetrySettings(int* delayMin, int* delayMax, int* delayFactor) const; - bool getSendUserId() const { return sendUserId; } - }; - -} -} - -#endif diff --git a/cpp/src/qmf/engine/ConsoleImpl.cpp b/cpp/src/qmf/engine/ConsoleImpl.cpp deleted file mode 100644 index 4a5da31bdc..0000000000 --- a/cpp/src/qmf/engine/ConsoleImpl.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/ConsoleImpl.h" -#include "qmf/engine/MessageImpl.h" -#include "qmf/engine/SchemaImpl.h" -#include "qmf/engine/Typecode.h" -#include "qmf/engine/ObjectImpl.h" -#include "qmf/engine/ObjectIdImpl.h" -#include "qmf/engine/QueryImpl.h" -#include "qmf/engine/ValueImpl.h" -#include "qmf/engine/Protocol.h" -#include "qmf/engine/SequenceManager.h" -#include "qmf/engine/BrokerProxyImpl.h" -#include <qpid/framing/Buffer.h> -#include <qpid/framing/Uuid.h> -#include <qpid/framing/FieldTable.h> -#include <qpid/framing/FieldValue.h> -#include <qpid/log/Statement.h> -#include <qpid/sys/Time.h> -#include <qpid/sys/SystemInfo.h> -#include <string.h> -#include <iostream> -#include <fstream> - -using namespace std; -using namespace qmf::engine; -using namespace qpid::framing; -using namespace qpid::sys; - -namespace { - const char* QMF_EXCHANGE = "qpid.management"; -} - -#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());} - -ConsoleEvent ConsoleEventImpl::copy() -{ - ConsoleEvent item; - - ::memset(&item, 0, sizeof(ConsoleEvent)); - item.kind = kind; - item.agent = agent.get(); - item.classKey = classKey; - item.object = object.get(); - item.context = context; - item.event = event.get(); - item.timestamp = timestamp; - item.hasProps = hasProps; - item.hasStats = hasStats; - - STRING_REF(name); - - return item; -} - -ConsoleImpl::ConsoleImpl(const ConsoleSettings& s) : settings(s) -{ - bindingList.push_back(pair<string, string>(string(), "schema.#")); - if (settings.rcvObjects && settings.rcvEvents && settings.rcvHeartbeats && !settings.userBindings) { - bindingList.push_back(pair<string, string>(string(), "console.#")); - } else { - if (settings.rcvObjects && !settings.userBindings) - bindingList.push_back(pair<string, string>(string(), "console.obj.#")); - else - bindingList.push_back(pair<string, string>(string(), "console.obj.*.*.org.apache.qpid.broker.agent")); - if (settings.rcvEvents) - bindingList.push_back(pair<string, string>(string(), "console.event.#")); - if (settings.rcvHeartbeats) - bindingList.push_back(pair<string, string>(string(), "console.heartbeat.#")); - } -} - -ConsoleImpl::~ConsoleImpl() -{ - // This function intentionally left blank. -} - -bool ConsoleImpl::getEvent(ConsoleEvent& event) const -{ - Mutex::ScopedLock _lock(lock); - if (eventQueue.empty()) - return false; - event = eventQueue.front()->copy(); - return true; -} - -void ConsoleImpl::popEvent() -{ - Mutex::ScopedLock _lock(lock); - if (!eventQueue.empty()) - eventQueue.pop_front(); -} - -void ConsoleImpl::addConnection(BrokerProxy& broker, void* /*context*/) -{ - Mutex::ScopedLock _lock(lock); - brokerList.push_back(broker.impl); -} - -void ConsoleImpl::delConnection(BrokerProxy& broker) -{ - Mutex::ScopedLock _lock(lock); - for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin(); - iter != brokerList.end(); iter++) - if (*iter == broker.impl) { - brokerList.erase(iter); - break; - } -} - -uint32_t ConsoleImpl::packageCount() const -{ - Mutex::ScopedLock _lock(lock); - return packages.size(); -} - -const string& ConsoleImpl::getPackageName(uint32_t idx) const -{ - const static string empty; - - Mutex::ScopedLock _lock(lock); - if (idx >= packages.size()) - return empty; - - PackageList::const_iterator iter = packages.begin(); - for (uint32_t i = 0; i < idx; i++) iter++; - return iter->first; -} - -uint32_t ConsoleImpl::classCount(const char* packageName) const -{ - Mutex::ScopedLock _lock(lock); - PackageList::const_iterator pIter = packages.find(packageName); - if (pIter == packages.end()) - return 0; - - const ObjectClassList& oList = pIter->second.first; - const EventClassList& eList = pIter->second.second; - - return oList.size() + eList.size(); -} - -const SchemaClassKey* ConsoleImpl::getClass(const char* packageName, uint32_t idx) const -{ - Mutex::ScopedLock _lock(lock); - PackageList::const_iterator pIter = packages.find(packageName); - if (pIter == packages.end()) - return 0; - - const ObjectClassList& oList = pIter->second.first; - const EventClassList& eList = pIter->second.second; - uint32_t count = 0; - - for (ObjectClassList::const_iterator oIter = oList.begin(); - oIter != oList.end(); oIter++) { - if (count == idx) - return oIter->second->getClassKey(); - count++; - } - - for (EventClassList::const_iterator eIter = eList.begin(); - eIter != eList.end(); eIter++) { - if (count == idx) - return eIter->second->getClassKey(); - count++; - } - - return 0; -} - -ClassKind ConsoleImpl::getClassKind(const SchemaClassKey* key) const -{ - Mutex::ScopedLock _lock(lock); - PackageList::const_iterator pIter = packages.find(key->getPackageName()); - if (pIter == packages.end()) - return CLASS_OBJECT; - - const EventClassList& eList = pIter->second.second; - if (eList.find(key) != eList.end()) - return CLASS_EVENT; - return CLASS_OBJECT; -} - -const SchemaObjectClass* ConsoleImpl::getObjectClass(const SchemaClassKey* key) const -{ - Mutex::ScopedLock _lock(lock); - PackageList::const_iterator pIter = packages.find(key->getPackageName()); - if (pIter == packages.end()) - return 0; - - const ObjectClassList& oList = pIter->second.first; - ObjectClassList::const_iterator iter = oList.find(key); - if (iter == oList.end()) - return 0; - return iter->second; -} - -const SchemaEventClass* ConsoleImpl::getEventClass(const SchemaClassKey* key) const -{ - Mutex::ScopedLock _lock(lock); - PackageList::const_iterator pIter = packages.find(key->getPackageName()); - if (pIter == packages.end()) - return 0; - - const EventClassList& eList = pIter->second.second; - EventClassList::const_iterator iter = eList.find(key); - if (iter == eList.end()) - return 0; - return iter->second; -} - -void ConsoleImpl::bindPackage(const char* packageName) -{ - stringstream key; - key << "console.obj.*.*." << packageName << ".#"; - Mutex::ScopedLock _lock(lock); - bindingList.push_back(pair<string, string>(string(), key.str())); - for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin(); - iter != brokerList.end(); iter++) - (*iter)->addBinding(QMF_EXCHANGE, key.str()); -} - -void ConsoleImpl::bindClass(const SchemaClassKey* classKey) -{ - stringstream key; - key << "console.obj.*.*." << classKey->getPackageName() << "." << classKey->getClassName() << ".#"; - Mutex::ScopedLock _lock(lock); - bindingList.push_back(pair<string, string>(string(), key.str())); - for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin(); - iter != brokerList.end(); iter++) - (*iter)->addBinding(QMF_EXCHANGE, key.str()); -} - -void ConsoleImpl::bindClass(const char* packageName, const char* className) -{ - stringstream key; - key << "console.obj.*.*." << packageName << "." << className << ".#"; - Mutex::ScopedLock _lock(lock); - bindingList.push_back(pair<string, string>(string(), key.str())); - for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin(); - iter != brokerList.end(); iter++) - (*iter)->addBinding(QMF_EXCHANGE, key.str()); -} - - -void ConsoleImpl::bindEvent(const SchemaClassKey* classKey) -{ - bindEvent(classKey->getPackageName(), classKey->getClassName()); -} - -void ConsoleImpl::bindEvent(const char* packageName, const char* eventName) -{ - if (!settings.userBindings) throw qpid::Exception("Console not configured for userBindings."); - if (settings.rcvEvents) throw qpid::Exception("Console already configured to receive all events."); - - stringstream key; - key << "console.event.*.*." << packageName; - if (eventName && *eventName) { - key << "." << eventName << ".#"; - } else { - key << ".#"; - } - - Mutex::ScopedLock _lock(lock); - bindingList.push_back(pair<string, string>(string(), key.str())); - for (vector<BrokerProxyImpl*>::iterator iter = brokerList.begin(); - iter != brokerList.end(); iter++) - (*iter)->addBinding(QMF_EXCHANGE, key.str()); -} - -/* -void ConsoleImpl::startSync(const Query& query, void* context, SyncQuery& sync) -{ -} - -void ConsoleImpl::touchSync(SyncQuery& sync) -{ -} - -void ConsoleImpl::endSync(SyncQuery& sync) -{ -} -*/ - -void ConsoleImpl::learnPackage(const string& packageName) -{ - Mutex::ScopedLock _lock(lock); - if (packages.find(packageName) == packages.end()) { - packages.insert(pair<string, pair<ObjectClassList, EventClassList> > - (packageName, pair<ObjectClassList, EventClassList>(ObjectClassList(), EventClassList()))); - eventNewPackage(packageName); - } -} - -void ConsoleImpl::learnClass(SchemaObjectClass* cls) -{ - Mutex::ScopedLock _lock(lock); - const SchemaClassKey* key = cls->getClassKey(); - PackageList::iterator pIter = packages.find(key->getPackageName()); - if (pIter == packages.end()) - return; - - ObjectClassList& list = pIter->second.first; - if (list.find(key) == list.end()) { - list[key] = cls; - eventNewClass(key); - } -} - -void ConsoleImpl::learnClass(SchemaEventClass* cls) -{ - Mutex::ScopedLock _lock(lock); - const SchemaClassKey* key = cls->getClassKey(); - PackageList::iterator pIter = packages.find(key->getPackageName()); - if (pIter == packages.end()) - return; - - EventClassList& list = pIter->second.second; - if (list.find(key) == list.end()) { - list[key] = cls; - eventNewClass(key); - } -} - -bool ConsoleImpl::haveClass(const SchemaClassKey* key) const -{ - Mutex::ScopedLock _lock(lock); - PackageList::const_iterator pIter = packages.find(key->getPackageName()); - if (pIter == packages.end()) - return false; - - const ObjectClassList& oList = pIter->second.first; - const EventClassList& eList = pIter->second.second; - - return oList.find(key) != oList.end() || eList.find(key) != eList.end(); -} - -SchemaObjectClass* ConsoleImpl::getSchema(const SchemaClassKey* key) const -{ - Mutex::ScopedLock _lock(lock); - PackageList::const_iterator pIter = packages.find(key->getPackageName()); - if (pIter == packages.end()) - return 0; - - const ObjectClassList& oList = pIter->second.first; - ObjectClassList::const_iterator iter = oList.find(key); - if (iter == oList.end()) - return 0; - - return iter->second; -} - -void ConsoleImpl::eventAgentAdded(boost::shared_ptr<AgentProxy> agent) -{ - ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::AGENT_ADDED)); - event->agent = agent; - Mutex::ScopedLock _lock(lock); - eventQueue.push_back(event); -} - -void ConsoleImpl::eventAgentDeleted(boost::shared_ptr<AgentProxy> agent) -{ - ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::AGENT_DELETED)); - event->agent = agent; - Mutex::ScopedLock _lock(lock); - eventQueue.push_back(event); -} - -void ConsoleImpl::eventNewPackage(const string& packageName) -{ - ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::NEW_PACKAGE)); - event->name = packageName; - Mutex::ScopedLock _lock(lock); - eventQueue.push_back(event); -} - -void ConsoleImpl::eventNewClass(const SchemaClassKey* key) -{ - ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::NEW_CLASS)); - event->classKey = key; - Mutex::ScopedLock _lock(lock); - eventQueue.push_back(event); -} - -void ConsoleImpl::eventObjectUpdate(ObjectPtr object, bool prop, bool stat) -{ - ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::OBJECT_UPDATE)); - event->object = object; - event->hasProps = prop; - event->hasStats = stat; - Mutex::ScopedLock _lock(lock); - eventQueue.push_back(event); -} - -void ConsoleImpl::eventAgentHeartbeat(boost::shared_ptr<AgentProxy> agent, uint64_t timestamp) -{ - ConsoleEventImpl::Ptr event(new ConsoleEventImpl(ConsoleEvent::AGENT_HEARTBEAT)); - event->agent = agent; - event->timestamp = timestamp; - Mutex::ScopedLock _lock(lock); - eventQueue.push_back(event); -} - - -void ConsoleImpl::eventEventReceived(EventPtr event) -{ - ConsoleEventImpl::Ptr console_event(new ConsoleEventImpl(ConsoleEvent::EVENT_RECEIVED)); - console_event->event = event; - Mutex::ScopedLock _lock(lock); - eventQueue.push_back(console_event); -} - -//================================================================== -// Wrappers -//================================================================== - -Console::Console(const ConsoleSettings& settings) : impl(new ConsoleImpl(settings)) {} -Console::~Console() { delete impl; } -bool Console::getEvent(ConsoleEvent& event) const { return impl->getEvent(event); } -void Console::popEvent() { impl->popEvent(); } -void Console::addConnection(BrokerProxy& broker, void* context) { impl->addConnection(broker, context); } -void Console::delConnection(BrokerProxy& broker) { impl->delConnection(broker); } -uint32_t Console::packageCount() const { return impl->packageCount(); } -const char* Console::getPackageName(uint32_t idx) const { return impl->getPackageName(idx).c_str(); } -uint32_t Console::classCount(const char* packageName) const { return impl->classCount(packageName); } -const SchemaClassKey* Console::getClass(const char* packageName, uint32_t idx) const { return impl->getClass(packageName, idx); } -ClassKind Console::getClassKind(const SchemaClassKey* key) const { return impl->getClassKind(key); } -const SchemaObjectClass* Console::getObjectClass(const SchemaClassKey* key) const { return impl->getObjectClass(key); } -const SchemaEventClass* Console::getEventClass(const SchemaClassKey* key) const { return impl->getEventClass(key); } -void Console::bindPackage(const char* packageName) { impl->bindPackage(packageName); } -void Console::bindClass(const SchemaClassKey* key) { impl->bindClass(key); } -void Console::bindClass(const char* packageName, const char* className) { impl->bindClass(packageName, className); } - -void Console::bindEvent(const SchemaClassKey *key) { impl->bindEvent(key); } -void Console::bindEvent(const char* packageName, const char* eventName) { impl->bindEvent(packageName, eventName); } - -//void Console::startSync(const Query& query, void* context, SyncQuery& sync) { impl->startSync(query, context, sync); } -//void Console::touchSync(SyncQuery& sync) { impl->touchSync(sync); } -//void Console::endSync(SyncQuery& sync) { impl->endSync(sync); } - - diff --git a/cpp/src/qmf/engine/ConsoleImpl.h b/cpp/src/qmf/engine/ConsoleImpl.h deleted file mode 100644 index 0c27fdabcd..0000000000 --- a/cpp/src/qmf/engine/ConsoleImpl.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef _QmfEngineConsoleEngineImpl_ -#define _QmfEngineConsoleEngineImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/Console.h" -#include "qmf/engine/MessageImpl.h" -#include "qmf/engine/SchemaImpl.h" -#include "qmf/engine/Typecode.h" -#include "qmf/engine/ObjectImpl.h" -#include "qmf/engine/ObjectIdImpl.h" -#include "qmf/engine/QueryImpl.h" -#include "qmf/engine/ValueImpl.h" -#include "qmf/engine/Protocol.h" -#include "qmf/engine/SequenceManager.h" -#include "qmf/engine/BrokerProxyImpl.h" -#include <qpid/framing/Buffer.h> -#include <qpid/framing/Uuid.h> -#include <qpid/framing/FieldTable.h> -#include <qpid/framing/FieldValue.h> -#include <qpid/sys/Mutex.h> -#include <qpid/sys/Time.h> -#include <qpid/sys/SystemInfo.h> -#include <string.h> -#include <string> -#include <deque> -#include <map> -#include <vector> -#include <iostream> -#include <fstream> -#include <boost/shared_ptr.hpp> -#include <boost/noncopyable.hpp> - -namespace qmf { -namespace engine { - - struct ConsoleEventImpl { - typedef boost::shared_ptr<ConsoleEventImpl> Ptr; - ConsoleEvent::EventKind kind; - boost::shared_ptr<AgentProxy> agent; - std::string name; - const SchemaClassKey* classKey; - boost::shared_ptr<Object> object; - void* context; - boost::shared_ptr<Event> event; - uint64_t timestamp; - bool hasProps; - bool hasStats; - - ConsoleEventImpl(ConsoleEvent::EventKind k) : - kind(k), classKey(0), context(0), timestamp(0) {} - ~ConsoleEventImpl() {} - ConsoleEvent copy(); - }; - - class ConsoleImpl : public boost::noncopyable { - public: - ConsoleImpl(const ConsoleSettings& settings = ConsoleSettings()); - ~ConsoleImpl(); - - bool getEvent(ConsoleEvent& event) const; - void popEvent(); - - void addConnection(BrokerProxy& broker, void* context); - void delConnection(BrokerProxy& broker); - - uint32_t packageCount() const; - const std::string& getPackageName(uint32_t idx) const; - - uint32_t classCount(const char* packageName) const; - const SchemaClassKey* getClass(const char* packageName, uint32_t idx) const; - - ClassKind getClassKind(const SchemaClassKey* key) const; - const SchemaObjectClass* getObjectClass(const SchemaClassKey* key) const; - const SchemaEventClass* getEventClass(const SchemaClassKey* key) const; - - void bindPackage(const char* packageName); - void bindClass(const SchemaClassKey* key); - void bindClass(const char* packageName, const char* className); - void bindEvent(const SchemaClassKey* key); - void bindEvent(const char* packageName, const char* eventName); - - /* - void startSync(const Query& query, void* context, SyncQuery& sync); - void touchSync(SyncQuery& sync); - void endSync(SyncQuery& sync); - */ - - private: - friend class BrokerProxyImpl; - friend struct StaticContext; - const ConsoleSettings& settings; - mutable qpid::sys::Mutex lock; - std::deque<ConsoleEventImpl::Ptr> eventQueue; - std::vector<BrokerProxyImpl*> brokerList; - std::vector<std::pair<std::string, std::string> > bindingList; // exchange/key (empty exchange => QMF_EXCHANGE) - - // Declare a compare class for the class maps that compares the dereferenced - // class key pointers. The default behavior would be to compare the pointer - // addresses themselves. - struct KeyCompare { - bool operator()(const SchemaClassKey* left, const SchemaClassKey* right) const { - return *left < *right; - } - }; - - typedef std::map<const SchemaClassKey*, SchemaObjectClass*, KeyCompare> ObjectClassList; - typedef std::map<const SchemaClassKey*, SchemaEventClass*, KeyCompare> EventClassList; - typedef std::map<std::string, std::pair<ObjectClassList, EventClassList> > PackageList; - - PackageList packages; - - void learnPackage(const std::string& packageName); - void learnClass(SchemaObjectClass* cls); - void learnClass(SchemaEventClass* cls); - bool haveClass(const SchemaClassKey* key) const; - SchemaObjectClass* getSchema(const SchemaClassKey* key) const; - - void eventAgentAdded(boost::shared_ptr<AgentProxy> agent); - void eventAgentDeleted(boost::shared_ptr<AgentProxy> agent); - void eventNewPackage(const std::string& packageName); - void eventNewClass(const SchemaClassKey* key); - void eventObjectUpdate(ObjectPtr object, bool prop, bool stat); - void eventAgentHeartbeat(boost::shared_ptr<AgentProxy> agent, uint64_t timestamp); - void eventEventReceived(boost::shared_ptr<Event> event); - }; -} -} - -#endif - diff --git a/cpp/src/qmf/engine/EventImpl.cpp b/cpp/src/qmf/engine/EventImpl.cpp deleted file mode 100644 index 4b034e8e83..0000000000 --- a/cpp/src/qmf/engine/EventImpl.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qmf/engine/EventImpl.h> -#include <qmf/engine/ValueImpl.h> - -#include <sstream> - -using namespace std; -using namespace qmf::engine; -using qpid::framing::Buffer; - -EventImpl::EventImpl(const SchemaEventClass* type) : eventClass(type), timestamp(0), severity(0) -{ - int argCount = eventClass->getArgumentCount(); - int idx; - - for (idx = 0; idx < argCount; idx++) { - const SchemaArgument* arg = eventClass->getArgument(idx); - arguments[arg->getName()] = ValuePtr(new Value(arg->getType())); - } -} - - -EventImpl::EventImpl(const SchemaEventClass* type, Buffer& buffer) : - eventClass(type), timestamp(0), severity(0) -{ - int argCount = eventClass->getArgumentCount(); - int idx; - - timestamp = buffer.getLongLong(); - severity = buffer.getOctet(); - - for (idx = 0; idx < argCount; idx++) - { - const SchemaArgument *arg = eventClass->getArgument(idx); - Value* pval = ValueImpl::factory(arg->getType(), buffer); - arguments[arg->getName()] = ValuePtr(pval); - } -} - - -Event* EventImpl::factory(const SchemaEventClass* type, Buffer& buffer) -{ - EventImpl* impl(new EventImpl(type, buffer)); - return new Event(impl); -} - - -Value* EventImpl::getValue(const char* key) const -{ - map<string, ValuePtr>::const_iterator iter; - - iter = arguments.find(key); - if (iter != arguments.end()) - return iter->second.get(); - - return 0; -} - - -void EventImpl::encodeSchemaKey(Buffer& buffer) const -{ - buffer.putShortString(eventClass->getClassKey()->getPackageName()); - buffer.putShortString(eventClass->getClassKey()->getClassName()); - buffer.putBin128(const_cast<uint8_t*>(eventClass->getClassKey()->getHash())); -} - - -void EventImpl::encode(Buffer& buffer) const -{ - buffer.putOctet((uint8_t) eventClass->getSeverity()); - - int argCount = eventClass->getArgumentCount(); - for (int idx = 0; idx < argCount; idx++) { - const SchemaArgument* arg = eventClass->getArgument(idx); - ValuePtr value = arguments[arg->getName()]; - value->impl->encode(buffer); - } -} - - -string EventImpl::getRoutingKey(uint32_t brokerBank, uint32_t agentBank) const -{ - stringstream key; - - key << "console.event." << brokerBank << "." << agentBank << "." << - eventClass->getClassKey()->getPackageName() << "." << - eventClass->getClassKey()->getClassName(); - return key.str(); -} - - -//================================================================== -// Wrappers -//================================================================== - -Event::Event(const SchemaEventClass* type) : impl(new EventImpl(type)) {} -Event::Event(EventImpl* i) : impl(i) {} -Event::Event(const Event& from) : impl(new EventImpl(*(from.impl))) {} -Event::~Event() { delete impl; } -const SchemaEventClass* Event::getClass() const { return impl->getClass(); } -Value* Event::getValue(const char* key) const { return impl->getValue(key); } - diff --git a/cpp/src/qmf/engine/EventImpl.h b/cpp/src/qmf/engine/EventImpl.h deleted file mode 100644 index 4046e71ef9..0000000000 --- a/cpp/src/qmf/engine/EventImpl.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _QmfEngineEventImpl_ -#define _QmfEngineEventImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qmf/engine/Event.h> -#include <qmf/engine/Schema.h> -#include <qpid/framing/Buffer.h> -#include <boost/shared_ptr.hpp> -#include <map> - -namespace qmf { -namespace engine { - - typedef boost::shared_ptr<Event> EventPtr; - - struct EventImpl { - typedef boost::shared_ptr<Value> ValuePtr; - const SchemaEventClass* eventClass; - uint64_t timestamp; - uint8_t severity; - mutable std::map<std::string, ValuePtr> arguments; - - EventImpl(const SchemaEventClass* type); - EventImpl(const SchemaEventClass* type, qpid::framing::Buffer& buffer); - static Event* factory(const SchemaEventClass* type, qpid::framing::Buffer& buffer); - - const SchemaEventClass* getClass() const { return eventClass; } - Value* getValue(const char* key) const; - - void encodeSchemaKey(qpid::framing::Buffer& buffer) const; - void encode(qpid::framing::Buffer& buffer) const; - std::string getRoutingKey(uint32_t brokerBank, uint32_t agentBank) const; - }; - -} -} - -#endif - diff --git a/cpp/src/qmf/engine/MessageImpl.cpp b/cpp/src/qmf/engine/MessageImpl.cpp deleted file mode 100644 index 0047d3eb9d..0000000000 --- a/cpp/src/qmf/engine/MessageImpl.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/MessageImpl.h" -#include <string.h> - -using namespace std; -using namespace qmf::engine; - -#define STRING_REF(s) {if (!s.empty()) item.s = const_cast<char*>(s.c_str());} - -Message MessageImpl::copy() -{ - Message item; - - ::memset(&item, 0, sizeof(Message)); - item.body = const_cast<char*>(body.c_str()); - item.length = body.length(); - STRING_REF(destination); - STRING_REF(routingKey); - STRING_REF(replyExchange); - STRING_REF(replyKey); - STRING_REF(userId); - - return item; -} - diff --git a/cpp/src/qmf/engine/MessageImpl.h b/cpp/src/qmf/engine/MessageImpl.h deleted file mode 100644 index b91291d2e4..0000000000 --- a/cpp/src/qmf/engine/MessageImpl.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _QmfEngineMessageImpl_ -#define _QmfEngineMessageImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/Message.h" -#include <string> -#include <boost/shared_ptr.hpp> - -namespace qmf { -namespace engine { - - struct MessageImpl { - typedef boost::shared_ptr<MessageImpl> Ptr; - std::string body; - std::string destination; - std::string routingKey; - std::string replyExchange; - std::string replyKey; - std::string userId; - - Message copy(); - }; -} -} - -#endif diff --git a/cpp/src/qmf/engine/ObjectIdImpl.cpp b/cpp/src/qmf/engine/ObjectIdImpl.cpp deleted file mode 100644 index 9216f7bac0..0000000000 --- a/cpp/src/qmf/engine/ObjectIdImpl.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/ObjectIdImpl.h" -#include <stdlib.h> -#include <sstream> - -using namespace std; -using namespace qmf::engine; -using qpid::framing::Buffer; - -void AgentAttachment::setBanks(uint32_t broker, uint32_t agent) -{ - first = - ((uint64_t) (broker & 0x000fffff)) << 28 | - ((uint64_t) (agent & 0x0fffffff)); -} - -ObjectIdImpl::ObjectIdImpl(Buffer& buffer) : agent(0) -{ - decode(buffer); -} - -ObjectIdImpl::ObjectIdImpl(AgentAttachment* a, uint8_t flags, uint16_t seq, uint64_t object) : agent(a) -{ - first = - ((uint64_t) (flags & 0x0f)) << 60 | - ((uint64_t) (seq & 0x0fff)) << 48; - second = object; -} - -ObjectId* ObjectIdImpl::factory(Buffer& buffer) -{ - ObjectIdImpl* impl(new ObjectIdImpl(buffer)); - return new ObjectId(impl); -} - -ObjectId* ObjectIdImpl::factory(AgentAttachment* agent, uint8_t flags, uint16_t seq, uint64_t object) -{ - ObjectIdImpl* impl(new ObjectIdImpl(agent, flags, seq, object)); - return new ObjectId(impl); -} - -void ObjectIdImpl::decode(Buffer& buffer) -{ - first = buffer.getLongLong(); - second = buffer.getLongLong(); -} - -void ObjectIdImpl::encode(Buffer& buffer) const -{ - if (agent == 0) - buffer.putLongLong(first); - else - buffer.putLongLong(first | agent->first); - buffer.putLongLong(second); -} - -void ObjectIdImpl::fromString(const std::string& repr) -{ -#define FIELDS 5 -#if defined (_WIN32) && !defined (atoll) -# define atoll(X) _atoi64(X) -#endif - - std::string copy(repr.c_str()); - char* cText; - char* field[FIELDS]; - bool atFieldStart = true; - int idx = 0; - - cText = const_cast<char*>(copy.c_str()); - for (char* cursor = cText; *cursor; cursor++) { - if (atFieldStart) { - if (idx >= FIELDS) - return; // TODO error - field[idx++] = cursor; - atFieldStart = false; - } else { - if (*cursor == '-') { - *cursor = '\0'; - atFieldStart = true; - } - } - } - - if (idx != FIELDS) - return; // TODO error - - first = (atoll(field[0]) << 60) + - (atoll(field[1]) << 48) + - (atoll(field[2]) << 28) + - atoll(field[3]); - second = atoll(field[4]); - agent = 0; -} - -const string& ObjectIdImpl::asString() const -{ - stringstream val; - - val << (int) getFlags() << "-" << getSequence() << "-" << getBrokerBank() << "-" << - getAgentBank() << "-" << getObjectNum(); - repr = val.str(); - return repr; -} - -#define ACTUAL_FIRST (agent == 0 ? first : first | agent->first) -#define ACTUAL_OTHER (other.agent == 0 ? other.first : other.first | other.agent->first) - -uint8_t ObjectIdImpl::getFlags() const -{ - return (ACTUAL_FIRST & 0xF000000000000000LL) >> 60; -} - -uint16_t ObjectIdImpl::getSequence() const -{ - return (ACTUAL_FIRST & 0x0FFF000000000000LL) >> 48; -} - -uint32_t ObjectIdImpl::getBrokerBank() const -{ - return (ACTUAL_FIRST & 0x0000FFFFF0000000LL) >> 28; -} - -uint32_t ObjectIdImpl::getAgentBank() const -{ - return ACTUAL_FIRST & 0x000000000FFFFFFFLL; -} - -uint64_t ObjectIdImpl::getObjectNum() const -{ - return second; -} - -uint32_t ObjectIdImpl::getObjectNumHi() const -{ - return (uint32_t) (second >> 32); -} - -uint32_t ObjectIdImpl::getObjectNumLo() const -{ - return (uint32_t) (second & 0x00000000FFFFFFFFLL); -} - -bool ObjectIdImpl::operator==(const ObjectIdImpl& other) const -{ - return ACTUAL_FIRST == ACTUAL_OTHER && second == other.second; -} - -bool ObjectIdImpl::operator<(const ObjectIdImpl& other) const -{ - return (ACTUAL_FIRST < ACTUAL_OTHER) || ((ACTUAL_FIRST == ACTUAL_OTHER) && (second < other.second)); -} - -bool ObjectIdImpl::operator>(const ObjectIdImpl& other) const -{ - return (ACTUAL_FIRST > ACTUAL_OTHER) || ((ACTUAL_FIRST == ACTUAL_OTHER) && (second > other.second)); -} - - -//================================================================== -// Wrappers -//================================================================== - -ObjectId::ObjectId() : impl(new ObjectIdImpl()) {} -ObjectId::ObjectId(const ObjectId& from) : impl(new ObjectIdImpl(*(from.impl))) {} -ObjectId::ObjectId(ObjectIdImpl* i) : impl(i) {} -ObjectId::~ObjectId() { delete impl; } -uint64_t ObjectId::getObjectNum() const { return impl->getObjectNum(); } -uint32_t ObjectId::getObjectNumHi() const { return impl->getObjectNumHi(); } -uint32_t ObjectId::getObjectNumLo() const { return impl->getObjectNumLo(); } -bool ObjectId::isDurable() const { return impl->isDurable(); } -const char* ObjectId::str() const { return impl->asString().c_str(); } -uint8_t ObjectId::getFlags() const { return impl->getFlags(); } -uint16_t ObjectId::getSequence() const { return impl->getSequence(); } -uint32_t ObjectId::getBrokerBank() const { return impl->getBrokerBank(); } -uint32_t ObjectId::getAgentBank() const { return impl->getAgentBank(); } -bool ObjectId::operator==(const ObjectId& other) const { return *impl == *other.impl; } -bool ObjectId::operator<(const ObjectId& other) const { return *impl < *other.impl; } -bool ObjectId::operator>(const ObjectId& other) const { return *impl > *other.impl; } -bool ObjectId::operator<=(const ObjectId& other) const { return !(*impl > *other.impl); } -bool ObjectId::operator>=(const ObjectId& other) const { return !(*impl < *other.impl); } -ObjectId& ObjectId::operator=(const ObjectId& other) { - ObjectIdImpl *old; - if (this != &other) { - old = impl; - impl = new ObjectIdImpl(*(other.impl)); - if (old) - delete old; - } - return *this; -} - diff --git a/cpp/src/qmf/engine/ObjectIdImpl.h b/cpp/src/qmf/engine/ObjectIdImpl.h deleted file mode 100644 index d70c8efff4..0000000000 --- a/cpp/src/qmf/engine/ObjectIdImpl.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _QmfEngineObjectIdImpl_ -#define _QmfEngineObjectIdImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qmf/engine/ObjectId.h> -#include <qpid/framing/Buffer.h> - -namespace qmf { -namespace engine { - - struct AgentAttachment { - uint64_t first; - - AgentAttachment() : first(0) {} - void setBanks(uint32_t broker, uint32_t bank); - uint64_t getFirst() const { return first; } - }; - - struct ObjectIdImpl { - AgentAttachment* agent; - uint64_t first; - uint64_t second; - mutable std::string repr; - - ObjectIdImpl() : agent(0), first(0), second(0) {} - ObjectIdImpl(qpid::framing::Buffer& buffer); - ObjectIdImpl(AgentAttachment* agent, uint8_t flags, uint16_t seq, uint64_t object); - - static ObjectId* factory(qpid::framing::Buffer& buffer); - static ObjectId* factory(AgentAttachment* agent, uint8_t flags, uint16_t seq, uint64_t object); - - void decode(qpid::framing::Buffer& buffer); - void encode(qpid::framing::Buffer& buffer) const; - void fromString(const std::string& repr); - const std::string& asString() const; - uint8_t getFlags() const; - uint16_t getSequence() const; - uint32_t getBrokerBank() const; - uint32_t getAgentBank() const; - uint64_t getObjectNum() const; - uint32_t getObjectNumHi() const; - uint32_t getObjectNumLo() const; - bool isDurable() const { return getSequence() == 0; } - void setValue(uint64_t f, uint64_t s) { first = f; second = s; agent = 0; } - - bool operator==(const ObjectIdImpl& other) const; - bool operator<(const ObjectIdImpl& other) const; - bool operator>(const ObjectIdImpl& other) const; - }; -} -} - -#endif - diff --git a/cpp/src/qmf/engine/ObjectImpl.cpp b/cpp/src/qmf/engine/ObjectImpl.cpp deleted file mode 100644 index 45925cb804..0000000000 --- a/cpp/src/qmf/engine/ObjectImpl.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/ObjectImpl.h" -#include "qmf/engine/ValueImpl.h" -#include "qmf/engine/BrokerProxyImpl.h" -#include <qpid/sys/Time.h> - -using namespace std; -using namespace qmf::engine; -using namespace qpid::sys; -using qpid::framing::Buffer; - -ObjectImpl::ObjectImpl(const SchemaObjectClass* type) : objectClass(type), broker(0), createTime(uint64_t(Duration(EPOCH, now()))), destroyTime(0), lastUpdatedTime(createTime) -{ - int propCount = objectClass->getPropertyCount(); - int statCount = objectClass->getStatisticCount(); - int idx; - - for (idx = 0; idx < propCount; idx++) { - const SchemaProperty* prop = objectClass->getProperty(idx); - properties[prop->getName()] = ValuePtr(new Value(prop->getType())); - } - - for (idx = 0; idx < statCount; idx++) { - const SchemaStatistic* stat = objectClass->getStatistic(idx); - statistics[stat->getName()] = ValuePtr(new Value(stat->getType())); - } -} - -ObjectImpl::ObjectImpl(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed) : - objectClass(type), broker(b), createTime(0), destroyTime(0), lastUpdatedTime(0) -{ - int idx; - - if (managed) { - lastUpdatedTime = buffer.getLongLong(); - createTime = buffer.getLongLong(); - destroyTime = buffer.getLongLong(); - objectId.reset(ObjectIdImpl::factory(buffer)); - } - - if (prop) { - int propCount = objectClass->getPropertyCount(); - set<string> excludes; - parsePresenceMasks(buffer, excludes); - for (idx = 0; idx < propCount; idx++) { - const SchemaProperty* prop = objectClass->getProperty(idx); - if (excludes.count(prop->getName()) != 0) { - properties[prop->getName()] = ValuePtr(new Value(prop->getType())); - } else { - Value* pval = ValueImpl::factory(prop->getType(), buffer); - properties[prop->getName()] = ValuePtr(pval); - } - } - } - - if (stat) { - int statCount = objectClass->getStatisticCount(); - for (idx = 0; idx < statCount; idx++) { - const SchemaStatistic* stat = objectClass->getStatistic(idx); - Value* sval = ValueImpl::factory(stat->getType(), buffer); - statistics[stat->getName()] = ValuePtr(sval); - } - } -} - -Object* ObjectImpl::factory(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed) -{ - ObjectImpl* impl(new ObjectImpl(type, b, buffer, prop, stat, managed)); - return new Object(impl); -} - -ObjectImpl::~ObjectImpl() -{ -} - -void ObjectImpl::destroy() -{ - destroyTime = uint64_t(Duration(EPOCH, now())); - // TODO - flag deletion -} - -Value* ObjectImpl::getValue(const string& key) const -{ - map<string, ValuePtr>::const_iterator iter; - - iter = properties.find(key); - if (iter != properties.end()) - return iter->second.get(); - - iter = statistics.find(key); - if (iter != statistics.end()) - return iter->second.get(); - - return 0; -} - -void ObjectImpl::invokeMethod(const string& methodName, const Value* inArgs, void* context) const -{ - if (broker != 0 && objectId.get() != 0) - broker->sendMethodRequest(objectId.get(), objectClass, methodName, inArgs, context); -} - -void ObjectImpl::merge(const Object& from) -{ - for (map<string, ValuePtr>::const_iterator piter = from.impl->properties.begin(); - piter != from.impl->properties.end(); piter++) - properties[piter->first] = piter->second; - for (map<string, ValuePtr>::const_iterator siter = from.impl->statistics.begin(); - siter != from.impl->statistics.end(); siter++) - statistics[siter->first] = siter->second; -} - -void ObjectImpl::parsePresenceMasks(Buffer& buffer, set<string>& excludeList) -{ - int propCount = objectClass->getPropertyCount(); - excludeList.clear(); - uint8_t bit = 0; - uint8_t mask = 0; - - for (int idx = 0; idx < propCount; idx++) { - const SchemaProperty* prop = objectClass->getProperty(idx); - if (prop->isOptional()) { - if (bit == 0) { - mask = buffer.getOctet(); - bit = 1; - } - if ((mask & bit) == 0) - excludeList.insert(string(prop->getName())); - if (bit == 0x80) - bit = 0; - else - bit = bit << 1; - } - } -} - -void ObjectImpl::encodeSchemaKey(qpid::framing::Buffer& buffer) const -{ - buffer.putShortString(objectClass->getClassKey()->getPackageName()); - buffer.putShortString(objectClass->getClassKey()->getClassName()); - buffer.putBin128(const_cast<uint8_t*>(objectClass->getClassKey()->getHash())); -} - -void ObjectImpl::encodeManagedObjectData(qpid::framing::Buffer& buffer) const -{ - buffer.putLongLong(lastUpdatedTime); - buffer.putLongLong(createTime); - buffer.putLongLong(destroyTime); - objectId->impl->encode(buffer); -} - -void ObjectImpl::encodeProperties(qpid::framing::Buffer& buffer) const -{ - int propCount = objectClass->getPropertyCount(); - uint8_t bit = 0; - uint8_t mask = 0; - ValuePtr value; - - for (int idx = 0; idx < propCount; idx++) { - const SchemaProperty* prop = objectClass->getProperty(idx); - if (prop->isOptional()) { - value = properties[prop->getName()]; - if (bit == 0) - bit = 1; - if (!value->isNull()) - mask |= bit; - if (bit == 0x80) { - buffer.putOctet(mask); - bit = 0; - mask = 0; - } else - bit = bit << 1; - } - } - if (bit != 0) { - buffer.putOctet(mask); - } - - for (int idx = 0; idx < propCount; idx++) { - const SchemaProperty* prop = objectClass->getProperty(idx); - value = properties[prop->getName()]; - if (!prop->isOptional() || !value->isNull()) { - value->impl->encode(buffer); - } - } -} - -void ObjectImpl::encodeStatistics(qpid::framing::Buffer& buffer) const -{ - int statCount = objectClass->getStatisticCount(); - for (int idx = 0; idx < statCount; idx++) { - const SchemaStatistic* stat = objectClass->getStatistic(idx); - ValuePtr value = statistics[stat->getName()]; - value->impl->encode(buffer); - } -} - -//================================================================== -// Wrappers -//================================================================== - -Object::Object(const SchemaObjectClass* type) : impl(new ObjectImpl(type)) {} -Object::Object(ObjectImpl* i) : impl(i) {} -Object::Object(const Object& from) : impl(new ObjectImpl(*(from.impl))) {} -Object::~Object() { delete impl; } -void Object::destroy() { impl->destroy(); } -const ObjectId* Object::getObjectId() const { return impl->getObjectId(); } -void Object::setObjectId(ObjectId* oid) { impl->setObjectId(oid); } -const SchemaObjectClass* Object::getClass() const { return impl->getClass(); } -Value* Object::getValue(const char* key) const { return impl->getValue(key); } -void Object::invokeMethod(const char* m, const Value* a, void* c) const { impl->invokeMethod(m, a, c); } -bool Object::isDeleted() const { return impl->isDeleted(); } -void Object::merge(const Object& from) { impl->merge(from); } - diff --git a/cpp/src/qmf/engine/ObjectImpl.h b/cpp/src/qmf/engine/ObjectImpl.h deleted file mode 100644 index 6f25867004..0000000000 --- a/cpp/src/qmf/engine/ObjectImpl.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _QmfEngineObjectImpl_ -#define _QmfEngineObjectImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qmf/engine/Object.h> -#include <qmf/engine/ObjectIdImpl.h> -#include <map> -#include <set> -#include <string> -#include <qpid/framing/Buffer.h> -#include <boost/shared_ptr.hpp> -#include <qpid/sys/Mutex.h> - -namespace qmf { -namespace engine { - - class BrokerProxyImpl; - - typedef boost::shared_ptr<Object> ObjectPtr; - - struct ObjectImpl { - typedef boost::shared_ptr<Value> ValuePtr; - const SchemaObjectClass* objectClass; - BrokerProxyImpl* broker; - boost::shared_ptr<ObjectId> objectId; - uint64_t createTime; - uint64_t destroyTime; - uint64_t lastUpdatedTime; - mutable std::map<std::string, ValuePtr> properties; - mutable std::map<std::string, ValuePtr> statistics; - - ObjectImpl(const SchemaObjectClass* type); - ObjectImpl(const SchemaObjectClass* type, BrokerProxyImpl* b, qpid::framing::Buffer& buffer, - bool prop, bool stat, bool managed); - static Object* factory(const SchemaObjectClass* type, BrokerProxyImpl* b, qpid::framing::Buffer& buffer, - bool prop, bool stat, bool managed); - ~ObjectImpl(); - - void destroy(); - const ObjectId* getObjectId() const { return objectId.get(); } - void setObjectId(ObjectId* oid) { objectId.reset(new ObjectId(*oid)); } - const SchemaObjectClass* getClass() const { return objectClass; } - Value* getValue(const std::string& key) const; - void invokeMethod(const std::string& methodName, const Value* inArgs, void* context) const; - bool isDeleted() const { return destroyTime != 0; } - void merge(const Object& from); - - void parsePresenceMasks(qpid::framing::Buffer& buffer, std::set<std::string>& excludeList); - void encodeSchemaKey(qpid::framing::Buffer& buffer) const; - void encodeManagedObjectData(qpid::framing::Buffer& buffer) const; - void encodeProperties(qpid::framing::Buffer& buffer) const; - void encodeStatistics(qpid::framing::Buffer& buffer) const; - }; -} -} - -#endif - diff --git a/cpp/src/qmf/engine/Protocol.cpp b/cpp/src/qmf/engine/Protocol.cpp deleted file mode 100644 index 9e5f490604..0000000000 --- a/cpp/src/qmf/engine/Protocol.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/Protocol.h" -#include "qpid/framing/Buffer.h" - -using namespace std; -using namespace qmf::engine; -using namespace qpid::framing; - - -bool Protocol::checkHeader(Buffer& buf, uint8_t *opcode, uint32_t *seq) -{ - if (buf.available() < 8) - return false; - - uint8_t h1 = buf.getOctet(); - uint8_t h2 = buf.getOctet(); - uint8_t h3 = buf.getOctet(); - - *opcode = buf.getOctet(); - *seq = buf.getLong(); - - return h1 == 'A' && h2 == 'M' && h3 == '2'; -} - -void Protocol::encodeHeader(qpid::framing::Buffer& buf, uint8_t opcode, uint32_t seq) -{ - buf.putOctet('A'); - buf.putOctet('M'); - buf.putOctet('2'); - buf.putOctet(opcode); - buf.putLong (seq); -} - - diff --git a/cpp/src/qmf/engine/Protocol.h b/cpp/src/qmf/engine/Protocol.h deleted file mode 100644 index 1cdfa60c84..0000000000 --- a/cpp/src/qmf/engine/Protocol.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _QmfEngineProtocol_ -#define _QmfEngineProtocol_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/sys/IntegerTypes.h> - -namespace qpid { - namespace framing { - class Buffer; - } -} - -namespace qmf { -namespace engine { - - class Protocol { - public: - static bool checkHeader(qpid::framing::Buffer& buf, uint8_t *opcode, uint32_t *seq); - static void encodeHeader(qpid::framing::Buffer& buf, uint8_t opcode, uint32_t seq = 0); - - const static uint8_t OP_ATTACH_REQUEST = 'A'; - const static uint8_t OP_ATTACH_RESPONSE = 'a'; - - const static uint8_t OP_BROKER_REQUEST = 'B'; - const static uint8_t OP_BROKER_RESPONSE = 'b'; - - const static uint8_t OP_CONSOLE_ADDED_INDICATION = 'x'; - const static uint8_t OP_COMMAND_COMPLETE = 'z'; - const static uint8_t OP_HEARTBEAT_INDICATION = 'h'; - - const static uint8_t OP_PACKAGE_REQUEST = 'P'; - const static uint8_t OP_PACKAGE_INDICATION = 'p'; - const static uint8_t OP_CLASS_QUERY = 'Q'; - const static uint8_t OP_CLASS_INDICATION = 'q'; - const static uint8_t OP_SCHEMA_REQUEST = 'S'; - const static uint8_t OP_SCHEMA_RESPONSE = 's'; - - const static uint8_t OP_METHOD_REQUEST = 'M'; - const static uint8_t OP_METHOD_RESPONSE = 'm'; - const static uint8_t OP_GET_QUERY = 'G'; - const static uint8_t OP_OBJECT_INDICATION = 'g'; - const static uint8_t OP_PROPERTY_INDICATION = 'c'; - const static uint8_t OP_STATISTIC_INDICATION = 'i'; - const static uint8_t OP_EVENT_INDICATION = 'e'; - }; - -} -} - -#endif - diff --git a/cpp/src/qmf/engine/QueryImpl.cpp b/cpp/src/qmf/engine/QueryImpl.cpp deleted file mode 100644 index 6f2beeee87..0000000000 --- a/cpp/src/qmf/engine/QueryImpl.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/QueryImpl.h" -#include "qmf/engine/ObjectIdImpl.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldTable.h" - -using namespace std; -using namespace qmf::engine; -using namespace qpid::framing; - -bool QueryElementImpl::evaluate(const Object* /*object*/) const -{ - // TODO: Implement this - return false; -} - -bool QueryExpressionImpl::evaluate(const Object* /*object*/) const -{ - // TODO: Implement this - return false; -} - -QueryImpl::QueryImpl(Buffer& buffer) -{ - FieldTable ft; - ft.decode(buffer); - // TODO -} - -Query* QueryImpl::factory(Buffer& buffer) -{ - QueryImpl* impl(new QueryImpl(buffer)); - return new Query(impl); -} - -void QueryImpl::encode(Buffer& buffer) const -{ - FieldTable ft; - - if (oid.get() != 0) { - ft.setString("_objectid", oid->impl->asString()); - } else { - if (!packageName.empty()) - ft.setString("_package", packageName); - ft.setString("_class", className); - } - - ft.encode(buffer); -} - - -//================================================================== -// Wrappers -//================================================================== - -QueryElement::QueryElement(const char* attrName, const Value* value, ValueOper oper) : impl(new QueryElementImpl(attrName, value, oper)) {} -QueryElement::QueryElement(QueryElementImpl* i) : impl(i) {} -QueryElement::~QueryElement() { delete impl; } -bool QueryElement::evaluate(const Object* object) const { return impl->evaluate(object); } - -QueryExpression::QueryExpression(ExprOper oper, const QueryOperand* operand1, const QueryOperand* operand2) : impl(new QueryExpressionImpl(oper, operand1, operand2)) {} -QueryExpression::QueryExpression(QueryExpressionImpl* i) : impl(i) {} -QueryExpression::~QueryExpression() { delete impl; } -bool QueryExpression::evaluate(const Object* object) const { return impl->evaluate(object); } - -Query::Query(const char* className, const char* packageName) : impl(new QueryImpl(className, packageName)) {} -Query::Query(const SchemaClassKey* key) : impl(new QueryImpl(key)) {} -Query::Query(const ObjectId* oid) : impl(new QueryImpl(oid)) {} -Query::Query(QueryImpl* i) : impl(i) {} -Query::Query(const Query& from) : impl(new QueryImpl(*(from.impl))) {} -Query::~Query() { delete impl; } -void Query::setSelect(const QueryOperand* criterion) { impl->setSelect(criterion); } -void Query::setLimit(uint32_t maxResults) { impl->setLimit(maxResults); } -void Query::setOrderBy(const char* attrName, bool decreasing) { impl->setOrderBy(attrName, decreasing); } -const char* Query::getPackage() const { return impl->getPackage().c_str(); } -const char* Query::getClass() const { return impl->getClass().c_str(); } -const ObjectId* Query::getObjectId() const { return impl->getObjectId(); } -bool Query::haveSelect() const { return impl->haveSelect(); } -bool Query::haveLimit() const { return impl->haveLimit(); } -bool Query::haveOrderBy() const { return impl->haveOrderBy(); } -const QueryOperand* Query::getSelect() const { return impl->getSelect(); } -uint32_t Query::getLimit() const { return impl->getLimit(); } -const char* Query::getOrderBy() const { return impl->getOrderBy().c_str(); } -bool Query::getDecreasing() const { return impl->getDecreasing(); } - diff --git a/cpp/src/qmf/engine/QueryImpl.h b/cpp/src/qmf/engine/QueryImpl.h deleted file mode 100644 index 8ebe0d932f..0000000000 --- a/cpp/src/qmf/engine/QueryImpl.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef _QmfEngineQueryImpl_ -#define _QmfEngineQueryImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/Query.h" -#include "qmf/engine/Schema.h" -#include <string> -#include <boost/shared_ptr.hpp> - -namespace qpid { - namespace framing { - class Buffer; - } -} - -namespace qmf { -namespace engine { - - struct QueryElementImpl { - QueryElementImpl(const std::string& a, const Value* v, ValueOper o) : attrName(a), value(v), oper(o) {} - ~QueryElementImpl() {} - bool evaluate(const Object* object) const; - - std::string attrName; - const Value* value; - ValueOper oper; - }; - - struct QueryExpressionImpl { - QueryExpressionImpl(ExprOper o, const QueryOperand* operand1, const QueryOperand* operand2) : oper(o), left(operand1), right(operand2) {} - ~QueryExpressionImpl() {} - bool evaluate(const Object* object) const; - - ExprOper oper; - const QueryOperand* left; - const QueryOperand* right; - }; - - struct QueryImpl { - // Constructors mapped to public - QueryImpl(const std::string& c, const std::string& p) : packageName(p), className(c), select(0), resultLimit(0) {} - QueryImpl(const SchemaClassKey* key) : packageName(key->getPackageName()), className(key->getClassName()), select(0), resultLimit(0) {} - QueryImpl(const ObjectId* oid) : oid(new ObjectId(*oid)), select(0), resultLimit(0) {} - - // Factory constructors - QueryImpl(qpid::framing::Buffer& buffer); - - ~QueryImpl() {}; - static Query* factory(qpid::framing::Buffer& buffer); - - void setSelect(const QueryOperand* criterion) { select = criterion; } - void setLimit(uint32_t maxResults) { resultLimit = maxResults; } - void setOrderBy(const std::string& attrName, bool decreasing) { - orderBy = attrName; orderDecreasing = decreasing; - } - - const std::string& getPackage() const { return packageName; } - const std::string& getClass() const { return className; } - const ObjectId* getObjectId() const { return oid.get(); } - - bool haveSelect() const { return select != 0; } - bool haveLimit() const { return resultLimit > 0; } - bool haveOrderBy() const { return !orderBy.empty(); } - const QueryOperand* getSelect() const { return select; } - uint32_t getLimit() const { return resultLimit; } - const std::string& getOrderBy() const { return orderBy; } - bool getDecreasing() const { return orderDecreasing; } - - void encode(qpid::framing::Buffer& buffer) const; - bool singleAgent() const { return oid.get() != 0; } - uint32_t agentBank() const { return singleAgent() ? oid->getAgentBank() : 0; } - - std::string packageName; - std::string className; - boost::shared_ptr<ObjectId> oid; - const QueryOperand* select; - uint32_t resultLimit; - std::string orderBy; - bool orderDecreasing; - }; -} -} - -#endif diff --git a/cpp/src/qmf/engine/ResilientConnection.cpp b/cpp/src/qmf/engine/ResilientConnection.cpp deleted file mode 100644 index ab65b8d768..0000000000 --- a/cpp/src/qmf/engine/ResilientConnection.cpp +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/ResilientConnection.h" -#include "qmf/engine/MessageImpl.h" -#include "qmf/engine/ConnectionSettingsImpl.h" -#include <qpid/client/Connection.h> -#include <qpid/client/Session.h> -#include <qpid/client/MessageListener.h> -#include <qpid/client/SubscriptionManager.h> -#include <qpid/client/Message.h> -#include <qpid/sys/Thread.h> -#include <qpid/sys/Runnable.h> -#include <qpid/sys/Mutex.h> -#include <qpid/sys/Condition.h> -#include <qpid/sys/Time.h> -#include <qpid/log/Statement.h> -#include <qpid/RefCounted.h> -#include <boost/bind.hpp> -#include <string> -#include <deque> -#include <vector> -#include <set> -#include <boost/intrusive_ptr.hpp> -#include <boost/noncopyable.hpp> -#include <unistd.h> -#include <fcntl.h> - -using namespace std; -using namespace qmf::engine; -using namespace qpid; -using qpid::sys::Mutex; - -namespace qmf { -namespace engine { - struct ResilientConnectionEventImpl { - ResilientConnectionEvent::EventKind kind; - void* sessionContext; - string errorText; - MessageImpl message; - - ResilientConnectionEventImpl(ResilientConnectionEvent::EventKind k, - const MessageImpl& m = MessageImpl()) : - kind(k), sessionContext(0), message(m) {} - ResilientConnectionEvent copy(); - }; - - struct RCSession : public client::MessageListener, public qpid::sys::Runnable, public qpid::RefCounted { - typedef boost::intrusive_ptr<RCSession> Ptr; - ResilientConnectionImpl& connImpl; - string name; - client::Connection& connection; - client::Session session; - client::SubscriptionManager* subscriptions; - string userId; - void* userContext; - vector<string> dests; - qpid::sys::Thread thread; - - RCSession(ResilientConnectionImpl& ci, const string& n, client::Connection& c, void* uc); - ~RCSession(); - void received(client::Message& msg); - void run(); - void stop(); - }; - - class ResilientConnectionImpl : public qpid::sys::Runnable, public boost::noncopyable { - public: - ResilientConnectionImpl(const ConnectionSettings& settings); - ~ResilientConnectionImpl(); - - bool isConnected() const; - bool getEvent(ResilientConnectionEvent& event); - void popEvent(); - bool createSession(const char* name, void* sessionContext, SessionHandle& handle); - void destroySession(SessionHandle handle); - void sendMessage(SessionHandle handle, qmf::engine::Message& message); - void declareQueue(SessionHandle handle, char* queue); - void deleteQueue(SessionHandle handle, char* queue); - void bind(SessionHandle handle, char* exchange, char* queue, char* key); - void unbind(SessionHandle handle, char* exchange, char* queue, char* key); - void setNotifyFd(int fd); - void notify(); - - void run(); - void failure(); - void sessionClosed(RCSession* sess); - - void EnqueueEvent(ResilientConnectionEvent::EventKind kind, - void* sessionContext = 0, - const MessageImpl& message = MessageImpl(), - const string& errorText = ""); - - private: - int notifyFd; - bool connected; - bool shutdown; - string lastError; - const ConnectionSettings settings; - client::Connection connection; - mutable qpid::sys::Mutex lock; - int delayMin; - int delayMax; - int delayFactor; - qpid::sys::Condition cond; - deque<ResilientConnectionEventImpl> eventQueue; - set<RCSession::Ptr> sessions; - qpid::sys::Thread connThread; - }; -} -} - -ResilientConnectionEvent ResilientConnectionEventImpl::copy() -{ - ResilientConnectionEvent item; - - ::memset(&item, 0, sizeof(ResilientConnectionEvent)); - item.kind = kind; - item.sessionContext = sessionContext; - item.message = message.copy(); - item.errorText = const_cast<char*>(errorText.c_str()); - - return item; -} - -RCSession::RCSession(ResilientConnectionImpl& ci, const string& n, client::Connection& c, void* uc) : - connImpl(ci), name(n), connection(c), session(connection.newSession(name)), - subscriptions(new client::SubscriptionManager(session)), userContext(uc), thread(*this) -{ - const qpid::client::ConnectionSettings& operSettings = connection.getNegotiatedSettings(); - userId = operSettings.username; -} - -RCSession::~RCSession() -{ - subscriptions->stop(); - thread.join(); - session.close(); - delete subscriptions; -} - -void RCSession::run() -{ - try { - subscriptions->run(); - } catch (exception& /*e*/) { - connImpl.sessionClosed(this); - } -} - -void RCSession::stop() -{ - subscriptions->stop(); -} - -void RCSession::received(client::Message& msg) -{ - MessageImpl qmsg; - qmsg.body = msg.getData(); - - qpid::framing::DeliveryProperties dp = msg.getDeliveryProperties(); - if (dp.hasRoutingKey()) { - qmsg.routingKey = dp.getRoutingKey(); - } - - qpid::framing::MessageProperties mp = msg.getMessageProperties(); - if (mp.hasReplyTo()) { - const qpid::framing::ReplyTo& rt = mp.getReplyTo(); - qmsg.replyExchange = rt.getExchange(); - qmsg.replyKey = rt.getRoutingKey(); - } - - if (mp.hasUserId()) { - qmsg.userId = mp.getUserId(); - } - - connImpl.EnqueueEvent(ResilientConnectionEvent::RECV, userContext, qmsg); -} - -ResilientConnectionImpl::ResilientConnectionImpl(const ConnectionSettings& _settings) : - notifyFd(-1), connected(false), shutdown(false), settings(_settings), delayMin(1), connThread(*this) -{ - connection.registerFailureCallback(boost::bind(&ResilientConnectionImpl::failure, this)); - settings.impl->getRetrySettings(&delayMin, &delayMax, &delayFactor); -} - -ResilientConnectionImpl::~ResilientConnectionImpl() -{ - shutdown = true; - connected = false; - cond.notify(); - connThread.join(); - connection.close(); -} - -bool ResilientConnectionImpl::isConnected() const -{ - Mutex::ScopedLock _lock(lock); - return connected; -} - -bool ResilientConnectionImpl::getEvent(ResilientConnectionEvent& event) -{ - Mutex::ScopedLock _lock(lock); - if (eventQueue.empty()) - return false; - event = eventQueue.front().copy(); - return true; -} - -void ResilientConnectionImpl::popEvent() -{ - Mutex::ScopedLock _lock(lock); - if (!eventQueue.empty()) - eventQueue.pop_front(); -} - -bool ResilientConnectionImpl::createSession(const char* name, void* sessionContext, - SessionHandle& handle) -{ - Mutex::ScopedLock _lock(lock); - if (!connected) - return false; - - RCSession::Ptr sess = RCSession::Ptr(new RCSession(*this, name, connection, sessionContext)); - - handle.impl = (void*) sess.get(); - sessions.insert(sess); - - return true; -} - -void ResilientConnectionImpl::destroySession(SessionHandle handle) -{ - Mutex::ScopedLock _lock(lock); - RCSession::Ptr sess = RCSession::Ptr((RCSession*) handle.impl); - set<RCSession::Ptr>::iterator iter = sessions.find(sess); - if (iter != sessions.end()) { - for (vector<string>::iterator dIter = sess->dests.begin(); dIter != sess->dests.end(); dIter++) - sess->subscriptions->cancel(dIter->c_str()); - sess->subscriptions->stop(); - sess->subscriptions->wait(); - - sessions.erase(iter); - return; - } -} - -void ResilientConnectionImpl::sendMessage(SessionHandle handle, qmf::engine::Message& message) -{ - Mutex::ScopedLock _lock(lock); - RCSession::Ptr sess = RCSession::Ptr((RCSession*) handle.impl); - set<RCSession::Ptr>::iterator iter = sessions.find(sess); - qpid::client::Message msg; - string data(message.body, message.length); - msg.getDeliveryProperties().setRoutingKey(message.routingKey); - msg.getMessageProperties().setReplyTo(qpid::framing::ReplyTo(message.replyExchange, message.replyKey)); - if (settings.impl->getSendUserId()) - msg.getMessageProperties().setUserId(sess->userId); - msg.setData(data); - - try { - sess->session.messageTransfer(client::arg::content=msg, client::arg::destination=message.destination); - } catch(exception& e) { - QPID_LOG(error, "Session Exception during message-transfer: " << e.what()); - sessions.erase(iter); - EnqueueEvent(ResilientConnectionEvent::SESSION_CLOSED, (*iter)->userContext); - } -} - -void ResilientConnectionImpl::declareQueue(SessionHandle handle, char* queue) -{ - Mutex::ScopedLock _lock(lock); - RCSession* sess = (RCSession*) handle.impl; - - sess->session.queueDeclare(client::arg::queue=queue, client::arg::autoDelete=true, client::arg::exclusive=true); - sess->subscriptions->setAcceptMode(client::ACCEPT_MODE_NONE); - sess->subscriptions->setAcquireMode(client::ACQUIRE_MODE_PRE_ACQUIRED); - sess->subscriptions->subscribe(*sess, queue, queue); - sess->subscriptions->setFlowControl(queue, client::FlowControl::unlimited()); - sess->dests.push_back(string(queue)); -} - -void ResilientConnectionImpl::deleteQueue(SessionHandle handle, char* queue) -{ - Mutex::ScopedLock _lock(lock); - RCSession* sess = (RCSession*) handle.impl; - - sess->session.queueDelete(client::arg::queue=queue); - for (vector<string>::iterator iter = sess->dests.begin(); - iter != sess->dests.end(); iter++) - if (*iter == queue) { - sess->subscriptions->cancel(queue); - sess->dests.erase(iter); - break; - } -} - -void ResilientConnectionImpl::bind(SessionHandle handle, - char* exchange, char* queue, char* key) -{ - Mutex::ScopedLock _lock(lock); - RCSession* sess = (RCSession*) handle.impl; - - sess->session.exchangeBind(client::arg::exchange=exchange, client::arg::queue=queue, client::arg::bindingKey=key); -} - -void ResilientConnectionImpl::unbind(SessionHandle handle, - char* exchange, char* queue, char* key) -{ - Mutex::ScopedLock _lock(lock); - RCSession* sess = (RCSession*) handle.impl; - - sess->session.exchangeUnbind(client::arg::exchange=exchange, client::arg::queue=queue, client::arg::bindingKey=key); -} - -void ResilientConnectionImpl::notify() -{ - if (notifyFd != -1) - { - int unused_ret; //Suppress warnings about ignoring return value. - unused_ret = ::write(notifyFd, ".", 1); - } -} - - -void ResilientConnectionImpl::setNotifyFd(int fd) -{ - notifyFd = fd; - if (notifyFd > 0) { - int original = fcntl(notifyFd, F_GETFL); - fcntl(notifyFd, F_SETFL, O_NONBLOCK | original); - } -} - -void ResilientConnectionImpl::run() -{ - int delay(delayMin); - - while (true) { - try { - QPID_LOG(trace, "Trying to open connection..."); - connection.open(settings.impl->getClientSettings()); - { - Mutex::ScopedLock _lock(lock); - connected = true; - EnqueueEvent(ResilientConnectionEvent::CONNECTED); - - while (connected) - cond.wait(lock); - delay = delayMin; - - while (!sessions.empty()) { - set<RCSession::Ptr>::iterator iter = sessions.begin(); - RCSession::Ptr sess = *iter; - sessions.erase(iter); - EnqueueEvent(ResilientConnectionEvent::SESSION_CLOSED, sess->userContext); - Mutex::ScopedUnlock _u(lock); - sess->stop(); - - // Nullify the intrusive pointer within the scoped unlock, otherwise, - // the reference is held until overwritted above (under lock) which causes - // the session destructor to be called with the lock held. - sess = 0; - } - - EnqueueEvent(ResilientConnectionEvent::DISCONNECTED); - - if (shutdown) - return; - } - connection.close(); - } catch (exception &e) { - QPID_LOG(debug, "connection.open exception: " << e.what()); - Mutex::ScopedLock _lock(lock); - lastError = e.what(); - if (delay < delayMax) - delay *= delayFactor; - } - - ::qpid::sys::sleep(delay); - } -} - -void ResilientConnectionImpl::failure() -{ - Mutex::ScopedLock _lock(lock); - - connected = false; - lastError = "Closed by Peer"; - cond.notify(); -} - -void ResilientConnectionImpl::sessionClosed(RCSession*) -{ - Mutex::ScopedLock _lock(lock); - connected = false; - lastError = "Closed due to Session failure"; - cond.notify(); -} - -void ResilientConnectionImpl::EnqueueEvent(ResilientConnectionEvent::EventKind kind, - void* sessionContext, - const MessageImpl& message, - const string& errorText) -{ - { - Mutex::ScopedLock _lock(lock); - ResilientConnectionEventImpl event(kind, message); - - event.sessionContext = sessionContext; - event.errorText = errorText; - - eventQueue.push_back(event); - } - - if (notifyFd != -1) - { - int unused_ret; //Suppress warnings about ignoring return value. - unused_ret = ::write(notifyFd, ".", 1); - } -} - - -//================================================================== -// Wrappers -//================================================================== - -ResilientConnection::ResilientConnection(const ConnectionSettings& settings) -{ - impl = new ResilientConnectionImpl(settings); -} - -ResilientConnection::~ResilientConnection() -{ - delete impl; -} - -bool ResilientConnection::isConnected() const -{ - return impl->isConnected(); -} - -bool ResilientConnection::getEvent(ResilientConnectionEvent& event) -{ - return impl->getEvent(event); -} - -void ResilientConnection::popEvent() -{ - impl->popEvent(); -} - -bool ResilientConnection::createSession(const char* name, void* sessionContext, SessionHandle& handle) -{ - return impl->createSession(name, sessionContext, handle); -} - -void ResilientConnection::destroySession(SessionHandle handle) -{ - impl->destroySession(handle); -} - -void ResilientConnection::sendMessage(SessionHandle handle, qmf::engine::Message& message) -{ - impl->sendMessage(handle, message); -} - -void ResilientConnection::declareQueue(SessionHandle handle, char* queue) -{ - impl->declareQueue(handle, queue); -} - -void ResilientConnection::deleteQueue(SessionHandle handle, char* queue) -{ - impl->deleteQueue(handle, queue); -} - -void ResilientConnection::bind(SessionHandle handle, char* exchange, char* queue, char* key) -{ - impl->bind(handle, exchange, queue, key); -} - -void ResilientConnection::unbind(SessionHandle handle, char* exchange, char* queue, char* key) -{ - impl->unbind(handle, exchange, queue, key); -} - -void ResilientConnection::setNotifyFd(int fd) -{ - impl->setNotifyFd(fd); -} - -void ResilientConnection::notify() -{ - impl->notify(); -} - diff --git a/cpp/src/qmf/engine/SchemaImpl.cpp b/cpp/src/qmf/engine/SchemaImpl.cpp deleted file mode 100644 index f75663e131..0000000000 --- a/cpp/src/qmf/engine/SchemaImpl.cpp +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/SchemaImpl.h" -#include <qpid/framing/Buffer.h> -#include <qpid/framing/FieldTable.h> -#include <qpid/framing/Uuid.h> -#include <string.h> -#include <string> -#include <vector> -#include <sstream> - -using namespace std; -using namespace qmf::engine; -using qpid::framing::Buffer; -using qpid::framing::FieldTable; -using qpid::framing::Uuid; - -SchemaHash::SchemaHash() -{ - for (int idx = 0; idx < 16; idx++) - hash[idx] = 0x5A; -} - -void SchemaHash::encode(Buffer& buffer) const -{ - buffer.putBin128(hash); -} - -void SchemaHash::decode(Buffer& buffer) -{ - buffer.getBin128(hash); -} - -void SchemaHash::update(uint8_t data) -{ - update((char*) &data, 1); -} - -void SchemaHash::update(const char* data, uint32_t len) -{ - union h { - uint8_t b[16]; - uint64_t q[2]; - }* h = reinterpret_cast<union h*>(&hash[0]); - uint64_t* first = &h->q[0]; - uint64_t* second = &h->q[1]; - for (uint32_t idx = 0; idx < len; idx++) { - *first = *first ^ (uint64_t) data[idx]; - *second = *second << 1; - *second |= ((*first & 0x8000000000000000LL) >> 63); - *first = *first << 1; - *first = *first ^ *second; - } -} - -bool SchemaHash::operator==(const SchemaHash& other) const -{ - return ::memcmp(&hash, &other.hash, 16) == 0; -} - -bool SchemaHash::operator<(const SchemaHash& other) const -{ - return ::memcmp(&hash, &other.hash, 16) < 0; -} - -bool SchemaHash::operator>(const SchemaHash& other) const -{ - return ::memcmp(&hash, &other.hash, 16) > 0; -} - -SchemaArgumentImpl::SchemaArgumentImpl(Buffer& buffer) -{ - FieldTable map; - map.decode(buffer); - - name = map.getAsString("name"); - typecode = (Typecode) map.getAsInt("type"); - unit = map.getAsString("unit"); - description = map.getAsString("desc"); - - dir = DIR_IN; - string dstr(map.getAsString("dir")); - if (dstr == "O") - dir = DIR_OUT; - else if (dstr == "IO") - dir = DIR_IN_OUT; -} - -SchemaArgument* SchemaArgumentImpl::factory(Buffer& buffer) -{ - SchemaArgumentImpl* impl(new SchemaArgumentImpl(buffer)); - return new SchemaArgument(impl); -} - -void SchemaArgumentImpl::encode(Buffer& buffer) const -{ - FieldTable map; - - map.setString("name", name); - map.setInt("type", (int) typecode); - if (dir == DIR_IN) - map.setString("dir", "I"); - else if (dir == DIR_OUT) - map.setString("dir", "O"); - else - map.setString("dir", "IO"); - if (!unit.empty()) - map.setString("unit", unit); - if (!description.empty()) - map.setString("desc", description); - - map.encode(buffer); -} - -void SchemaArgumentImpl::updateHash(SchemaHash& hash) const -{ - hash.update(name); - hash.update(typecode); - hash.update(dir); - hash.update(unit); - hash.update(description); -} - -SchemaMethodImpl::SchemaMethodImpl(Buffer& buffer) -{ - FieldTable map; - int argCount; - - map.decode(buffer); - name = map.getAsString("name"); - argCount = map.getAsInt("argCount"); - description = map.getAsString("desc"); - - for (int idx = 0; idx < argCount; idx++) { - SchemaArgument* arg = SchemaArgumentImpl::factory(buffer); - addArgument(arg); - } -} - -SchemaMethod* SchemaMethodImpl::factory(Buffer& buffer) -{ - SchemaMethodImpl* impl(new SchemaMethodImpl(buffer)); - return new SchemaMethod(impl); -} - -void SchemaMethodImpl::encode(Buffer& buffer) const -{ - FieldTable map; - - map.setString("name", name); - map.setInt("argCount", arguments.size()); - if (!description.empty()) - map.setString("desc", description); - map.encode(buffer); - - for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin(); - iter != arguments.end(); iter++) - (*iter)->impl->encode(buffer); -} - -void SchemaMethodImpl::addArgument(const SchemaArgument* argument) -{ - arguments.push_back(argument); -} - -const SchemaArgument* SchemaMethodImpl::getArgument(int idx) const -{ - int count = 0; - for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin(); - iter != arguments.end(); iter++, count++) - if (idx == count) - return (*iter); - return 0; -} - -void SchemaMethodImpl::updateHash(SchemaHash& hash) const -{ - hash.update(name); - hash.update(description); - for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin(); - iter != arguments.end(); iter++) - (*iter)->impl->updateHash(hash); -} - -SchemaPropertyImpl::SchemaPropertyImpl(Buffer& buffer) -{ - FieldTable map; - map.decode(buffer); - - name = map.getAsString("name"); - typecode = (Typecode) map.getAsInt("type"); - access = (Access) map.getAsInt("access"); - index = map.getAsInt("index") != 0; - optional = map.getAsInt("optional") != 0; - unit = map.getAsString("unit"); - description = map.getAsString("desc"); -} - -SchemaProperty* SchemaPropertyImpl::factory(Buffer& buffer) -{ - SchemaPropertyImpl* impl(new SchemaPropertyImpl(buffer)); - return new SchemaProperty(impl); -} - -void SchemaPropertyImpl::encode(Buffer& buffer) const -{ - FieldTable map; - - map.setString("name", name); - map.setInt("type", (int) typecode); - map.setInt("access", (int) access); - map.setInt("index", index ? 1 : 0); - map.setInt("optional", optional ? 1 : 0); - if (!unit.empty()) - map.setString("unit", unit); - if (!description.empty()) - map.setString("desc", description); - - map.encode(buffer); -} - -void SchemaPropertyImpl::updateHash(SchemaHash& hash) const -{ - hash.update(name); - hash.update(typecode); - hash.update(access); - hash.update(index); - hash.update(optional); - hash.update(unit); - hash.update(description); -} - -SchemaStatisticImpl::SchemaStatisticImpl(Buffer& buffer) -{ - FieldTable map; - map.decode(buffer); - - name = map.getAsString("name"); - typecode = (Typecode) map.getAsInt("type"); - unit = map.getAsString("unit"); - description = map.getAsString("desc"); -} - -SchemaStatistic* SchemaStatisticImpl::factory(Buffer& buffer) -{ - SchemaStatisticImpl* impl(new SchemaStatisticImpl(buffer)); - return new SchemaStatistic(impl); -} - -void SchemaStatisticImpl::encode(Buffer& buffer) const -{ - FieldTable map; - - map.setString("name", name); - map.setInt("type", (int) typecode); - if (!unit.empty()) - map.setString("unit", unit); - if (!description.empty()) - map.setString("desc", description); - - map.encode(buffer); -} - -void SchemaStatisticImpl::updateHash(SchemaHash& hash) const -{ - hash.update(name); - hash.update(typecode); - hash.update(unit); - hash.update(description); -} - -SchemaClassKeyImpl::SchemaClassKeyImpl(const string& p, const string& n, const SchemaHash& h) : package(p), name(n), hash(h) {} - -SchemaClassKeyImpl::SchemaClassKeyImpl(Buffer& buffer) : package(packageContainer), name(nameContainer), hash(hashContainer) -{ - buffer.getShortString(packageContainer); - buffer.getShortString(nameContainer); - hashContainer.decode(buffer); -} - -SchemaClassKey* SchemaClassKeyImpl::factory(const string& package, const string& name, const SchemaHash& hash) -{ - SchemaClassKeyImpl* impl(new SchemaClassKeyImpl(package, name, hash)); - return new SchemaClassKey(impl); -} - -SchemaClassKey* SchemaClassKeyImpl::factory(Buffer& buffer) -{ - SchemaClassKeyImpl* impl(new SchemaClassKeyImpl(buffer)); - return new SchemaClassKey(impl); -} - -void SchemaClassKeyImpl::encode(Buffer& buffer) const -{ - buffer.putShortString(package); - buffer.putShortString(name); - hash.encode(buffer); -} - -bool SchemaClassKeyImpl::operator==(const SchemaClassKeyImpl& other) const -{ - return package == other.package && - name == other.name && - hash == other.hash; -} - -bool SchemaClassKeyImpl::operator<(const SchemaClassKeyImpl& other) const -{ - if (package < other.package) return true; - if (package > other.package) return false; - if (name < other.name) return true; - if (name > other.name) return false; - return hash < other.hash; -} - -const string& SchemaClassKeyImpl::str() const -{ - Uuid printableHash(hash.get()); - stringstream str; - str << package << ":" << name << "(" << printableHash << ")"; - repr = str.str(); - return repr; -} - -SchemaObjectClassImpl::SchemaObjectClassImpl(Buffer& buffer) : hasHash(true), classKey(SchemaClassKeyImpl::factory(package, name, hash)) -{ - buffer.getShortString(package); - buffer.getShortString(name); - hash.decode(buffer); - - uint16_t propCount = buffer.getShort(); - uint16_t statCount = buffer.getShort(); - uint16_t methodCount = buffer.getShort(); - - for (uint16_t idx = 0; idx < propCount; idx++) { - const SchemaProperty* property = SchemaPropertyImpl::factory(buffer); - addProperty(property); - } - - for (uint16_t idx = 0; idx < statCount; idx++) { - const SchemaStatistic* statistic = SchemaStatisticImpl::factory(buffer); - addStatistic(statistic); - } - - for (uint16_t idx = 0; idx < methodCount; idx++) { - SchemaMethod* method = SchemaMethodImpl::factory(buffer); - addMethod(method); - } -} - -SchemaObjectClass* SchemaObjectClassImpl::factory(Buffer& buffer) -{ - SchemaObjectClassImpl* impl(new SchemaObjectClassImpl(buffer)); - return new SchemaObjectClass(impl); -} - -void SchemaObjectClassImpl::encode(Buffer& buffer) const -{ - buffer.putOctet((uint8_t) CLASS_OBJECT); - buffer.putShortString(package); - buffer.putShortString(name); - hash.encode(buffer); - //buffer.putOctet(0); // No parent class - buffer.putShort((uint16_t) properties.size()); - buffer.putShort((uint16_t) statistics.size()); - buffer.putShort((uint16_t) methods.size()); - - for (vector<const SchemaProperty*>::const_iterator iter = properties.begin(); - iter != properties.end(); iter++) - (*iter)->impl->encode(buffer); - for (vector<const SchemaStatistic*>::const_iterator iter = statistics.begin(); - iter != statistics.end(); iter++) - (*iter)->impl->encode(buffer); - for (vector<const SchemaMethod*>::const_iterator iter = methods.begin(); - iter != methods.end(); iter++) - (*iter)->impl->encode(buffer); -} - -const SchemaClassKey* SchemaObjectClassImpl::getClassKey() const -{ - if (!hasHash) { - hasHash = true; - hash.update(package); - hash.update(name); - for (vector<const SchemaProperty*>::const_iterator iter = properties.begin(); - iter != properties.end(); iter++) - (*iter)->impl->updateHash(hash); - for (vector<const SchemaStatistic*>::const_iterator iter = statistics.begin(); - iter != statistics.end(); iter++) - (*iter)->impl->updateHash(hash); - for (vector<const SchemaMethod*>::const_iterator iter = methods.begin(); - iter != methods.end(); iter++) - (*iter)->impl->updateHash(hash); - } - - return classKey.get(); -} - -void SchemaObjectClassImpl::addProperty(const SchemaProperty* property) -{ - properties.push_back(property); -} - -void SchemaObjectClassImpl::addStatistic(const SchemaStatistic* statistic) -{ - statistics.push_back(statistic); -} - -void SchemaObjectClassImpl::addMethod(const SchemaMethod* method) -{ - methods.push_back(method); -} - -const SchemaProperty* SchemaObjectClassImpl::getProperty(int idx) const -{ - int count = 0; - for (vector<const SchemaProperty*>::const_iterator iter = properties.begin(); - iter != properties.end(); iter++, count++) - if (idx == count) - return *iter; - return 0; -} - -const SchemaStatistic* SchemaObjectClassImpl::getStatistic(int idx) const -{ - int count = 0; - for (vector<const SchemaStatistic*>::const_iterator iter = statistics.begin(); - iter != statistics.end(); iter++, count++) - if (idx == count) - return *iter; - return 0; -} - -const SchemaMethod* SchemaObjectClassImpl::getMethod(int idx) const -{ - int count = 0; - for (vector<const SchemaMethod*>::const_iterator iter = methods.begin(); - iter != methods.end(); iter++, count++) - if (idx == count) - return *iter; - return 0; -} - -SchemaEventClassImpl::SchemaEventClassImpl(Buffer& buffer) : hasHash(true), classKey(SchemaClassKeyImpl::factory(package, name, hash)) -{ - buffer.getShortString(package); - buffer.getShortString(name); - hash.decode(buffer); - - uint16_t argCount = buffer.getShort(); - - for (uint16_t idx = 0; idx < argCount; idx++) { - SchemaArgument* argument = SchemaArgumentImpl::factory(buffer); - addArgument(argument); - } -} - -SchemaEventClass* SchemaEventClassImpl::factory(Buffer& buffer) -{ - SchemaEventClassImpl* impl(new SchemaEventClassImpl(buffer)); - return new SchemaEventClass(impl); -} - -void SchemaEventClassImpl::encode(Buffer& buffer) const -{ - buffer.putOctet((uint8_t) CLASS_EVENT); - buffer.putShortString(package); - buffer.putShortString(name); - hash.encode(buffer); - buffer.putShort((uint16_t) arguments.size()); - - for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin(); - iter != arguments.end(); iter++) - (*iter)->impl->encode(buffer); -} - -const SchemaClassKey* SchemaEventClassImpl::getClassKey() const -{ - if (!hasHash) { - hasHash = true; - hash.update(package); - hash.update(name); - for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin(); - iter != arguments.end(); iter++) - (*iter)->impl->updateHash(hash); - } - return classKey.get(); -} - -void SchemaEventClassImpl::addArgument(const SchemaArgument* argument) -{ - arguments.push_back(argument); -} - -const SchemaArgument* SchemaEventClassImpl::getArgument(int idx) const -{ - int count = 0; - for (vector<const SchemaArgument*>::const_iterator iter = arguments.begin(); - iter != arguments.end(); iter++, count++) - if (idx == count) - return (*iter); - return 0; -} - - -//================================================================== -// Wrappers -//================================================================== - -SchemaArgument::SchemaArgument(const char* name, Typecode typecode) { impl = new SchemaArgumentImpl(name, typecode); } -SchemaArgument::SchemaArgument(SchemaArgumentImpl* i) : impl(i) {} -SchemaArgument::SchemaArgument(const SchemaArgument& from) : impl(new SchemaArgumentImpl(*(from.impl))) {} -SchemaArgument::~SchemaArgument() { delete impl; } -void SchemaArgument::setDirection(Direction dir) { impl->setDirection(dir); } -void SchemaArgument::setUnit(const char* val) { impl->setUnit(val); } -void SchemaArgument::setDesc(const char* desc) { impl->setDesc(desc); } -const char* SchemaArgument::getName() const { return impl->getName().c_str(); } -Typecode SchemaArgument::getType() const { return impl->getType(); } -Direction SchemaArgument::getDirection() const { return impl->getDirection(); } -const char* SchemaArgument::getUnit() const { return impl->getUnit().c_str(); } -const char* SchemaArgument::getDesc() const { return impl->getDesc().c_str(); } - -SchemaMethod::SchemaMethod(const char* name) : impl(new SchemaMethodImpl(name)) {} -SchemaMethod::SchemaMethod(SchemaMethodImpl* i) : impl(i) {} -SchemaMethod::SchemaMethod(const SchemaMethod& from) : impl(new SchemaMethodImpl(*(from.impl))) {} -SchemaMethod::~SchemaMethod() { delete impl; } -void SchemaMethod::addArgument(const SchemaArgument* argument) { impl->addArgument(argument); } -void SchemaMethod::setDesc(const char* desc) { impl->setDesc(desc); } -const char* SchemaMethod::getName() const { return impl->getName().c_str(); } -const char* SchemaMethod::getDesc() const { return impl->getDesc().c_str(); } -int SchemaMethod::getArgumentCount() const { return impl->getArgumentCount(); } -const SchemaArgument* SchemaMethod::getArgument(int idx) const { return impl->getArgument(idx); } - -SchemaProperty::SchemaProperty(const char* name, Typecode typecode) : impl(new SchemaPropertyImpl(name, typecode)) {} -SchemaProperty::SchemaProperty(SchemaPropertyImpl* i) : impl(i) {} -SchemaProperty::SchemaProperty(const SchemaProperty& from) : impl(new SchemaPropertyImpl(*(from.impl))) {} -SchemaProperty::~SchemaProperty() { delete impl; } -void SchemaProperty::setAccess(Access access) { impl->setAccess(access); } -void SchemaProperty::setIndex(bool val) { impl->setIndex(val); } -void SchemaProperty::setOptional(bool val) { impl->setOptional(val); } -void SchemaProperty::setUnit(const char* val) { impl->setUnit(val); } -void SchemaProperty::setDesc(const char* desc) { impl->setDesc(desc); } -const char* SchemaProperty::getName() const { return impl->getName().c_str(); } -Typecode SchemaProperty::getType() const { return impl->getType(); } -Access SchemaProperty::getAccess() const { return impl->getAccess(); } -bool SchemaProperty::isIndex() const { return impl->isIndex(); } -bool SchemaProperty::isOptional() const { return impl->isOptional(); } -const char* SchemaProperty::getUnit() const { return impl->getUnit().c_str(); } -const char* SchemaProperty::getDesc() const { return impl->getDesc().c_str(); } - -SchemaStatistic::SchemaStatistic(const char* name, Typecode typecode) : impl(new SchemaStatisticImpl(name, typecode)) {} -SchemaStatistic::SchemaStatistic(SchemaStatisticImpl* i) : impl(i) {} -SchemaStatistic::SchemaStatistic(const SchemaStatistic& from) : impl(new SchemaStatisticImpl(*(from.impl))) {} -SchemaStatistic::~SchemaStatistic() { delete impl; } -void SchemaStatistic::setUnit(const char* val) { impl->setUnit(val); } -void SchemaStatistic::setDesc(const char* desc) { impl->setDesc(desc); } -const char* SchemaStatistic::getName() const { return impl->getName().c_str(); } -Typecode SchemaStatistic::getType() const { return impl->getType(); } -const char* SchemaStatistic::getUnit() const { return impl->getUnit().c_str(); } -const char* SchemaStatistic::getDesc() const { return impl->getDesc().c_str(); } - -SchemaClassKey::SchemaClassKey(SchemaClassKeyImpl* i) : impl(i) {} -SchemaClassKey::SchemaClassKey(const SchemaClassKey& from) : impl(new SchemaClassKeyImpl(*(from.impl))) {} -SchemaClassKey::~SchemaClassKey() { delete impl; } -const char* SchemaClassKey::getPackageName() const { return impl->getPackageName().c_str(); } -const char* SchemaClassKey::getClassName() const { return impl->getClassName().c_str(); } -const uint8_t* SchemaClassKey::getHash() const { return impl->getHash(); } -const char* SchemaClassKey::asString() const { return impl->str().c_str(); } -bool SchemaClassKey::operator==(const SchemaClassKey& other) const { return *impl == *(other.impl); } -bool SchemaClassKey::operator<(const SchemaClassKey& other) const { return *impl < *(other.impl); } - -SchemaObjectClass::SchemaObjectClass(const char* package, const char* name) : impl(new SchemaObjectClassImpl(package, name)) {} -SchemaObjectClass::SchemaObjectClass(SchemaObjectClassImpl* i) : impl(i) {} -SchemaObjectClass::SchemaObjectClass(const SchemaObjectClass& from) : impl(new SchemaObjectClassImpl(*(from.impl))) {} -SchemaObjectClass::~SchemaObjectClass() { delete impl; } -void SchemaObjectClass::addProperty(const SchemaProperty* property) { impl->addProperty(property); } -void SchemaObjectClass::addStatistic(const SchemaStatistic* statistic) { impl->addStatistic(statistic); } -void SchemaObjectClass::addMethod(const SchemaMethod* method) { impl->addMethod(method); } -const SchemaClassKey* SchemaObjectClass::getClassKey() const { return impl->getClassKey(); } -int SchemaObjectClass::getPropertyCount() const { return impl->getPropertyCount(); } -int SchemaObjectClass::getStatisticCount() const { return impl->getStatisticCount(); } -int SchemaObjectClass::getMethodCount() const { return impl->getMethodCount(); } -const SchemaProperty* SchemaObjectClass::getProperty(int idx) const { return impl->getProperty(idx); } -const SchemaStatistic* SchemaObjectClass::getStatistic(int idx) const { return impl->getStatistic(idx); } -const SchemaMethod* SchemaObjectClass::getMethod(int idx) const { return impl->getMethod(idx); } - -SchemaEventClass::SchemaEventClass(const char* package, const char* name, Severity s) : impl(new SchemaEventClassImpl(package, name, s)) {} -SchemaEventClass::SchemaEventClass(SchemaEventClassImpl* i) : impl(i) {} -SchemaEventClass::SchemaEventClass(const SchemaEventClass& from) : impl(new SchemaEventClassImpl(*(from.impl))) {} -SchemaEventClass::~SchemaEventClass() { delete impl; } -void SchemaEventClass::addArgument(const SchemaArgument* argument) { impl->addArgument(argument); } -void SchemaEventClass::setDesc(const char* desc) { impl->setDesc(desc); } -const SchemaClassKey* SchemaEventClass::getClassKey() const { return impl->getClassKey(); } -Severity SchemaEventClass::getSeverity() const { return impl->getSeverity(); } -int SchemaEventClass::getArgumentCount() const { return impl->getArgumentCount(); } -const SchemaArgument* SchemaEventClass::getArgument(int idx) const { return impl->getArgument(idx); } - diff --git a/cpp/src/qmf/engine/SchemaImpl.h b/cpp/src/qmf/engine/SchemaImpl.h deleted file mode 100644 index 8b079a5ec6..0000000000 --- a/cpp/src/qmf/engine/SchemaImpl.h +++ /dev/null @@ -1,227 +0,0 @@ -#ifndef _QmfEngineSchemaImpl_ -#define _QmfEngineSchemaImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/Schema.h" -#include "qpid/framing/Buffer.h" - -#include <string> -#include <vector> -#include <memory> - -namespace qmf { -namespace engine { - - // TODO: Destructors for schema classes - // TODO: Add "frozen" attribute for schema classes so they can't be modified after - // they've been registered. - - class SchemaHash { - uint8_t hash[16]; - public: - SchemaHash(); - void encode(qpid::framing::Buffer& buffer) const; - void decode(qpid::framing::Buffer& buffer); - void update(const char* data, uint32_t len); - void update(uint8_t data); - void update(const std::string& data) { update(data.c_str(), data.size()); } - void update(Typecode t) { update((uint8_t) t); } - void update(Direction d) { update((uint8_t) d); } - void update(Access a) { update((uint8_t) a); } - void update(bool b) { update((uint8_t) (b ? 1 : 0)); } - const uint8_t* get() const { return hash; } - bool operator==(const SchemaHash& other) const; - bool operator<(const SchemaHash& other) const; - bool operator>(const SchemaHash& other) const; - }; - - struct SchemaArgumentImpl { - std::string name; - Typecode typecode; - Direction dir; - std::string unit; - std::string description; - - SchemaArgumentImpl(const char* n, Typecode t) : name(n), typecode(t), dir(DIR_IN) {} - SchemaArgumentImpl(qpid::framing::Buffer& buffer); - static SchemaArgument* factory(qpid::framing::Buffer& buffer); - void encode(qpid::framing::Buffer& buffer) const; - void setDirection(Direction d) { dir = d; } - void setUnit(const char* val) { unit = val; } - void setDesc(const char* desc) { description = desc; } - const std::string& getName() const { return name; } - Typecode getType() const { return typecode; } - Direction getDirection() const { return dir; } - const std::string& getUnit() const { return unit; } - const std::string& getDesc() const { return description; } - void updateHash(SchemaHash& hash) const; - }; - - struct SchemaMethodImpl { - std::string name; - std::string description; - std::vector<const SchemaArgument*> arguments; - - SchemaMethodImpl(const char* n) : name(n) {} - SchemaMethodImpl(qpid::framing::Buffer& buffer); - static SchemaMethod* factory(qpid::framing::Buffer& buffer); - void encode(qpid::framing::Buffer& buffer) const; - void addArgument(const SchemaArgument* argument); - void setDesc(const char* desc) { description = desc; } - const std::string& getName() const { return name; } - const std::string& getDesc() const { return description; } - int getArgumentCount() const { return arguments.size(); } - const SchemaArgument* getArgument(int idx) const; - void updateHash(SchemaHash& hash) const; - }; - - struct SchemaPropertyImpl { - std::string name; - Typecode typecode; - Access access; - bool index; - bool optional; - std::string unit; - std::string description; - - SchemaPropertyImpl(const char* n, Typecode t) : name(n), typecode(t), access(ACCESS_READ_ONLY), index(false), optional(false) {} - SchemaPropertyImpl(qpid::framing::Buffer& buffer); - static SchemaProperty* factory(qpid::framing::Buffer& buffer); - void encode(qpid::framing::Buffer& buffer) const; - void setAccess(Access a) { access = a; } - void setIndex(bool val) { index = val; } - void setOptional(bool val) { optional = val; } - void setUnit(const char* val) { unit = val; } - void setDesc(const char* desc) { description = desc; } - const std::string& getName() const { return name; } - Typecode getType() const { return typecode; } - Access getAccess() const { return access; } - bool isIndex() const { return index; } - bool isOptional() const { return optional; } - const std::string& getUnit() const { return unit; } - const std::string& getDesc() const { return description; } - void updateHash(SchemaHash& hash) const; - }; - - struct SchemaStatisticImpl { - std::string name; - Typecode typecode; - std::string unit; - std::string description; - - SchemaStatisticImpl(const char* n, Typecode t) : name(n), typecode(t) {} - SchemaStatisticImpl(qpid::framing::Buffer& buffer); - static SchemaStatistic* factory(qpid::framing::Buffer& buffer); - void encode(qpid::framing::Buffer& buffer) const; - void setUnit(const char* val) { unit = val; } - void setDesc(const char* desc) { description = desc; } - const std::string& getName() const { return name; } - Typecode getType() const { return typecode; } - const std::string& getUnit() const { return unit; } - const std::string& getDesc() const { return description; } - void updateHash(SchemaHash& hash) const; - }; - - struct SchemaClassKeyImpl { - const std::string& package; - const std::string& name; - const SchemaHash& hash; - mutable std::string repr; - - // The *Container elements are only used if there isn't an external place to - // store these values. - std::string packageContainer; - std::string nameContainer; - SchemaHash hashContainer; - - SchemaClassKeyImpl(const std::string& package, const std::string& name, const SchemaHash& hash); - SchemaClassKeyImpl(qpid::framing::Buffer& buffer); - static SchemaClassKey* factory(const std::string& package, const std::string& name, const SchemaHash& hash); - static SchemaClassKey* factory(qpid::framing::Buffer& buffer); - - const std::string& getPackageName() const { return package; } - const std::string& getClassName() const { return name; } - const uint8_t* getHash() const { return hash.get(); } - - void encode(qpid::framing::Buffer& buffer) const; - bool operator==(const SchemaClassKeyImpl& other) const; - bool operator<(const SchemaClassKeyImpl& other) const; - const std::string& str() const; - }; - - struct SchemaObjectClassImpl { - std::string package; - std::string name; - mutable SchemaHash hash; - mutable bool hasHash; - std::auto_ptr<SchemaClassKey> classKey; - std::vector<const SchemaProperty*> properties; - std::vector<const SchemaStatistic*> statistics; - std::vector<const SchemaMethod*> methods; - - SchemaObjectClassImpl(const char* p, const char* n) : - package(p), name(n), hasHash(false), classKey(SchemaClassKeyImpl::factory(package, name, hash)) {} - SchemaObjectClassImpl(qpid::framing::Buffer& buffer); - static SchemaObjectClass* factory(qpid::framing::Buffer& buffer); - - void encode(qpid::framing::Buffer& buffer) const; - void addProperty(const SchemaProperty* property); - void addStatistic(const SchemaStatistic* statistic); - void addMethod(const SchemaMethod* method); - - const SchemaClassKey* getClassKey() const; - int getPropertyCount() const { return properties.size(); } - int getStatisticCount() const { return statistics.size(); } - int getMethodCount() const { return methods.size(); } - const SchemaProperty* getProperty(int idx) const; - const SchemaStatistic* getStatistic(int idx) const; - const SchemaMethod* getMethod(int idx) const; - }; - - struct SchemaEventClassImpl { - std::string package; - std::string name; - mutable SchemaHash hash; - mutable bool hasHash; - std::auto_ptr<SchemaClassKey> classKey; - std::string description; - Severity severity; - std::vector<const SchemaArgument*> arguments; - - SchemaEventClassImpl(const char* p, const char* n, Severity sev) : - package(p), name(n), hasHash(false), classKey(SchemaClassKeyImpl::factory(package, name, hash)), severity(sev) {} - SchemaEventClassImpl(qpid::framing::Buffer& buffer); - static SchemaEventClass* factory(qpid::framing::Buffer& buffer); - - void encode(qpid::framing::Buffer& buffer) const; - void addArgument(const SchemaArgument* argument); - void setDesc(const char* desc) { description = desc; } - - const SchemaClassKey* getClassKey() const; - Severity getSeverity() const { return severity; } - int getArgumentCount() const { return arguments.size(); } - const SchemaArgument* getArgument(int idx) const; - }; -} -} - -#endif - diff --git a/cpp/src/qmf/engine/SequenceManager.cpp b/cpp/src/qmf/engine/SequenceManager.cpp deleted file mode 100644 index 4a4644a8b9..0000000000 --- a/cpp/src/qmf/engine/SequenceManager.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/SequenceManager.h" - -using namespace std; -using namespace qmf::engine; -using namespace qpid::sys; - -SequenceManager::SequenceManager() : nextSequence(1) {} - -void SequenceManager::setUnsolicitedContext(SequenceContext::Ptr ctx) -{ - unsolicitedContext = ctx; -} - -uint32_t SequenceManager::reserve(SequenceContext::Ptr ctx) -{ - Mutex::ScopedLock _lock(lock); - if (ctx.get() == 0) - ctx = unsolicitedContext; - uint32_t seq = nextSequence; - while (contextMap.find(seq) != contextMap.end()) - seq = seq < 0xFFFFFFFF ? seq + 1 : 1; - nextSequence = seq < 0xFFFFFFFF ? seq + 1 : 1; - contextMap[seq] = ctx; - ctx->reserve(); - return seq; -} - -void SequenceManager::release(uint32_t sequence) -{ - Mutex::ScopedLock _lock(lock); - - if (sequence == 0) { - if (unsolicitedContext.get() != 0) - unsolicitedContext->release(); - return; - } - - map<uint32_t, SequenceContext::Ptr>::iterator iter = contextMap.find(sequence); - if (iter != contextMap.end()) { - if (iter->second != 0) - iter->second->release(); - contextMap.erase(iter); - } -} - -void SequenceManager::releaseAll() -{ - Mutex::ScopedLock _lock(lock); - contextMap.clear(); -} - -void SequenceManager::dispatch(uint8_t opcode, uint32_t sequence, const string& routingKey, qpid::framing::Buffer& buffer) -{ - Mutex::ScopedLock _lock(lock); - bool done; - - if (sequence == 0) { - if (unsolicitedContext.get() != 0) { - done = unsolicitedContext->handleMessage(opcode, sequence, routingKey, buffer); - if (done) - unsolicitedContext->release(); - } - return; - } - - map<uint32_t, SequenceContext::Ptr>::iterator iter = contextMap.find(sequence); - if (iter != contextMap.end()) { - if (iter->second != 0) { - done = iter->second->handleMessage(opcode, sequence, routingKey, buffer); - if (done) { - iter->second->release(); - contextMap.erase(iter); - } - } - } -} - diff --git a/cpp/src/qmf/engine/SequenceManager.h b/cpp/src/qmf/engine/SequenceManager.h deleted file mode 100644 index 9e47e38610..0000000000 --- a/cpp/src/qmf/engine/SequenceManager.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef _QmfEngineSequenceManager_ -#define _QmfEngineSequenceManager_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qpid/sys/Mutex.h" -#include <boost/shared_ptr.hpp> -#include <map> - -namespace qpid { - namespace framing { - class Buffer; - } -} - -namespace qmf { -namespace engine { - - class SequenceContext { - public: - typedef boost::shared_ptr<SequenceContext> Ptr; - SequenceContext() {} - virtual ~SequenceContext() {} - - virtual void reserve() = 0; - virtual bool handleMessage(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer) = 0; - virtual void release() = 0; - }; - - class SequenceManager { - public: - SequenceManager(); - - void setUnsolicitedContext(SequenceContext::Ptr ctx); - uint32_t reserve(SequenceContext::Ptr ctx = SequenceContext::Ptr()); - void release(uint32_t sequence); - void releaseAll(); - void dispatch(uint8_t opcode, uint32_t sequence, const std::string& routingKey, qpid::framing::Buffer& buffer); - - private: - mutable qpid::sys::Mutex lock; - uint32_t nextSequence; - SequenceContext::Ptr unsolicitedContext; - std::map<uint32_t, SequenceContext::Ptr> contextMap; - }; - -} -} - -#endif - diff --git a/cpp/src/qmf/engine/ValueImpl.cpp b/cpp/src/qmf/engine/ValueImpl.cpp deleted file mode 100644 index f9ebbf5028..0000000000 --- a/cpp/src/qmf/engine/ValueImpl.cpp +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qmf/engine/ValueImpl.h" -#include <qpid/framing/FieldValue.h> -#include <qpid/framing/FieldTable.h> -#include <qpid/framing/List.h> -#include <qpid/log/Statement.h> - -using namespace std; -using namespace qmf::engine; -//using qpid::framing::Buffer; -//using qpid::framing::FieldTable; -//using qpid::framing::FieldValue; -using namespace qpid::framing; - -ValueImpl::ValueImpl(Typecode t, Buffer& buf) : typecode(t) -{ - uint64_t first; - uint64_t second; - FieldTable ft; - List fl; - - switch (typecode) { - case TYPE_UINT8 : value.u32 = (uint32_t) buf.getOctet(); break; - case TYPE_UINT16 : value.u32 = (uint32_t) buf.getShort(); break; - case TYPE_UINT32 : value.u32 = (uint32_t) buf.getLong(); break; - case TYPE_UINT64 : value.u64 = buf.getLongLong(); break; - case TYPE_SSTR : buf.getShortString(stringVal); break; - case TYPE_LSTR : buf.getMediumString(stringVal); break; - case TYPE_ABSTIME : value.s64 = buf.getLongLong(); break; - case TYPE_DELTATIME : value.u64 = buf.getLongLong(); break; - case TYPE_BOOL : value.boolVal = (buf.getOctet() != 0); break; - case TYPE_FLOAT : value.floatVal = buf.getFloat(); break; - case TYPE_DOUBLE : value.doubleVal = buf.getDouble(); break; - case TYPE_INT8 : value.s32 = (int32_t) ((int8_t) buf.getOctet()); break; - case TYPE_INT16 : value.s32 = (int32_t) ((int16_t) buf.getShort()); break; - case TYPE_INT32 : value.s32 = (int32_t) buf.getLong(); break; - case TYPE_INT64 : value.s64 = buf.getLongLong(); break; - case TYPE_UUID : buf.getBin128(value.uuidVal); break; - case TYPE_REF: - first = buf.getLongLong(); - second = buf.getLongLong(); - refVal.impl->setValue(first, second); - break; - - case TYPE_MAP: - ft.decode(buf); - initMap(ft); - break; - - case TYPE_LIST: - fl.decode(buf); - initList(fl); - break; - - case TYPE_ARRAY: - case TYPE_OBJECT: - default: - break; - } -} - -ValueImpl::ValueImpl(Typecode t, Typecode at) : typecode(t), valid(false), arrayTypecode(at) -{ -} - -ValueImpl::ValueImpl(Typecode t) : typecode(t) -{ - ::memset(&value, 0, sizeof(value)); -} - -Value* ValueImpl::factory(Typecode t, Buffer& b) -{ - ValueImpl* impl(new ValueImpl(t, b)); - return new Value(impl); -} - -Value* ValueImpl::factory(Typecode t) -{ - ValueImpl* impl(new ValueImpl(t)); - return new Value(impl); -} - -ValueImpl::~ValueImpl() -{ -} - -void ValueImpl::initMap(const FieldTable& ft) -{ - for (FieldTable::ValueMap::const_iterator iter = ft.begin(); - iter != ft.end(); iter++) { - const string& name(iter->first); - const FieldValue& fvalue(*iter->second); - uint8_t amqType = fvalue.getType(); - - if (amqType == 0x32) { - Value* subval(new Value(TYPE_UINT64)); - subval->setUint64(fvalue.get<int64_t>()); - insert(name.c_str(), subval); - } else if ((amqType & 0xCF) == 0x02) { - Value* subval(new Value(TYPE_UINT32)); - switch (amqType) { - case 0x02 : subval->setUint(fvalue.get<int>()); break; - case 0x12 : subval->setUint(fvalue.get<int>()); break; - case 0x22 : subval->setUint(fvalue.get<int>()); break; - } - insert(name.c_str(), subval); - } else if (amqType == 0x31) { // int64 - Value* subval(new Value(TYPE_INT64)); - subval->setInt64(fvalue.get<int64_t>()); - insert(name.c_str(), subval); - } else if ((amqType & 0xCF) == 0x01) { // 0x01:int8, 0x11:int16, 0x21:int21 - Value* subval(new Value(TYPE_INT32)); - subval->setInt((int32_t)fvalue.get<int>()); - insert(name.c_str(), subval); - } else if (amqType == 0x85 || amqType == 0x95) { - Value* subval(new Value(TYPE_LSTR)); - subval->setString(fvalue.get<string>().c_str()); - insert(name.c_str(), subval); - } else if (amqType == 0x23 || amqType == 0x33) { - Value* subval(new Value(TYPE_DOUBLE)); - subval->setDouble(fvalue.get<double>()); - insert(name.c_str(), subval); - } else if (amqType == 0xa8) { - FieldTable subFt; - bool valid = qpid::framing::getEncodedValue<FieldTable>(iter->second, subFt); - if (valid) { - Value* subval(new Value(TYPE_MAP)); - subval->impl->initMap(subFt); - insert(name.c_str(), subval); - } - } else if (amqType == 0xa9) { - List subList; - bool valid = qpid::framing::getEncodedValue<List>(iter->second, subList); - if (valid) { - Value* subval(new Value(TYPE_LIST)); - subval->impl->initList(subList); - insert(name.c_str(), subval); - } - } else if (amqType == 0x08) { - Value* subval(new Value(TYPE_BOOL)); - subval->setBool(fvalue.get<int>() ? true : false); - insert(name.c_str(), subval); - } else { - QPID_LOG(error, "Unable to decode unsupported AMQP typecode=" << amqType << " map index=" << name); - } - } -} - -void ValueImpl::mapToFieldTable(FieldTable& ft) const -{ - FieldTable subFt; - - for (map<string, Value>::const_iterator iter = mapVal.begin(); - iter != mapVal.end(); iter++) { - const string& name(iter->first); - const Value& subval(iter->second); - - switch (subval.getType()) { - case TYPE_UINT8: - case TYPE_UINT16: - case TYPE_UINT32: - ft.setUInt64(name, (uint64_t) subval.asUint()); - break; - case TYPE_UINT64: - case TYPE_DELTATIME: - ft.setUInt64(name, subval.asUint64()); - break; - case TYPE_SSTR: - case TYPE_LSTR: - ft.setString(name, subval.asString()); - break; - case TYPE_INT64: - case TYPE_ABSTIME: - ft.setInt64(name, subval.asInt64()); - break; - case TYPE_BOOL: - ft.set(name, FieldTable::ValuePtr(new BoolValue(subval.asBool()))); - break; - case TYPE_FLOAT: - ft.setFloat(name, subval.asFloat()); - break; - case TYPE_DOUBLE: - ft.setDouble(name, subval.asDouble()); - break; - case TYPE_INT8: - case TYPE_INT16: - case TYPE_INT32: - ft.setInt(name, subval.asInt()); - break; - case TYPE_MAP: - subFt.clear(); - subval.impl->mapToFieldTable(subFt); - ft.setTable(name, subFt); - break; - case TYPE_LIST: - { - List subList; - subval.impl->listToFramingList(subList); - ft.set(name, - ::qpid::framing::FieldTable::ValuePtr( - new ListValue( - subList))); - } break; - case TYPE_ARRAY: - case TYPE_OBJECT: - case TYPE_UUID: - case TYPE_REF: - default: - break; - } - } - } - - -void ValueImpl::initList(const List& fl) -{ - for (List::const_iterator iter = fl.begin(); - iter != fl.end(); iter++) { - const FieldValue& fvalue(*iter->get()); - uint8_t amqType = fvalue.getType(); - - if (amqType == 0x32) { - Value* subval(new Value(TYPE_UINT64)); - subval->setUint64(fvalue.get<int64_t>()); - appendToList(subval); - } else if ((amqType & 0xCF) == 0x02) { - Value* subval(new Value(TYPE_UINT32)); - switch (amqType) { - case 0x02 : subval->setUint(fvalue.get<int>()); break; // uint8 - case 0x12 : subval->setUint(fvalue.get<int>()); break; // uint16 - case 0x22 : subval->setUint(fvalue.get<int>()); break; // uint32 - } - appendToList(subval); - } else if (amqType == 0x31) { // int64 - Value* subval(new Value(TYPE_INT64)); - subval->setInt64(fvalue.get<int64_t>()); - appendToList(subval); - } else if ((amqType & 0xCF) == 0x01) { // 0x01:int8, 0x11:int16, 0x21:int32 - Value* subval(new Value(TYPE_INT32)); - subval->setInt((int32_t)fvalue.get<int>()); - appendToList(subval); - } else if (amqType == 0x85 || amqType == 0x95) { - Value* subval(new Value(TYPE_LSTR)); - subval->setString(fvalue.get<string>().c_str()); - appendToList(subval); - } else if (amqType == 0x23 || amqType == 0x33) { - Value* subval(new Value(TYPE_DOUBLE)); - subval->setDouble(fvalue.get<double>()); - appendToList(subval); - } else if (amqType == 0xa8) { - FieldTable subFt; - bool valid = qpid::framing::getEncodedValue<FieldTable>(*iter, subFt); - if (valid) { - Value* subval(new Value(TYPE_MAP)); - subval->impl->initMap(subFt); - appendToList(subval); - } - } else if (amqType == 0xa9) { - List subList; - bool valid = qpid::framing::getEncodedValue<List>(*iter, subList); - if (valid) { - Value *subVal(new Value(TYPE_LIST)); - subVal->impl->initList(subList); - appendToList(subVal); - } - } else if (amqType == 0x08) { - Value* subval(new Value(TYPE_BOOL)); - subval->setBool(fvalue.get<int>() ? true : false); - appendToList(subval); - } else { - QPID_LOG(error, "Unable to decode unsupported AMQP typecode =" << amqType); - } - } -} - -void ValueImpl::listToFramingList(List& fl) const -{ - for (vector<Value>::const_iterator iter = vectorVal.begin(); - iter != vectorVal.end(); iter++) { - const Value& subval(*iter); - - switch (subval.getType()) { - case TYPE_UINT8: - case TYPE_UINT16: - case TYPE_UINT32: - fl.push_back(List::ValuePtr(new Unsigned64Value((uint64_t) subval.asUint()))); - break; - case TYPE_UINT64: - case TYPE_DELTATIME: - fl.push_back(List::ValuePtr(new Unsigned64Value(subval.asUint64()))); - break; - case TYPE_SSTR: - case TYPE_LSTR: - fl.push_back(List::ValuePtr(new Str16Value(subval.asString()))); - break; - case TYPE_INT64: - case TYPE_ABSTIME: - fl.push_back(List::ValuePtr(new Integer64Value(subval.asInt64()))); - break; - case TYPE_BOOL: - fl.push_back(List::ValuePtr(new BoolValue(subval.asBool() ? 1 : 0))); - break; - case TYPE_FLOAT: - fl.push_back(List::ValuePtr(new FloatValue(subval.asFloat()))); - break; - case TYPE_DOUBLE: - fl.push_back(List::ValuePtr(new DoubleValue(subval.asDouble()))); - break; - case TYPE_INT8: - case TYPE_INT16: - case TYPE_INT32: - fl.push_back(List::ValuePtr(new IntegerValue(subval.asInt()))); - break; - case TYPE_MAP: - { - FieldTable subFt; - subval.impl->mapToFieldTable(subFt); - fl.push_back(List::ValuePtr(new FieldTableValue(subFt))); - - } break; - case TYPE_LIST: - { - List subList; - subval.impl->listToFramingList(subList); - fl.push_back(List::ValuePtr(new ListValue(subList))); - } break; - - case TYPE_ARRAY: - case TYPE_OBJECT: - case TYPE_UUID: - case TYPE_REF: - default: - break; - } - } - } - - - -void ValueImpl::encode(Buffer& buf) const -{ - FieldTable ft; - List fl; - - switch (typecode) { - case TYPE_UINT8 : buf.putOctet((uint8_t) value.u32); break; - case TYPE_UINT16 : buf.putShort((uint16_t) value.u32); break; - case TYPE_UINT32 : buf.putLong(value.u32); break; - case TYPE_UINT64 : buf.putLongLong(value.u64); break; - case TYPE_SSTR : buf.putShortString(stringVal); break; - case TYPE_LSTR : buf.putMediumString(stringVal); break; - case TYPE_ABSTIME : buf.putLongLong(value.s64); break; - case TYPE_DELTATIME : buf.putLongLong(value.u64); break; - case TYPE_BOOL : buf.putOctet(value.boolVal ? 1 : 0); break; - case TYPE_FLOAT : buf.putFloat(value.floatVal); break; - case TYPE_DOUBLE : buf.putDouble(value.doubleVal); break; - case TYPE_INT8 : buf.putOctet((uint8_t) value.s32); break; - case TYPE_INT16 : buf.putShort((uint16_t) value.s32); break; - case TYPE_INT32 : buf.putLong(value.s32); break; - case TYPE_INT64 : buf.putLongLong(value.s64); break; - case TYPE_UUID : buf.putBin128(value.uuidVal); break; - case TYPE_REF : refVal.impl->encode(buf); break; - case TYPE_MAP: - mapToFieldTable(ft); - ft.encode(buf); - break; - case TYPE_LIST: - listToFramingList(fl); - fl.encode(buf); - break; - - case TYPE_ARRAY: - case TYPE_OBJECT: - default: - break; - } -} - -uint32_t ValueImpl::encodedSize() const -{ - FieldTable ft; - List fl; - - switch (typecode) { - case TYPE_UINT8 : - case TYPE_BOOL : - case TYPE_INT8 : return 1; - - case TYPE_UINT16 : - case TYPE_INT16 : return 2; - - case TYPE_UINT32 : - case TYPE_INT32 : - case TYPE_FLOAT : return 4; - - case TYPE_UINT64 : - case TYPE_INT64 : - case TYPE_DOUBLE : - case TYPE_ABSTIME : - case TYPE_DELTATIME : return 8; - - case TYPE_UUID : - case TYPE_REF : return 16; - - case TYPE_SSTR : return 1 + stringVal.size(); - case TYPE_LSTR : return 2 + stringVal.size(); - case TYPE_MAP: - mapToFieldTable(ft); - return ft.encodedSize(); - - case TYPE_LIST: - listToFramingList(fl); - return fl.encodedSize(); - - case TYPE_ARRAY: - case TYPE_OBJECT: - default: - break; - } - - return 0; -} - -bool ValueImpl::keyInMap(const char* key) const -{ - return typecode == TYPE_MAP && mapVal.count(key) > 0; -} - -Value* ValueImpl::byKey(const char* key) -{ - if (keyInMap(key)) { - map<string, Value>::iterator iter = mapVal.find(key); - if (iter != mapVal.end()) - return &iter->second; - } - return 0; -} - -const Value* ValueImpl::byKey(const char* key) const -{ - if (keyInMap(key)) { - map<string, Value>::const_iterator iter = mapVal.find(key); - if (iter != mapVal.end()) - return &iter->second; - } - return 0; -} - -void ValueImpl::deleteKey(const char* key) -{ - mapVal.erase(key); -} - -void ValueImpl::insert(const char* key, Value* val) -{ - pair<string, Value> entry(key, *val); - mapVal.insert(entry); -} - -const char* ValueImpl::key(uint32_t idx) const -{ - map<string, Value>::const_iterator iter = mapVal.begin(); - for (uint32_t i = 0; i < idx; i++) { - if (iter == mapVal.end()) - break; - iter++; - } - - if (iter == mapVal.end()) - return 0; - else - return iter->first.c_str(); -} - -Value* ValueImpl::arrayItem(uint32_t) -{ - return 0; -} - -void ValueImpl::appendToArray(Value*) -{ -} - -void ValueImpl::deleteArrayItem(uint32_t) -{ -} - - -//================================================================== -// Wrappers -//================================================================== - -Value::Value(const Value& from) : impl(new ValueImpl(*(from.impl))) {} -Value::Value(Typecode t, Typecode at) : impl(new ValueImpl(t, at)) {} -Value::Value(ValueImpl* i) : impl(i) {} -Value::~Value() { delete impl;} - -Typecode Value::getType() const { return impl->getType(); } -bool Value::isNull() const { return impl->isNull(); } -void Value::setNull() { impl->setNull(); } -bool Value::isObjectId() const { return impl->isObjectId(); } -const ObjectId& Value::asObjectId() const { return impl->asObjectId(); } -void Value::setObjectId(const ObjectId& oid) { impl->setObjectId(oid); } -bool Value::isUint() const { return impl->isUint(); } -uint32_t Value::asUint() const { return impl->asUint(); } -void Value::setUint(uint32_t val) { impl->setUint(val); } -bool Value::isInt() const { return impl->isInt(); } -int32_t Value::asInt() const { return impl->asInt(); } -void Value::setInt(int32_t val) { impl->setInt(val); } -bool Value::isUint64() const { return impl->isUint64(); } -uint64_t Value::asUint64() const { return impl->asUint64(); } -void Value::setUint64(uint64_t val) { impl->setUint64(val); } -bool Value::isInt64() const { return impl->isInt64(); } -int64_t Value::asInt64() const { return impl->asInt64(); } -void Value::setInt64(int64_t val) { impl->setInt64(val); } -bool Value::isString() const { return impl->isString(); } -const char* Value::asString() const { return impl->asString(); } -void Value::setString(const char* val) { impl->setString(val); } -bool Value::isBool() const { return impl->isBool(); } -bool Value::asBool() const { return impl->asBool(); } -void Value::setBool(bool val) { impl->setBool(val); } -bool Value::isFloat() const { return impl->isFloat(); } -float Value::asFloat() const { return impl->asFloat(); } -void Value::setFloat(float val) { impl->setFloat(val); } -bool Value::isDouble() const { return impl->isDouble(); } -double Value::asDouble() const { return impl->asDouble(); } -void Value::setDouble(double val) { impl->setDouble(val); } -bool Value::isUuid() const { return impl->isUuid(); } -const uint8_t* Value::asUuid() const { return impl->asUuid(); } -void Value::setUuid(const uint8_t* val) { impl->setUuid(val); } -bool Value::isObject() const { return impl->isObject(); } -const Object* Value::asObject() const { return impl->asObject(); } -void Value::setObject(Object* val) { impl->setObject(val); } -bool Value::isMap() const { return impl->isMap(); } -bool Value::keyInMap(const char* key) const { return impl->keyInMap(key); } -Value* Value::byKey(const char* key) { return impl->byKey(key); } -const Value* Value::byKey(const char* key) const { return impl->byKey(key); } -void Value::deleteKey(const char* key) { impl->deleteKey(key); } -void Value::insert(const char* key, Value* val) { impl->insert(key, val); } -uint32_t Value::keyCount() const { return impl->keyCount(); } -const char* Value::key(uint32_t idx) const { return impl->key(idx); } -bool Value::isList() const { return impl->isList(); } -uint32_t Value::listItemCount() const { return impl->listItemCount(); } -Value* Value::listItem(uint32_t idx) { return impl->listItem(idx); } -void Value::appendToList(Value* val) { impl->appendToList(val); } -void Value::deleteListItem(uint32_t idx) { impl->deleteListItem(idx); } -bool Value::isArray() const { return impl->isArray(); } -Typecode Value::arrayType() const { return impl->arrayType(); } -uint32_t Value::arrayItemCount() const { return impl->arrayItemCount(); } -Value* Value::arrayItem(uint32_t idx) { return impl->arrayItem(idx); } -void Value::appendToArray(Value* val) { impl->appendToArray(val); } -void Value::deleteArrayItem(uint32_t idx) { impl->deleteArrayItem(idx); } - diff --git a/cpp/src/qmf/engine/ValueImpl.h b/cpp/src/qmf/engine/ValueImpl.h deleted file mode 100644 index 8de8c5329f..0000000000 --- a/cpp/src/qmf/engine/ValueImpl.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef _QmfEngineValueImpl_ -#define _QmfEngineValueImpl_ - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qmf/engine/Value.h> -#include <qmf/engine/ObjectIdImpl.h> -#include <qmf/engine/Object.h> -#include <qpid/framing/Buffer.h> -#include <string> -#include <string.h> -#include <map> -#include <vector> -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace framing { - class FieldTable; - class List; -} -} - -namespace qmf { -namespace engine { - - // TODO: set valid flag on all value settors - // TODO: add a modified flag and accessors - - struct ValueImpl { - const Typecode typecode; - bool valid; - - ObjectId refVal; - std::string stringVal; - std::auto_ptr<Object> objectVal; - std::map<std::string, Value> mapVal; - std::vector<Value> vectorVal; - Typecode arrayTypecode; - - union { - uint32_t u32; - uint64_t u64; - int32_t s32; - int64_t s64; - bool boolVal; - float floatVal; - double doubleVal; - uint8_t uuidVal[16]; - } value; - - ValueImpl(const ValueImpl& from) : - typecode(from.typecode), valid(from.valid), refVal(from.refVal), stringVal(from.stringVal), - objectVal(from.objectVal.get() ? new Object(*(from.objectVal)) : 0), - mapVal(from.mapVal), vectorVal(from.vectorVal), arrayTypecode(from.arrayTypecode), - value(from.value) {} - - ValueImpl(Typecode t, Typecode at); - ValueImpl(Typecode t, qpid::framing::Buffer& b); - ValueImpl(Typecode t); - static Value* factory(Typecode t, qpid::framing::Buffer& b); - static Value* factory(Typecode t); - ~ValueImpl(); - - void encode(qpid::framing::Buffer& b) const; - uint32_t encodedSize() const; - - Typecode getType() const { return typecode; } - bool isNull() const { return !valid; } - void setNull() { valid = false; } - - bool isObjectId() const { return typecode == TYPE_REF; } - const ObjectId& asObjectId() const { return refVal; } - void setObjectId(const ObjectId& o) { refVal = o; } // TODO - - bool isUint() const { return typecode >= TYPE_UINT8 && typecode <= TYPE_UINT32; } - uint32_t asUint() const { return value.u32; } - void setUint(uint32_t val) { value.u32 = val; } - - bool isInt() const { return typecode >= TYPE_INT8 && typecode <= TYPE_INT32; } - int32_t asInt() const { return value.s32; } - void setInt(int32_t val) { value.s32 = val; } - - bool isUint64() const { return typecode == TYPE_UINT64 || typecode == TYPE_DELTATIME; } - uint64_t asUint64() const { return value.u64; } - void setUint64(uint64_t val) { value.u64 = val; } - - bool isInt64() const { return typecode == TYPE_INT64 || typecode == TYPE_ABSTIME; } - int64_t asInt64() const { return value.s64; } - void setInt64(int64_t val) { value.s64 = val; } - - bool isString() const { return typecode == TYPE_SSTR || typecode == TYPE_LSTR; } - const char* asString() const { return stringVal.c_str(); } - void setString(const char* val) { stringVal = val; } - - bool isBool() const { return typecode == TYPE_BOOL; } - bool asBool() const { return value.boolVal; } - void setBool(bool val) { value.boolVal = val; } - - bool isFloat() const { return typecode == TYPE_FLOAT; } - float asFloat() const { return value.floatVal; } - void setFloat(float val) { value.floatVal = val; } - - bool isDouble() const { return typecode == TYPE_DOUBLE; } - double asDouble() const { return value.doubleVal; } - void setDouble(double val) { value.doubleVal = val; } - - bool isUuid() const { return typecode == TYPE_UUID; } - const uint8_t* asUuid() const { return value.uuidVal; } - void setUuid(const uint8_t* val) { ::memcpy(value.uuidVal, val, 16); } - - bool isObject() const { return typecode == TYPE_OBJECT; } - Object* asObject() const { return objectVal.get(); } - void setObject(Object* val) { objectVal.reset(val); } - - bool isMap() const { return typecode == TYPE_MAP; } - bool keyInMap(const char* key) const; - Value* byKey(const char* key); - const Value* byKey(const char* key) const; - void deleteKey(const char* key); - void insert(const char* key, Value* val); - uint32_t keyCount() const { return mapVal.size(); } - const char* key(uint32_t idx) const; - - bool isList() const { return typecode == TYPE_LIST; } - uint32_t listItemCount() const { return vectorVal.size(); } - Value* listItem(uint32_t idx) { return idx < listItemCount() ? &vectorVal[idx] : 0; } - const Value* listItem(uint32_t idx) const { return idx < listItemCount() ? &vectorVal[idx] : 0; } - void appendToList(Value* val) { vectorVal.push_back(*val); } - void deleteListItem(uint32_t idx) { if (idx < listItemCount()) vectorVal.erase(vectorVal.begin()+idx); } - - bool isArray() const { return typecode == TYPE_ARRAY; } - Typecode arrayType() const { return arrayTypecode; } - uint32_t arrayItemCount() const { return 0; } - Value* arrayItem(uint32_t idx); - void appendToArray(Value* val); - void deleteArrayItem(uint32_t idx); - - private: - void mapToFieldTable(qpid::framing::FieldTable& ft) const; - void initMap(const qpid::framing::FieldTable& ft); - - void listToFramingList(qpid::framing::List& fl) const; - void initList(const qpid::framing::List& fl); - }; -} -} - -#endif - diff --git a/cpp/src/qmf/exceptions.cpp b/cpp/src/qmf/exceptions.cpp deleted file mode 100644 index be212f62f7..0000000000 --- a/cpp/src/qmf/exceptions.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qmf/exceptions.h" - -namespace qmf { - - QmfException::QmfException(const std::string& msg) : qpid::types::Exception(msg) {} - QmfException::~QmfException() throw() {} - - KeyNotFound::KeyNotFound(const std::string& msg) : QmfException("Key Not Found: " + msg) {} - KeyNotFound::~KeyNotFound() throw() {} - - IndexOutOfRange::IndexOutOfRange() : QmfException("Index out-of-range") {} - IndexOutOfRange::~IndexOutOfRange() throw() {} - - OperationTimedOut::OperationTimedOut() : QmfException("Timeout Expired") {} - OperationTimedOut::~OperationTimedOut() throw() {} -} - diff --git a/cpp/src/qmfc.mk b/cpp/src/qmfc.mk deleted file mode 100644 index e445a538a1..0000000000 --- a/cpp/src/qmfc.mk +++ /dev/null @@ -1,57 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# -# qmf console library makefile fragment, to be included in Makefile.am -# -lib_LTLIBRARIES += libqmfconsole.la - -# Public header files. -nobase_include_HEADERS += \ - ../include/qpid/console/Agent.h \ - ../include/qpid/console/Broker.h \ - ../include/qpid/console/ClassKey.h \ - ../include/qpid/console/ConsoleImportExport.h \ - ../include/qpid/console/ConsoleListener.h \ - ../include/qpid/console/Event.h \ - ../include/qpid/console/Object.h \ - ../include/qpid/console/ObjectId.h \ - ../include/qpid/console/Package.h \ - ../include/qpid/console/Schema.h \ - ../include/qpid/console/SequenceManager.h \ - ../include/qpid/console/SessionManager.h \ - ../include/qpid/console/Value.h - -libqmfconsole_la_SOURCES = \ - qpid/console/Agent.cpp \ - qpid/console/Broker.cpp \ - qpid/console/ClassKey.cpp \ - qpid/console/Event.cpp \ - qpid/console/Object.cpp \ - qpid/console/ObjectId.cpp \ - qpid/console/Package.cpp \ - qpid/console/Schema.cpp \ - qpid/console/SequenceManager.cpp \ - qpid/console/SessionManager.cpp \ - qpid/console/Value.cpp - -libqmfconsole_la_LIBADD = libqpidclient.la - -QMFCONSOLE_VERSION_INFO = 2:0:0 -libqmfconsole_la_LDFLAGS = -version-info $(QMFCONSOLE_VERSION_INFO) diff --git a/cpp/src/qpid.pc.in b/cpp/src/qpid.pc.in deleted file mode 100644 index 87d368f20c..0000000000 --- a/cpp/src/qpid.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: qpid -Version: @VERSION@ -Description: Qpid C++ client library -Requires: -Libs: -L${libdir} -lqpidmessaging @LIBS@ -Cflags: -I${includedir} diff --git a/cpp/src/qpid/Address.cpp b/cpp/src/qpid/Address.cpp deleted file mode 100644 index e2b2dfbcdf..0000000000 --- a/cpp/src/qpid/Address.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/Address.h" -#include "qpid/client/ConnectionSettings.h" - -#include <ostream> - -using namespace std; - -namespace qpid { - -const string Address::TCP("tcp"); - -ostream& operator<<(ostream& os, const Address& a) { - return os << a.protocol << ":" << a.host << ":" << a.port; -} - -bool operator==(const Address& x, const Address& y) { - return y.protocol==x.protocol && y.host==x.host && y.port == x.port; -} - -} // namespace qpid diff --git a/cpp/src/qpid/BufferRef.h b/cpp/src/qpid/BufferRef.h deleted file mode 100644 index bfe1f9ebaa..0000000000 --- a/cpp/src/qpid/BufferRef.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef QPID_BUFFERREF_H -#define QPID_BUFFERREF_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - -/** Template for mutable or const buffer references */ -template <class T> class BufferRefT { - public: - BufferRefT() : begin_(0), end_(0) {} - - BufferRefT(boost::intrusive_ptr<RefCounted> c, T* begin, T* end) : - counter(c), begin_(begin), end_(end) {} - - template <class U> BufferRefT(const BufferRefT<U>& other) : - counter(other.counter), begin_(other.begin_), end_(other.end_) {} - - T* begin() const { return begin_; } - T* end() const { return end_; } - - /** Return a sub-buffer of the current buffer */ - BufferRefT sub_buffer(T* begin, T* end) { - assert(begin_ <= begin && begin <= end_); - assert(begin_ <= end && end <= end_); - assert(begin <= end); - return BufferRefT(counter, begin, end); - } - - private: - boost::intrusive_ptr<RefCounted> counter; - T* begin_; - T* end_; -}; - -/** - * Reference to a mutable ref-counted buffer. - */ -typedef BufferRefT<char> BufferRef; - -/** - * Reference to a const ref-counted buffer. - */ -typedef BufferRefT<const char> ConstBufferRef; - -} // namespace qpid - -#endif /*!QPID_BUFFERREF_H*/ diff --git a/cpp/src/qpid/DataDir.cpp b/cpp/src/qpid/DataDir.cpp deleted file mode 100644 index ad732052ab..0000000000 --- a/cpp/src/qpid/DataDir.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Exception.h" -#include "qpid/DataDir.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/FileSysDir.h" -#include "qpid/sys/LockFile.h" - -namespace qpid { - -DataDir::DataDir (std::string path) : - enabled (!path.empty ()), - dirPath (path) -{ - if (!enabled) - { - QPID_LOG (info, "No data directory - Disabling persistent configuration"); - return; - } - - sys::FileSysDir dir(dirPath); - if (!dir.exists()) - dir.mkdir(); - std::string lockFileName(path); - lockFileName += "/lock"; - lockFile = std::auto_ptr<sys::LockFile>(new sys::LockFile(lockFileName, true)); -} - -DataDir::~DataDir () {} - -} // namespace qpid - diff --git a/cpp/src/qpid/DataDir.h b/cpp/src/qpid/DataDir.h deleted file mode 100644 index 828299f3ba..0000000000 --- a/cpp/src/qpid/DataDir.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_DATADIR_H -#define QPID_DATADIR_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include <memory> -#include "qpid/CommonImportExport.h" - -namespace qpid { - - namespace sys { - class LockFile; - } - -/** - * DataDir class. - */ -class DataDir -{ - const bool enabled; - const std::string dirPath; - std::auto_ptr<qpid::sys::LockFile> lockFile; - - public: - - QPID_COMMON_EXTERN DataDir (std::string path); - QPID_COMMON_EXTERN ~DataDir (); - - bool isEnabled() { return enabled; } - const std::string& getPath() { return dirPath; } -}; - -} // namespace qpid - -#endif /*!QPID_DATADIR_H*/ diff --git a/cpp/src/qpid/DisableExceptionLogging.h b/cpp/src/qpid/DisableExceptionLogging.h deleted file mode 100644 index 04a9240513..0000000000 --- a/cpp/src/qpid/DisableExceptionLogging.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef QPID_DISABLEEXCEPTIONLOGGING_H -#define QPID_DISABLEEXCEPTIONLOGGING_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/CommonImportExport.h" - -namespace qpid { - -/** - * Temporarily disable logging in qpid::Exception constructor. - * Used by log::Logger to avoid logging exceptions during Logger construction. - */ -struct DisableExceptionLogging -{ - QPID_COMMON_EXTERN DisableExceptionLogging(); - QPID_COMMON_EXTERN ~DisableExceptionLogging(); -}; -} // namespace qpid - -#endif /*!QPID_DISABLEEXCEPTIONLOGGING_H*/ diff --git a/cpp/src/qpid/Exception.cpp b/cpp/src/qpid/Exception.cpp deleted file mode 100644 index a6696f06e1..0000000000 --- a/cpp/src/qpid/Exception.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" -#include "qpid/DisableExceptionLogging.h" -#include <typeinfo> -#include <assert.h> -#include <string.h> - -namespace qpid { - -// Note on static initialization order: if an exception is constructed -// in a static constructor before disableExceptionLogging has been -// initialized, the worst that can happen is we lose an exception log -// message. Since we shouldn't be throwing a lot of exceptions during -// static construction this seems safe. -static bool disableExceptionLogging = false; - -DisableExceptionLogging::DisableExceptionLogging() { disableExceptionLogging = true; } -DisableExceptionLogging::~DisableExceptionLogging() { disableExceptionLogging = false; } - -Exception::Exception(const std::string& msg) throw() : message(msg) { - if (disableExceptionLogging) return; - QPID_LOG_IF(debug, !msg.empty(), "Exception constructed: " << message); -} - -Exception::~Exception() throw() {} - -std::string Exception::getPrefix() const { return ""; } - -std::string Exception::getMessage() const { return message; } - -const char* Exception::what() const throw() { - // Construct the what string the first time it is needed. - if (whatStr.empty()) { - whatStr = getPrefix(); - if (!whatStr.empty()) whatStr += ": "; - whatStr += message; - } - return whatStr.c_str(); -} - -ClosedException::ClosedException(const std::string& msg) - : Exception(msg) {} - -std::string ClosedException::getPrefix() const { return "Closed"; } - -} // namespace qpid diff --git a/cpp/src/qpid/Modules.cpp b/cpp/src/qpid/Modules.cpp deleted file mode 100644 index 727e05d212..0000000000 --- a/cpp/src/qpid/Modules.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "config.h" -#include "qpid/Modules.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Shlib.h" - -#include <boost/filesystem/operations.hpp> -#include <boost/filesystem/path.hpp> - -namespace fs=boost::filesystem; - -namespace { - -// CMake sets QPID_MODULE_SUFFIX; Autoconf doesn't, so assume Linux .so -#ifndef QPID_MODULE_SUFFIX -#define QPID_MODULE_SUFFIX ".so" -#endif - -inline std::string& suffix() { - static std::string s(QPID_MODULE_SUFFIX); - return s; -} - -bool isShlibName(const std::string& name) { - return name.find (suffix()) == name.length() - suffix().length(); -} - -} - -namespace qpid { - -ModuleOptions::ModuleOptions(const std::string& defaultModuleDir) - : qpid::Options("Module options"), loadDir(defaultModuleDir), noLoad(false) -{ - addOptions() - ("module-dir", optValue(loadDir, "DIR"), "Load all shareable modules in this directory") - ("load-module", optValue(load, "FILE"), "Specifies additional module(s) to be loaded") - ("no-module-dir", optValue(noLoad), "Don't load modules from module directory"); -} - -void tryShlib(const char* libname_, bool noThrow) { - std::string libname(libname_); - if (!isShlibName(libname)) libname += suffix(); - try { - sys::Shlib shlib(libname); - } - catch (const std::exception& /*e*/) { - if (!noThrow) - throw; - } -} - -void loadModuleDir (std::string dirname, bool isDefault) -{ - fs::path dirPath (dirname, fs::native); - - if (!fs::exists (dirPath)) - { - if (isDefault) - return; - throw Exception ("Directory not found: " + dirname); - } - if (!fs::is_directory(dirPath)) - { - throw Exception ("Invalid value for module-dir: " + dirname + " is not a directory"); - } - - fs::directory_iterator endItr; - for (fs::directory_iterator itr (dirPath); itr != endItr; ++itr) - { - if (!fs::is_directory(*itr) && isShlibName(itr->string())) - tryShlib (itr->string().data(), true); - } -} - -} // namespace qpid diff --git a/cpp/src/qpid/Modules.h b/cpp/src/qpid/Modules.h deleted file mode 100644 index 159dd156c1..0000000000 --- a/cpp/src/qpid/Modules.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef QPID_MODULES_H -#define QPID_MODULES_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Options.h" -#include <string> -#include <vector> -#include "qpid/CommonImportExport.h" - -namespace qpid { - -struct ModuleOptions : public qpid::Options { - std::string loadDir; - std::vector<std::string> load; - bool noLoad; - QPID_COMMON_EXTERN ModuleOptions(const std::string& defaultModuleDir); -}; - -QPID_COMMON_EXTERN void tryShlib(const char* libname, bool noThrow); -QPID_COMMON_EXTERN void loadModuleDir (std::string dirname, bool isDefault); - -} // namespace qpid - -#endif /*!QPID_MODULES_H*/ diff --git a/cpp/src/qpid/Options.cpp b/cpp/src/qpid/Options.cpp deleted file mode 100644 index 4b13e349f5..0000000000 --- a/cpp/src/qpid/Options.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/Options.h" -#include "qpid/Exception.h" - -#include <boost/bind.hpp> - -#include <fstream> -#include <algorithm> -#include <iostream> - -namespace qpid { - -using namespace std; - - -namespace { - -struct EnvOptMapper { - static bool matchChar(char env, char opt) { - return (env==toupper(opt)) || (strchr("-.", opt) && env=='_'); - } - - static bool matchStr(const string& env, boost::shared_ptr<po::option_description> desc) { - return desc->long_name().size() == env.size() && - std::equal(env.begin(), env.end(), desc->long_name().begin(), &matchChar); - } - - static bool matchCase(const string& env, boost::shared_ptr<po::option_description> desc) { - return env == desc->long_name(); - } - - EnvOptMapper(const Options& o) : opts(o) {} - - string operator()(const string& envVar) { - static const std::string prefix("QPID_"); - if (envVar.substr(0, prefix.size()) == prefix) { - string env = envVar.substr(prefix.size()); - typedef const std::vector< boost::shared_ptr<po::option_description> > OptDescs; - OptDescs::const_iterator i = - find_if(opts.options().begin(), opts.options().end(), boost::bind(matchStr, env, _1)); - if (i != opts.options().end()) - return (*i)->long_name(); - } - return string(); - } - - - bool - isComment ( string const & str ) - { - size_t i = str.find_first_not_of ( " \t" ); - - if ( i == string::npos ) - return true; - - return str[i] == '#'; - } - - - string configFileLine (string& line) { - - if ( isComment ( line ) ) - return string(); - - size_t pos = line.find ('='); - if (pos == string::npos) - return string(); - string key = line.substr (0, pos); -#if (BOOST_VERSION >= 103300) - typedef const std::vector< boost::shared_ptr<po::option_description> > OptDescs; - OptDescs::const_iterator i = - find_if(opts.options().begin(), opts.options().end(), boost::bind(matchCase, key, _1)); - if (i != opts.options().end()) - return string (line) + "\n"; - else - return string(); -#else - // Use 'count' to see if this option exists. Using 'find' will SEGV or hang - // if the option has not been defined yet. - if ( opts.count(key.c_str()) > 0 ) - return string ( line ) + "\n"; - else - return string ( ); -#endif - } - - const Options& opts; -}; - -} -std::string prettyArg(const std::string& name, const std::string& value) { - return value.empty() ? name+" " : name+" ("+value+") "; -} - -Options::Options(const string& name) : - po::options_description(name) -{ -} - - - - - -void Options::parse(int argc, char const* const* argv, const std::string& configFile, bool allowUnknown) -{ - string defaultConfigFile = configFile; // May be changed by env/cmdline - string parsing; - try { - po::variables_map vm; - parsing="command line options"; - if (argc > 0 && argv != 0) { - if (allowUnknown) { - // This hideous workaround is required because boost 1.33 has a bug - // that causes 'allow_unregistered' to not work. - po::command_line_parser clp = po::command_line_parser(argc, const_cast<char**>(argv)). - options(*this).allow_unregistered(); - po::parsed_options opts = clp.run(); - po::parsed_options filtopts = clp.run(); - filtopts.options.clear (); - for (std::vector< po::basic_option<char> >::iterator i = opts.options.begin(); - i != opts.options.end(); i++) - if (!i->unregistered) - filtopts.options.push_back (*i); - po::store(filtopts, vm); - - } - else - po::store(po::parse_command_line(argc, const_cast<char**>(argv), *this), vm); - } - parsing="environment variables"; - po::store(po::parse_environment(*this, EnvOptMapper(*this)), vm); - po::notify(vm); // configFile may be updated from arg/env options. - if (!configFile.empty()) { - parsing="configuration file "+configFile; - ifstream conf(configFile.c_str()); - if (conf.good()) { - // Remove this hack when we get a stable version of boost that - // can allow unregistered options in config files. - EnvOptMapper mapper(*this); - stringstream filtered; - - while (!conf.eof()) { - string line; - getline (conf, line); - filtered << mapper.configFileLine (line); - } - - po::store(po::parse_config_file(filtered, *this), vm); - // End of hack - } - else { - // No error if default configfile is missing/unreadable - // but complain for non-default config file. - if (configFile != defaultConfigFile) - throw Exception("cannot read configuration file " - +configFile); - } - } - po::notify(vm); - } - catch (const std::exception& e) { - ostringstream msg; - msg << "Error in " << parsing << ": " << e.what() << endl; -#if (BOOST_VERSION >= 103300) - if (find_nothrow("help", false)) - msg << "Use --help to see valid options" << endl; -#endif - throw Exception(msg.str()); - } -} - -CommonOptions::CommonOptions(const string& name, const string& configfile) - : Options(name), config(configfile) -{ - addOptions() - ("help,h", optValue(help), "Displays the help message") - ("version,v", optValue(version), "Displays version information") - ("config", optValue(config, "FILE"), "Reads configuration from FILE"); -} - - -} // namespace qpid - diff --git a/cpp/src/qpid/Plugin.cpp b/cpp/src/qpid/Plugin.cpp deleted file mode 100644 index 196b5c2333..0000000000 --- a/cpp/src/qpid/Plugin.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include <boost/bind.hpp> -#include <algorithm> - -namespace qpid { - -namespace { - -Plugin::Plugins& thePlugins() { - // This is a single threaded singleton implementation so - // it is important to be sure that the first use of this - // singleton is when the program is still single threaded - static Plugin::Plugins plugins; - return plugins; -} - -void invoke(boost::function<void()> f) { f(); } - -} // namespace - -Plugin::Target::~Target() { finalize(); } - -void Plugin::Target::finalize() { - std::for_each(finalizers.begin(), finalizers.end(), invoke); - finalizers.clear(); -} - -void Plugin::Target::addFinalizer(const boost::function<void()>& f) { - finalizers.push_back(f); -} - -namespace { -bool initBefore(const Plugin* a, const Plugin* b) { - return a->initOrder() < b->initOrder(); -} -} - -Plugin::Plugin() { - // Register myself. - thePlugins().push_back(this); - std::sort(thePlugins().begin(), thePlugins().end(), &initBefore); -} - -Plugin::~Plugin() {} - -Options* Plugin::getOptions() { return 0; } - -const Plugin::Plugins& Plugin::getPlugins() { return thePlugins(); } - -namespace { -template <class F> void each_plugin(const F& f) { - std::for_each(Plugin::getPlugins().begin(), Plugin::getPlugins().end(), f); -} -} - -void Plugin::addOptions(Options& opts) { - for (Plugins::const_iterator i = getPlugins().begin(); i != getPlugins().end(); ++i) { - if ((*i)->getOptions()) - opts.add(*(*i)->getOptions()); - } -} - -int Plugin::initOrder() const { return DEFAULT_INIT_ORDER; } - -void Plugin::earlyInitAll(Target& t) { - each_plugin(boost::bind(&Plugin::earlyInitialize, _1, boost::ref(t))); -} - -void Plugin::initializeAll(Target& t) { - each_plugin(boost::bind(&Plugin::initialize, _1, boost::ref(t))); -} - -} // namespace qpid diff --git a/cpp/src/qpid/Plugin.h b/cpp/src/qpid/Plugin.h deleted file mode 100644 index 4e057872b9..0000000000 --- a/cpp/src/qpid/Plugin.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef QPID_PLUGIN_H -#define QPID_PLUGIN_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/noncopyable.hpp> -#include <boost/function.hpp> -#include <vector> -#include "qpid/CommonImportExport.h" - -/**@file Generic plug-in framework. */ - -namespace qpid { -struct Options; - -/** - * Plug-in base class. - */ -class Plugin : private boost::noncopyable { - public: - typedef std::vector<Plugin*> Plugins; - /** Default value returned by initOrder() */ - static const int DEFAULT_INIT_ORDER=1000; - - /** - * Base interface for targets that can receive plug-ins. - * Also allows plug-ins to attach a a function to be called - * when the target is 'finalized'. - */ - class Target : private boost::noncopyable - { - public: - /** Calls finalize() if not already called. */ - QPID_COMMON_EXTERN virtual ~Target(); - - /** Run all the finalizers */ - QPID_COMMON_EXTERN void finalize(); - - /** Add a function to run when finalize() is called */ - QPID_COMMON_EXTERN void addFinalizer(const boost::function<void()>&); - - private: - std::vector<boost::function<void()> > finalizers; - }; - - /** - * Constructor registers the plug-in to appear in getPlugins(). - * - * A concrete Plugin is instantiated as a global or static - * member variable in a library so it is registered during - * initialization when the library is loaded. - */ - QPID_COMMON_EXTERN Plugin(); - - QPID_COMMON_EXTERN virtual ~Plugin(); - - /** - * Configuration options for the plugin. - * Then will be updated during option parsing by the host program. - * - * @return An options group or 0 for no options. Default returns 0. - * Plugin retains ownership of return value. - */ - QPID_COMMON_EXTERN virtual Options* getOptions(); - - /** - * Initialize Plugin functionality on a Target, called before - * initializing the target. - * - * Plugins should ignore targets they don't recognize. - * - * Called before the target itself is initialized. - */ - virtual void earlyInitialize(Target&) = 0; - - /** - * Initialize Plugin functionality on a Target. Called after - * initializing the target. - * - * Plugins should ignore targets they don't recognize. - * - * Called after the target is fully initialized. - */ - virtual void initialize(Target&) = 0; - - /** - * Initialization order. If a plugin does not override this, it - * returns DEFAULT_INIT_ORDER. Plugins that need to be initialized - * earlier/later than normal can override initOrder to return - * a lower/higher value than DEFAULT_INIT_ORDER. - */ - QPID_COMMON_EXTERN virtual int initOrder() const; - - /** List of registered Plugin objects. - * Caller must not delete plugin pointers. - */ - QPID_COMMON_EXTERN static const Plugins& getPlugins(); - - /** Call earlyInitialize() on all registered plugins */ - QPID_COMMON_EXTERN static void earlyInitAll(Target&); - - /** Call initialize() on all registered plugins */ - QPID_COMMON_EXTERN static void initializeAll(Target&); - - /** For each registered plugin, add plugin.getOptions() to opts. */ - QPID_COMMON_EXTERN static void addOptions(Options& opts); -}; - -} // namespace qpid - -#endif /*!QPID_PLUGIN_H*/ diff --git a/cpp/src/qpid/RefCounted.h b/cpp/src/qpid/RefCounted.h deleted file mode 100644 index f9e0107103..0000000000 --- a/cpp/src/qpid/RefCounted.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef QPID_REFCOUNTED_H -#define QPID_REFCOUNTED_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/utility.hpp> -#include <boost/detail/atomic_count.hpp> - -namespace qpid { - -/** - * Reference-counted base class. - * Note: this class isn't copyable - you must copy the intrusive_ptr that points - * to the class that has mixed this in not the class itself (as that would sidestep - * the reference counting) - */ -class RefCounted : boost::noncopyable { - mutable boost::detail::atomic_count count; - -public: - RefCounted() : count(0) {} - void addRef() const { ++count; } - void release() const { if (--count==0) released(); } - long refCount() { return count; } - -protected: - virtual ~RefCounted() {}; - // Allow subclasses to over-ride behavior when refcount reaches 0. - virtual void released() const { delete this; } -}; - - -} // namespace qpid - -// intrusive_ptr support. -namespace boost { -template <typename T> -inline void intrusive_ptr_add_ref(const T* p) { p->qpid::RefCounted::addRef(); } -template <typename T> -inline void intrusive_ptr_release(const T* p) { p->qpid::RefCounted::release(); } -} - - -#endif /*!QPID_REFCOUNTED_H*/ diff --git a/cpp/src/qpid/RefCountedBuffer.cpp b/cpp/src/qpid/RefCountedBuffer.cpp deleted file mode 100644 index 40d620f7ad..0000000000 --- a/cpp/src/qpid/RefCountedBuffer.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCountedBuffer.h" -#include <new> - -namespace qpid { - -void RefCountedBuffer::released() const { - this->~RefCountedBuffer(); - ::delete[] reinterpret_cast<const char*>(this); -} - -BufferRef RefCountedBuffer::create(size_t n) { - char* store=::new char[n+sizeof(RefCountedBuffer)]; - new(store) RefCountedBuffer; - char* start = store+sizeof(RefCountedBuffer); - return BufferRef( - boost::intrusive_ptr<RefCounted>(reinterpret_cast<RefCountedBuffer*>(store)), - start, start+n); -} - -} // namespace qpid - - diff --git a/cpp/src/qpid/RefCountedBuffer.h b/cpp/src/qpid/RefCountedBuffer.h deleted file mode 100644 index f0ea86130b..0000000000 --- a/cpp/src/qpid/RefCountedBuffer.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef QPID_REFCOUNTEDBUFFER_H -#define QPID_REFCOUNTEDBUFFER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/RefCounted.h> -#include <qpid/BufferRef.h> - -namespace qpid { - -/** - * Reference-counted byte buffer. No alignment guarantees. - */ -class RefCountedBuffer : public RefCounted { - public: - /** Create a reference counted buffer of size n */ - static BufferRef create(size_t n); - - protected: - void released() const; -}; - -} // namespace qpid - -#endif /*!QPID_REFCOUNTEDBUFFER_H*/ diff --git a/cpp/src/qpid/Sasl.h b/cpp/src/qpid/Sasl.h deleted file mode 100644 index 9a9d61b037..0000000000 --- a/cpp/src/qpid/Sasl.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_SASL_H -#define QPID_SASL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <memory> -#include <string> -#include "qpid/sys/IntegerTypes.h" - -namespace qpid { - -namespace sys { -class SecurityLayer; -struct SecuritySettings; -} - -/** - * Interface to SASL support. This class is implemented by platform-specific - * SASL providers. - */ -class Sasl -{ - public: - /** - * Start SASL negotiation with the broker. - * - * @param mechanisms Comma-separated list of the SASL mechanism the - * client supports. - * @param externalSecuritySettings security related details from the underlying transport - */ - virtual std::string start(const std::string& mechanisms, - const qpid::sys::SecuritySettings* externalSecuritySettings = 0) = 0; - virtual std::string step(const std::string& challenge) = 0; - virtual std::string getMechanism() = 0; - virtual std::string getUserId() = 0; - virtual std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(uint16_t maxFrameSize) = 0; - virtual ~Sasl() {} -}; -} // namespace qpid - -#endif /*!QPID_SASL_H*/ diff --git a/cpp/src/qpid/SaslFactory.cpp b/cpp/src/qpid/SaslFactory.cpp deleted file mode 100644 index f117404028..0000000000 --- a/cpp/src/qpid/SaslFactory.cpp +++ /dev/null @@ -1,429 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid//SaslFactory.h" -#include <map> -#include <string.h> - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifndef HAVE_SASL - -namespace qpid { - -//Null implementation - -SaslFactory::SaslFactory() {} - -SaslFactory::~SaslFactory() {} - -SaslFactory& SaslFactory::getInstance() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!instance.get()) { - instance = std::auto_ptr<SaslFactory>(new SaslFactory()); - } - return *instance; -} - -std::auto_ptr<Sasl> SaslFactory::create( const std::string &, const std::string &, const std::string &, const std::string &, int, int, bool ) -{ - return std::auto_ptr<Sasl>(); -} - -qpid::sys::Mutex SaslFactory::lock; -std::auto_ptr<SaslFactory> SaslFactory::instance; - -} // namespace qpid - -#else - -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/cyrus/CyrusSecurityLayer.h" -#include "qpid/log/Statement.h" -#include <sasl/sasl.h> -#include <strings.h> - -namespace qpid { - -using qpid::sys::SecurityLayer; -using qpid::sys::SecuritySettings; -using qpid::sys::cyrus::CyrusSecurityLayer; -using qpid::framing::InternalErrorException; - -const size_t MAX_LOGIN_LENGTH = 50; - -struct CyrusSaslSettings -{ - CyrusSaslSettings ( ) : - username ( std::string(0) ), - password ( std::string(0) ), - service ( std::string(0) ), - host ( std::string(0) ), - minSsf ( 0 ), - maxSsf ( 0 ) - { - } - - CyrusSaslSettings ( const std::string & user, const std::string & password, const std::string & service, const std::string & host, int minSsf, int maxSsf ) : - username(user), - password(password), - service(service), - host(host), - minSsf(minSsf), - maxSsf(maxSsf) - { - } - - std::string username, - password, - service, - host; - - int minSsf, - maxSsf; -}; - - -class CyrusSasl : public Sasl -{ - public: - CyrusSasl(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction); - ~CyrusSasl(); - std::string start(const std::string& mechanisms, const SecuritySettings* externalSettings); - std::string step(const std::string& challenge); - std::string getMechanism(); - std::string getUserId(); - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); - private: - sasl_conn_t* conn; - sasl_callback_t callbacks[5];//realm, user, authname, password, end-of-list - CyrusSaslSettings settings; - std::string input; - std::string mechanism; - char login[MAX_LOGIN_LENGTH]; - - /* In some contexts, like running in the broker or as a daemon, console - * interaction is impossible. In those cases, we will treat the attempt - * to interact as an error. */ - bool allowInteraction; - void interact(sasl_interact_t* client_interact); -}; - -//sasl callback functions -int getUserFromSettings(void *context, int id, const char **result, unsigned *len); -int getPasswordFromSettings(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret); -typedef int CallbackProc(); - -qpid::sys::Mutex SaslFactory::lock; -std::auto_ptr<SaslFactory> SaslFactory::instance; - -SaslFactory::SaslFactory() -{ - sasl_callback_t* callbacks = 0; - int result = sasl_client_init(callbacks); - if (result != SASL_OK) { - throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errstring(result, 0, 0))); - } -} - -SaslFactory::~SaslFactory() -{ - sasl_done(); -} - -SaslFactory& SaslFactory::getInstance() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!instance.get()) { - instance = std::auto_ptr<SaslFactory>(new SaslFactory()); - } - return *instance; -} - -std::auto_ptr<Sasl> SaslFactory::create(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction) -{ - std::auto_ptr<Sasl> sasl(new CyrusSasl(username, password, serviceName, hostName, minSsf, maxSsf, allowInteraction)); - return sasl; -} - -CyrusSasl::CyrusSasl(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction) - : conn(0), settings(username, password, serviceName, hostName, minSsf, maxSsf), allowInteraction(allowInteraction) -{ - size_t i = 0; - - callbacks[i].id = SASL_CB_GETREALM; - callbacks[i].proc = 0; - callbacks[i++].context = 0; - - if (!settings.username.empty()) { - callbacks[i].id = SASL_CB_AUTHNAME; - callbacks[i].proc = (CallbackProc*) &getUserFromSettings; - callbacks[i++].context = &settings; - - callbacks[i].id = SASL_CB_PASS; - if (settings.password.empty()) { - callbacks[i].proc = 0; - callbacks[i++].context = 0; - } else { - callbacks[i].proc = (CallbackProc*) &getPasswordFromSettings; - callbacks[i++].context = &settings; - } - } - - - callbacks[i].id = SASL_CB_LIST_END; - callbacks[i].proc = 0; - callbacks[i++].context = 0; -} - -CyrusSasl::~CyrusSasl() -{ - if (conn) { - sasl_dispose(&conn); - } -} - -namespace { - const std::string SSL("ssl"); -} - -std::string CyrusSasl::start(const std::string& mechanisms, const SecuritySettings* externalSettings) -{ - QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << ")"); - int result = sasl_client_new(settings.service.c_str(), - settings.host.c_str(), - 0, 0, /* Local and remote IP address strings */ - callbacks, - 0, /* security flags */ - &conn); - - if (result != SASL_OK) throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errdetail(conn))); - - sasl_security_properties_t secprops; - - if (externalSettings) { - sasl_ssf_t external_ssf = (sasl_ssf_t) externalSettings->ssf; - if (external_ssf) { - int result = sasl_setprop(conn, SASL_SSF_EXTERNAL, &external_ssf); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external SSF: " << result)); - } - QPID_LOG(debug, "external SSF detected and set to " << external_ssf); - } - if (externalSettings->authid.size()) { - const char* external_authid = externalSettings->authid.c_str(); - result = sasl_setprop(conn, SASL_AUTH_EXTERNAL, external_authid); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external auth: " << result)); - } - QPID_LOG(debug, "external auth detected and set to " << external_authid); - } - } - - secprops.min_ssf = settings.minSsf; - secprops.max_ssf = settings.maxSsf; - secprops.maxbufsize = 65535; - - QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << ", max_ssf: " << secprops.max_ssf); - - secprops.property_names = 0; - secprops.property_values = 0; - secprops.security_flags = 0;//TODO: provide means for application to configure these - - result = sasl_setprop(conn, SASL_SEC_PROPS, &secprops); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(conn))); - } - - sasl_interact_t* client_interact = 0; - const char *out = 0; - unsigned outlen = 0; - const char *chosenMechanism = 0; - - do { - result = sasl_client_start(conn, - mechanisms.c_str(), - &client_interact, - &out, - &outlen, - &chosenMechanism); - - if (result == SASL_INTERACT) { - interact(client_interact); - } - } while (result == SASL_INTERACT); - - if (result != SASL_CONTINUE && result != SASL_OK) { - throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errdetail(conn))); - } - - mechanism = std::string(chosenMechanism); - QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << "): selected " - << mechanism << " response: '" << std::string(out, outlen) << "'"); - return std::string(out, outlen); -} - -std::string CyrusSasl::step(const std::string& challenge) -{ - sasl_interact_t* client_interact = 0; - const char *out = 0; - unsigned outlen = 0; - int result = 0; - do { - result = sasl_client_step(conn, /* our context */ - challenge.data(), /* the data from the server */ - challenge.size(), /* it's length */ - &client_interact, /* this should be - unallocated and NULL */ - &out, /* filled in on success */ - &outlen); /* filled in on success */ - - if (result == SASL_INTERACT) { - interact(client_interact); - } - } while (result == SASL_INTERACT); - - std::string response; - if (result == SASL_CONTINUE || result == SASL_OK) response = std::string(out, outlen); - else if (result != SASL_OK) { - throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errdetail(conn))); - } - QPID_LOG(debug, "CyrusSasl::step(" << challenge << "): " << response); - return response; -} - -std::string CyrusSasl::getMechanism() -{ - return mechanism; -} - -std::string CyrusSasl::getUserId() -{ - int propResult; - const void* operName; - - propResult = sasl_getprop(conn, SASL_USERNAME, &operName); - if (propResult == SASL_OK) - return std::string((const char*) operName); - - return std::string(); -} - -void CyrusSasl::interact(sasl_interact_t* client_interact) -{ - - /* - In some context console interaction cannot be allowed, such - as when this code run as part of a broker, or as a some other - daemon. In those cases we will treat the attempt to - */ - if ( ! allowInteraction ) { - throw InternalErrorException("interaction disallowed"); - } - - if (client_interact->id == SASL_CB_PASS) { - char* password = getpass(client_interact->prompt); - input = std::string(password); - client_interact->result = input.data(); - client_interact->len = input.size(); - } else { - std::cout << client_interact->prompt; - if (client_interact->defresult) std::cout << " (" << client_interact->defresult << ")"; - std::cout << ": "; - if (std::cin >> input) { - client_interact->result = input.data(); - client_interact->len = input.size(); - } - } - -} - -std::auto_ptr<SecurityLayer> CyrusSasl::getSecurityLayer(uint16_t maxFrameSize) -{ - const void* value(0); - int result = sasl_getprop(conn, SASL_SSF, &value); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(conn))); - } - uint ssf = *(reinterpret_cast<const unsigned*>(value)); - std::auto_ptr<SecurityLayer> securityLayer; - if (ssf) { - QPID_LOG(info, "Installing security layer, SSF: "<< ssf); - securityLayer = std::auto_ptr<SecurityLayer>(new CyrusSecurityLayer(conn, maxFrameSize)); - } - return securityLayer; -} - -int getUserFromSettings(void* context, int /*id*/, const char** result, unsigned* /*len*/) -{ - if (context) { - *result = ((CyrusSaslSettings*) context)->username.c_str(); - QPID_LOG(debug, "getUserFromSettings(): " << (*result)); - return SASL_OK; - } else { - return SASL_FAIL; - } -} - -namespace { -// Global map of secrets allocated for SASL connections via callback -// to getPasswordFromSettings. Ensures secrets are freed. -class SecretsMap { - typedef std::map<sasl_conn_t*, void*> Map; - Map map; - public: - void keep(sasl_conn_t* conn, void* secret) { - Map::iterator i = map.find(conn); - if (i != map.end()) free(i->second); - map[conn] = secret; - } - - ~SecretsMap() { - for (Map::iterator i = map.begin(); i != map.end(); ++i) - free(i->second); - } -}; -SecretsMap getPasswordFromSettingsSecrets; -} - -int getPasswordFromSettings(sasl_conn_t* conn, void* context, int /*id*/, sasl_secret_t** psecret) -{ - if (context) { - size_t length = ((CyrusSaslSettings*) context)->password.size(); - sasl_secret_t* secret = (sasl_secret_t*) malloc(sizeof(sasl_secret_t) + length); - getPasswordFromSettingsSecrets.keep(conn, secret); - secret->len = length; - memcpy(secret->data, ((CyrusSaslSettings*) context)->password.data(), length); - *psecret = secret; - return SASL_OK; - } else { - return SASL_FAIL; - } -} - -} // namespace qpid - -#endif diff --git a/cpp/src/qpid/SaslFactory.h b/cpp/src/qpid/SaslFactory.h deleted file mode 100644 index 8554597147..0000000000 --- a/cpp/src/qpid/SaslFactory.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_SASLFACTORY_H -#define QPID_SASLFACTORY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/Sasl.h" -#include "qpid/sys/Mutex.h" -#include <memory> - -namespace qpid { - -/** - * Factory for instances of the Sasl interface through which Sasl - * support is provided to a ConnectionHandler. - */ -class SaslFactory -{ - public: - QPID_COMMON_EXTERN std::auto_ptr<Sasl> create(const std::string & userName, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction=true ); - QPID_COMMON_EXTERN static SaslFactory& getInstance(); - QPID_COMMON_EXTERN ~SaslFactory(); - private: - SaslFactory(); - static qpid::sys::Mutex lock; - static std::auto_ptr<SaslFactory> instance; -}; -} // namespace qpid - -#endif /*!QPID_SASLFACTORY_H*/ diff --git a/cpp/src/qpid/Serializer.h b/cpp/src/qpid/Serializer.h deleted file mode 100644 index a8ded9f5e0..0000000000 --- a/cpp/src/qpid/Serializer.h +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef QPID_SERIALIZER_H -#define QPID_SERIALIZER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <limits> -#include <algorithm> -#include "qpid/Exception.h" // FIXME aconway 2008-04-03: proper exception class. - -namespace qpid { - -/** - * Overload for types that do not provide a serialize() member. - * It should retrun a wrapper holding a reference to t that implements - * serialize() - */ -template <class T> T& serializable(T& t) { return t; } - -/** Serialize std::pair */ -template <class T, class U> struct SerializablePair { - std::pair<T,U>& value; - SerializablePair(std::pair<T,U>& x) : value(x) {} - template <class S> void serialize(S& s) { s(value.first)(value.second); } -}; - -template <class T, class U> -SerializablePair<T,U> serializable(std::pair<T,U>& p) { - return SerializablePair<T,U>(p); -} - -/** - * Base class for all serializers. - * Derived serializers inherit from either Encoder or Decoder. - * Serializers can be used as functors or static_visitors. - */ -template <class Derived> class Serializer { - public: - /** Temporarily set a lower relative limit on the serializer */ - class ScopedLimit { - public: - ScopedLimit(Serializer& s, size_t l) - : serializer(s), save(serializer.setLimit(l)) {} - - ~ScopedLimit() { serializer.setAbsLimit(save); } - - private: - Serializer& serializer; - size_t save; - }; - - static size_t maxLimit() { return std::numeric_limits<size_t>::max(); } - - Serializer() : bytes(0), limit(maxLimit()) {} - - typedef Derived& result_type; // unary functor requirement. - - /** Wrapper functor to pass serializer functors by reference. */ - template <class S> struct Ref { - typedef typename S::result_type result_type; - S& s; - Ref(S& ss) : s(ss) {} - template <class T> result_type operator()(T& x) { return s(x); } - template <class T> result_type operator()(const T& x) { return s(x); } - }; - - /** Reference wrapper to pass serializers by reference, - * e.g. to std:: functions that take functors. - */ - template <class S> static Ref<S> ref(S& s) { return Ref<S>(s); } - - /** Generic rule to serialize an iterator range */ - template <class Iter> Derived& operator()(Iter begin, Iter end) { - std::for_each(begin, end, ref(this->self())); - return self(); - } - - /** Set limit relative to current position. - * @return old absolute limit. - */ - size_t setLimit(size_t n) { - size_t l=limit; - limit = bytes+n; - return l; - } - - /** Get the max number of bytes that can be processed under the - * current limit. - */ - size_t bytesRemaining() const { - return limit - bytes; - } - /** Set absolute limit. */ - void setAbsLimit(size_t n) { - limit = n; - if (bytes > limit) - throw Exception("Framing error: data overrun"); // FIXME aconway 2008-04-03: proper exception. - } - - protected: - Derived& self() { return *static_cast<Derived*>(this); } - void addBytes(size_t n) { - size_t newBytes=bytes+n; - if (newBytes > limit) - throw Exception("Framing error: data overrun"); // FIXME aconway 2008-04-03: proper exception. - bytes = newBytes; - } - - private: - void checkLimit() { - } - - size_t bytes; // how many bytes serialized. - size_t limit; // bytes may not exceed this limit. -}; - -/** - * Base class for encoders, provides generic encode functions. - * - * A derived encoder must provide operator(const T&) to encode all - * primitive types T. - */ -template <class Derived> class EncoderBase : public Serializer<Derived> { - public: - using Serializer<Derived>::operator(); - using Serializer<Derived>::self; - - /** Default op() for non-primitive types. */ - template <class T> Derived& operator()(const T& t) { - serializable(const_cast<T&>(t)).serialize(self()); return self(); - } - - /** Split serialize() into encode()/decode() */ - template <class T> Derived& split(const T& t) { - t.encode(self()); return self(); - } -}; - -/** - * Base class for decoders, provides generic decode functions. - * - * A derived encoder must provide operator(T&) to encode all - * primitive types T. - */ -template <class Derived> class DecoderBase : public Serializer<Derived> { - public: - using Serializer<Derived>::operator(); - using Serializer<Derived>::self; - - /** Default op() for non-primitive types. */ - template <class T> Derived& operator()(T& t) { - - serializable(t).serialize(self()); return self(); - } - - /** Split serialize() into encode()/decode() */ - template <class T> Derived& split(T& t) { - t.decode(self()); return self(); - } -}; - -/** Serialize a type by converting it to/from another type. - * To serialize type Foo by converting to/from type Bar create - * a serializable() overload like this: - * - * SerializeAs<Foo,Bar> serializable(Foo& t) { return SerializeAs<Foo,Bar>(t); } - */ -template <class Type, class AsType> -struct SerializeAs { - Type& value; - SerializeAs(Type & t) : value(t) {} - template <class S> void serialize(S& s) { s.split(*this); } - template <class S> void encode(S& s) const { s(AsType(value)); } - template <class S> void decode(S& s) { AsType x; s(x); value=Type(x); } -}; - -} // namespace qpid - -#endif /*!QPID_SERIALIZER_H*/ diff --git a/cpp/src/qpid/SessionId.cpp b/cpp/src/qpid/SessionId.cpp deleted file mode 100644 index c7e83f83d7..0000000000 --- a/cpp/src/qpid/SessionId.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/SessionId.h" -#include <sstream> - -namespace qpid { - -SessionId::SessionId(const std::string& u, const std::string& n) : userId(u), name(n) {} - -bool SessionId::operator<(const SessionId& id) const { - return userId < id.userId || (userId == id.userId && name < id.name); -} - -bool SessionId::operator==(const SessionId& id) const { - return id.name == name && id.userId == userId; -} - -std::ostream& operator<<(std::ostream& o, const SessionId& id) { - return o << id.getUserId() << "." << id.getName(); -} - -std::string SessionId::str() const { - std::ostringstream o; - o << *this; - return o.str(); -} - -} // namespace qpid diff --git a/cpp/src/qpid/SessionState.cpp b/cpp/src/qpid/SessionState.cpp deleted file mode 100644 index e5019604d2..0000000000 --- a/cpp/src/qpid/SessionState.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/SessionState.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Statement.h" -#include <boost/bind.hpp> -#include <numeric> - -namespace qpid { -using framing::AMQFrame; -using framing::NotImplementedException; -using framing::InvalidArgumentException; -using framing::IllegalStateException; -using framing::ResourceLimitExceededException; -using framing::InternalErrorException; -using framing::FramingErrorException; - -namespace { -bool isControl(const AMQFrame& f) { - return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_CONTROL; -} -bool isCommand(const AMQFrame& f) { - return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_COMMAND; -} -} // namespace - -SessionPoint::SessionPoint(SequenceNumber c, uint64_t o) : command(c), offset(o) {} - -// TODO aconway 2008-05-22: Do complete frame sequence validity check here, -// currently duplicated betwen broker and client session impl. -// -void SessionPoint::advance(const AMQFrame& f) { - if (isControl(f)) return; // Ignore controls. - if (f.isFirstSegment() && f.isFirstFrame()) { - if (offset != 0) - throw FramingErrorException(QPID_MSG("Unexpected command start frame.")); - if (!isCommand(f)) - throw FramingErrorException( - QPID_MSG("Command start frame has invalid type" << f.getBody()->type())); - if (f.isLastSegment() && f.isLastFrame()) - ++command; // Single-frame command. - else - offset += f.encodedSize(); - } - else { // continuation frame for partial command - if (offset == 0) - throw FramingErrorException(QPID_MSG("Unexpected command continuation frame.")); - if (f.isLastSegment() && f.isLastFrame()) { - ++command; - offset = 0; - } - else { - // TODO aconway 2008-04-24: if we go to support for partial - // command replay, then it may be better to record the unframed - // data size in a command point rather than the framed size so - // that the relationship of fragment offsets to the replay - // list can be computed more easily. - // - offset += f.encodedSize(); - } - } -} - -bool SessionPoint::operator<(const SessionPoint& x) const { - return command < x.command || (command == x.command && offset < x.offset); -} - -bool SessionPoint::operator==(const SessionPoint& x) const { - return command == x.command && offset == x.offset; -} - - -SessionState::SendState::SendState() : unflushedSize(), replaySize(), bytesSinceKnownCompleted() {} - -SessionState::ReceiveState::ReceiveState() : bytesSinceKnownCompleted() {} - -uint32_t SessionState::getTimeout() const { return timeout; } -void SessionState::setTimeout(uint32_t seconds) { timeout = seconds; } - -SessionPoint SessionState::senderGetCommandPoint() { return sender.sendPoint; } -SequenceSet SessionState::senderGetIncomplete() const { return sender.incomplete; } -SessionPoint SessionState::senderGetReplayPoint() const { return sender.replayPoint; } - -SessionState::ReplayRange SessionState::senderExpected(const SessionPoint& expect) { - if (expect < sender.replayPoint || sender.sendPoint < expect) - throw InvalidArgumentException(QPID_MSG(getId() << ": expected command-point out of range.")); - QPID_LOG(debug, getId() << ": sender expected point moved to " << expect); - ReplayList::iterator i = sender.replayList.begin(); - SessionPoint p = sender.replayPoint; - while (i != sender.replayList.end() && p.command < expect.command) - p.advance(*i++); - assert(p.command == expect.command); - return boost::make_iterator_range(i, sender.replayList.end()); -} - -void SessionState::senderRecord(const AMQFrame& f) { - if (isControl(f)) return; // Ignore control frames. - QPID_LOG(trace, getId() << ": sent cmd " << sender.sendPoint.command << ": " << *f.getBody()); - - stateful = true; - if (timeout) sender.replayList.push_back(f); - sender.unflushedSize += f.encodedSize(); - sender.bytesSinceKnownCompleted += f.encodedSize(); - sender.replaySize += f.encodedSize(); - sender.incomplete += sender.sendPoint.command; - sender.sendPoint.advance(f); - if (config.replayHardLimit && config.replayHardLimit < sender.replaySize) - throw ResourceLimitExceededException("Replay buffer exceeeded hard limit"); -} - -static const uint32_t SPONTANEOUS_REQUEST_INTERVAL = 65536; - -bool SessionState::senderNeedFlush() const { - return (sender.sendPoint.command % SPONTANEOUS_REQUEST_INTERVAL == 0) || - (config.replayFlushLimit && sender.unflushedSize >= config.replayFlushLimit); -} - -void SessionState::senderRecordFlush() { - sender.flushPoint = sender.sendPoint; - sender.unflushedSize = 0; -} - -bool SessionState::senderNeedKnownCompleted() const { - return config.replayFlushLimit && sender.bytesSinceKnownCompleted >= config.replayFlushLimit; -} - -void SessionState::senderRecordKnownCompleted() { - sender.bytesSinceKnownCompleted = 0; -} - -void SessionState::senderConfirmed(const SessionPoint& confirmed) { - if (confirmed > sender.sendPoint) - throw InvalidArgumentException(QPID_MSG(getId() << ": confirmed < " << confirmed << " but only sent < " << sender.sendPoint)); - QPID_LOG(debug, getId() << ": sender confirmed point moved to " << confirmed); - ReplayList::iterator i = sender.replayList.begin(); - while (i != sender.replayList.end() && sender.replayPoint.command < confirmed.command) { - sender.replayPoint.advance(*i); - assert(sender.replayPoint <= sender.sendPoint); - sender.replaySize -= i->encodedSize(); - if (sender.replayPoint > sender.flushPoint) - sender.unflushedSize -= i->encodedSize(); - ++i; - } - if (sender.replayPoint > sender.flushPoint) - sender.flushPoint = sender.replayPoint; - sender.replayList.erase(sender.replayList.begin(), i); - assert(sender.replayPoint.offset == 0); -} - -void SessionState::senderCompleted(const SequenceSet& commands) { - if (commands.empty()) return; - QPID_LOG(debug, getId() << ": sender marked completed: " << commands); - sender.incomplete -= commands; - // Completion implies confirmation but we don't handle out-of-order - // confirmation, so confirm up to the end of the first contiguous range of commands. - senderConfirmed(SessionPoint(commands.rangesBegin()->end())); -} - -void SessionState::receiverSetCommandPoint(const SessionPoint& point) { - if (hasState() && point > receiver.received) - throw InvalidArgumentException(QPID_MSG(getId() << ": Command-point out of range.")); - QPID_LOG(debug, getId() << ": receiver command-point set to: " << point); - receiver.expected = point; - if (receiver.expected > receiver.received) - receiver.received = receiver.expected; -} - -bool SessionState::receiverRecord(const AMQFrame& f) { - if (receiverTrackingDisabled) return true; //Very nasty hack for push bridges - if (isControl(f)) return true; // Ignore control frames. - stateful = true; - receiver.expected.advance(f); - receiver.bytesSinceKnownCompleted += f.encodedSize(); - bool firstTime = receiver.expected > receiver.received; - if (firstTime) { - receiver.received = receiver.expected; - receiver.incomplete += receiverGetCurrent(); - } - QPID_LOG(trace, getId() << ": recv cmd " << receiverGetCurrent() << ": " << *f.getBody()); - if (!firstTime) QPID_LOG(trace, "Ignoring duplicate frame."); - return firstTime; -} - -void SessionState::receiverCompleted(SequenceNumber command, bool cumulative) { - if (receiverTrackingDisabled) return; //Very nasty hack for push bridges - assert(receiver.incomplete.contains(command)); // Internal error to complete command twice. - SequenceNumber first =cumulative ? receiver.incomplete.front() : command; - SequenceNumber last = command; - receiver.unknownCompleted.add(first, last); - receiver.incomplete.remove(first, last); - QPID_LOG(debug, getId() << ": receiver marked completed: " << command - << " incomplete: " << receiver.incomplete - << " unknown-completed: " << receiver.unknownCompleted); -} - -void SessionState::receiverKnownCompleted(const SequenceSet& commands) { - if (!commands.empty() && commands.back() > receiver.received.command) - throw InvalidArgumentException(QPID_MSG(getId() << ": Known-completed has invalid commands.")); - receiver.bytesSinceKnownCompleted=0; - receiver.unknownCompleted -= commands; - QPID_LOG(debug, getId() << ": receiver known completed: " << commands << " unknown: " << receiver.unknownCompleted); -} - -bool SessionState::receiverNeedKnownCompleted() const { - return (receiver.expected.command % SPONTANEOUS_REQUEST_INTERVAL == 0) || - (config.replayFlushLimit && receiver.bytesSinceKnownCompleted >= config.replayFlushLimit); -} - -const SessionPoint& SessionState::receiverGetExpected() const { return receiver.expected; } -const SessionPoint& SessionState::receiverGetReceived() const { return receiver.received; } -const SequenceSet& SessionState::receiverGetUnknownComplete() const { return receiver.unknownCompleted; } -const SequenceSet& SessionState::receiverGetIncomplete() const { return receiver.incomplete; } - -SequenceNumber SessionState::receiverGetCurrent() const { - SequenceNumber current = receiver.expected.command; - if (receiver.expected.offset == 0) - --current; - return current; -} - -SessionState::Configuration::Configuration(size_t flush, size_t hard) : - replayFlushLimit(flush), replayHardLimit(hard) {} - -SessionState::SessionState(const SessionId& i, const Configuration& c) - : id(i), timeout(0), config(c), stateful(false), receiverTrackingDisabled(false) -{ - QPID_LOG(debug, "SessionState::SessionState " << id << ": " << this); -} - -bool SessionState::hasState() const { return stateful; } - -SessionState::~SessionState() {} - -std::ostream& operator<<(std::ostream& o, const SessionPoint& p) { - return o << "(" << p.command.getValue() << "+" << p.offset << ")"; -} - -void SessionState::setState( - const SequenceNumber& replayStart, - const SequenceNumber& sendCommandPoint, - const SequenceSet& sentIncomplete, - const SequenceNumber& expected, - const SequenceNumber& received, - const SequenceSet& unknownCompleted, - const SequenceSet& receivedIncomplete -) -{ - sender.replayPoint = replayStart; - sender.flushPoint = sendCommandPoint; - sender.sendPoint = sendCommandPoint; - sender.unflushedSize = 0; - sender.replaySize = 0; // Replay list will be updated separately. - sender.incomplete = sentIncomplete; - sender.bytesSinceKnownCompleted = 0; - - receiver.expected = expected; - receiver.received = received; - receiver.unknownCompleted = unknownCompleted; - receiver.incomplete = receivedIncomplete; - receiver.bytesSinceKnownCompleted = 0; -} - -void SessionState::disableReceiverTracking() { receiverTrackingDisabled = true; } -void SessionState::enableReceiverTracking() { receiverTrackingDisabled = false; } - -} // namespace qpid diff --git a/cpp/src/qpid/SessionState.h b/cpp/src/qpid/SessionState.h deleted file mode 100644 index 02853b1143..0000000000 --- a/cpp/src/qpid/SessionState.h +++ /dev/null @@ -1,235 +0,0 @@ -#ifndef QPID_SESSIONSTATE_H -#define QPID_SESSIONSTATE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/SessionId.h> -#include <qpid/framing/SequenceNumber.h> -#include <qpid/framing/SequenceSet.h> -#include <qpid/framing/AMQFrame.h> -#include <qpid/framing/FrameHandler.h> -#include <boost/operators.hpp> -#include <boost/range/iterator_range.hpp> -#include <vector> -#include <iosfwd> -#include <qpid/CommonImportExport.h> - -namespace qpid { -using framing::SequenceNumber; -using framing::SequenceSet; - -/** A point in the session. Points to command id + offset */ -struct SessionPoint : boost::totally_ordered1<SessionPoint> { - QPID_COMMON_EXTERN SessionPoint(SequenceNumber command = 0, uint64_t offset = 0); - - SequenceNumber command; - uint64_t offset; - - /** Advance past frame f */ - QPID_COMMON_EXTERN void advance(const framing::AMQFrame& f); - - QPID_COMMON_EXTERN bool operator<(const SessionPoint&) const; - QPID_COMMON_EXTERN bool operator==(const SessionPoint&) const; -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const SessionPoint&); - -/** - * Support for session idempotence barrier and resume as defined in - * AMQP 0-10. - * - * We only issue/use contiguous confirmations, out-of-order confirmation - * is ignored. Out of order completion is fully supported. - * - * Raises NotImplemented if the command point is set greater than the - * max currently received command data, either explicitly via - * session.command-point or implicitly via session.gap. - * - * Partial replay is not supported, replay always begins on a command - * boundary, and we never confirm partial commands. - * - * The SessionPoint data structure does store offsets so this class - * could be extended to support partial replay without - * source-incompatbile API changes. - */ -class SessionState { - typedef std::vector<framing::AMQFrame> ReplayList; - - public: - - typedef boost::iterator_range<ReplayList::iterator> ReplayRange; - - struct Configuration { - QPID_COMMON_EXTERN Configuration(size_t flush=1024*1024, size_t hard=0); - size_t replayFlushLimit; // Flush when the replay list >= N bytes. 0 disables. - size_t replayHardLimit; // Kill session if replay list > N bytes. 0 disables. - }; - - QPID_COMMON_EXTERN SessionState(const SessionId& =SessionId(), const Configuration& =Configuration()); - - QPID_COMMON_EXTERN virtual ~SessionState(); - - bool hasState() const; - - const SessionId& getId() const { return id; } - - QPID_COMMON_EXTERN virtual uint32_t getTimeout() const; - QPID_COMMON_EXTERN virtual void setTimeout(uint32_t seconds); - - bool operator==(const SessionId& other) const { return id == other; } - bool operator==(const SessionState& other) const { return id == other.id; } - - // ==== Functions for sender state. - - /** Record frame f for replay. Should not be called during replay. */ - QPID_COMMON_EXTERN virtual void senderRecord(const framing::AMQFrame& f); - - /** @return true if we should send flush for confirmed and completed commands. */ - QPID_COMMON_EXTERN virtual bool senderNeedFlush() const; - - /** Called when flush for confirmed and completed commands is sent to peer. */ - QPID_COMMON_EXTERN virtual void senderRecordFlush(); - - /** True if we should reply to the next incoming completed command */ - QPID_COMMON_EXTERN virtual bool senderNeedKnownCompleted() const; - - /** Called when knownCompleted is sent to peer. */ - QPID_COMMON_EXTERN virtual void senderRecordKnownCompleted(); - - /** Called when the peer confirms up to comfirmed. */ - QPID_COMMON_EXTERN virtual void senderConfirmed(const SessionPoint& confirmed); - - /** Called when the peer indicates commands completed */ - QPID_COMMON_EXTERN virtual void senderCompleted(const SequenceSet& commands); - - /** Point from which the next new (not replayed) data will be sent. */ - QPID_COMMON_EXTERN virtual SessionPoint senderGetCommandPoint(); - - /** Set of outstanding incomplete commands */ - QPID_COMMON_EXTERN virtual SequenceSet senderGetIncomplete() const; - - /** Point from which we can replay. */ - QPID_COMMON_EXTERN virtual SessionPoint senderGetReplayPoint() const; - - /** Peer expecting commands from this point. - *@return Range of frames to be replayed. - */ - QPID_COMMON_EXTERN virtual ReplayRange senderExpected(const SessionPoint& expected); - - // ==== Functions for receiver state - - /** Set the command point. */ - QPID_COMMON_EXTERN virtual void receiverSetCommandPoint(const SessionPoint& point); - - /** Returns true if frame should be be processed, false if it is a duplicate. */ - QPID_COMMON_EXTERN virtual bool receiverRecord(const framing::AMQFrame& f); - - /** Command completed locally */ - QPID_COMMON_EXTERN virtual void receiverCompleted(SequenceNumber command, bool cumulative=false); - - /** Peer has indicated commands are known completed */ - QPID_COMMON_EXTERN virtual void receiverKnownCompleted(const SequenceSet& commands); - - /** True if the next completed control should set the timely-reply argument - * to request a knonw-completed response. - */ - QPID_COMMON_EXTERN virtual bool receiverNeedKnownCompleted() const; - - /** Get the incoming command point */ - QPID_COMMON_EXTERN virtual const SessionPoint& receiverGetExpected() const; - - /** Get the received high-water-mark, may be > getExpected() during replay */ - QPID_COMMON_EXTERN virtual const SessionPoint& receiverGetReceived() const; - - /** Completed received commands that the peer may not know about. */ - QPID_COMMON_EXTERN virtual const SequenceSet& receiverGetUnknownComplete() const; - - /** Incomplete received commands. */ - QPID_COMMON_EXTERN virtual const SequenceSet& receiverGetIncomplete() const; - - /** ID of the command currently being handled. */ - QPID_COMMON_EXTERN virtual SequenceNumber receiverGetCurrent() const; - - /** Set the state variables, used to create a session that will resume - * from some previously established point. - */ - QPID_COMMON_EXTERN virtual void setState( - const SequenceNumber& replayStart, - const SequenceNumber& sendCommandPoint, - const SequenceSet& sentIncomplete, - const SequenceNumber& expected, - const SequenceNumber& received, - const SequenceSet& unknownCompleted, - const SequenceSet& receivedIncomplete - ); - - /** - * So called 'push' bridges work by faking a subscribe request - * (and the accompanying flows etc) to the local broker to initiate - * the outflow of messages for the bridge. - * - * As the peer doesn't send these it cannot include them in its - * session state. To keep the session state on either side of the - * bridge in sync, this hack allows the tracking of state for - * received messages to be disabled for the faked commands and - * subsequently re-enabled. - */ - QPID_COMMON_EXTERN void disableReceiverTracking(); - QPID_COMMON_EXTERN void enableReceiverTracking(); - - private: - - struct SendState { - SendState(); - // invariant: replayPoint <= flushPoint <= sendPoint - SessionPoint replayPoint; // Can replay from this point - SessionPoint flushPoint; // Point of last flush - SessionPoint sendPoint; // Send from this point - ReplayList replayList; // Starts from replayPoint. - size_t unflushedSize; // Un-flushed bytes in replay list. - size_t replaySize; // Total bytes in replay list. - SequenceSet incomplete; // Commands sent and not yet completed. - size_t bytesSinceKnownCompleted; // Bytes sent since we last issued a knownCompleted. - } sender; - - struct ReceiveState { - ReceiveState(); - SessionPoint expected; // Expected from here - SessionPoint received; // Received to here. Invariant: expected <= received. - SequenceSet unknownCompleted; // Received & completed, may not not known-complete by peer. - SequenceSet incomplete; // Incomplete received commands. - size_t bytesSinceKnownCompleted; // Bytes sent since we last issued a knownCompleted. - } receiver; - - SessionId id; - uint32_t timeout; - Configuration config; - bool stateful; - bool receiverTrackingDisabled;//very nasty hack for 'push' bridges -}; - -inline bool operator==(const SessionId& id, const SessionState& s) { return s == id; } - -} // namespace qpid - - -#endif /*!QPID_SESSIONSTATE_H*/ diff --git a/cpp/src/qpid/SharedObject.h b/cpp/src/qpid/SharedObject.h deleted file mode 100644 index 852a036ab9..0000000000 --- a/cpp/src/qpid/SharedObject.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _SharedObject_ -#define _SharedObject_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include <boost/noncopyable.hpp> - -namespace qpid { - /** - * Template to enforce shared object conventions. - * Shared object classes should inherit : public qpid::SharedObject - * That ensures Foo: - * - has typedef boost::shared_ptr<T> shared_ptr - * - has virtual destructor - * - is boost::noncopyable (no default copy or assign) - * - has a protected default constructor. - * - * Shared objects should not have public constructors. - * Make constructors protected and provide public statc create() - * functions that return a shared_ptr. - */ - template <class T> - class SharedObject : private boost::noncopyable - { - public: - typedef boost::shared_ptr<T> shared_ptr; - - virtual ~SharedObject() {}; - - protected: - SharedObject() {} - }; -} - -#endif /*!_SharedObject_*/ diff --git a/cpp/src/qpid/StringUtils.cpp b/cpp/src/qpid/StringUtils.cpp deleted file mode 100644 index c436441c56..0000000000 --- a/cpp/src/qpid/StringUtils.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/StringUtils.h" - -namespace qpid { - -using std::string; -using std::vector; - -void split(vector<string>& out, const string& in, const string& delims) -{ - string::size_type start = in.find_first_not_of(delims); - if (start == string::npos) return; - - string::size_type end = in.find_first_of(delims, start); - while (end != string::npos) { - out.push_back(in.substr(start, end - start)); - start = in.find_first_not_of(delims, end); - if (start == string::npos) return; - end = in.find_first_of(delims, start); - } - out.push_back(in.substr(start)); -} - -vector<string> split(const string& in, const string& delims) -{ - vector<string> out; - split(out, in, delims); - return out; -} - -} // namespace qpid diff --git a/cpp/src/qpid/StringUtils.h b/cpp/src/qpid/StringUtils.h deleted file mode 100644 index 4130fae017..0000000000 --- a/cpp/src/qpid/StringUtils.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_STRINGUTILS_H -#define QPID_STRINGUTILS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/CommonImportExport.h" - -#include <string> -#include <vector> - -namespace qpid { - -/** - * Split 'in' into words using delimiters in 'delims' and put - * resulting strings into 'out' vector. - */ -QPID_COMMON_EXTERN void split(std::vector<std::string>& out, const std::string& in, const std::string& delims); -/** - * Split 'in' into words using delimiters in 'delims' and return the - * resulting strings in a vector. - */ -QPID_COMMON_EXTERN std::vector<std::string> split(const std::string& in, const std::string& delims); - -} // namespace qpid - -#endif /*!QPID_STRINGUTILS_H*/ diff --git a/cpp/src/qpid/Url.cpp b/cpp/src/qpid/Url.cpp deleted file mode 100644 index ab796f4642..0000000000 --- a/cpp/src/qpid/Url.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/Url.h" -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/StrError.h" -#include "qpid/client/Connector.h" -#include "qpid/sys/Mutex.h" -#include <boost/lexical_cast.hpp> - -#include <algorithm> -#include <vector> -#include <string> - -#include <string.h> - -using namespace std; -using boost::lexical_cast; - -namespace qpid { - -class ProtocolTags { - public: - bool find(const string& tag) { - sys::Mutex::ScopedLock l(lock); - return std::find(tags.begin(), tags.end(), tag) != tags.end(); - } - - void add(const string& tag) { - sys::Mutex::ScopedLock l(lock); - if (std::find(tags.begin(), tags.end(), tag) == tags.end()) - tags.push_back(tag); - } - - static ProtocolTags& instance() { - /** First call must be made while program is still single threaded. - * This will be the case since tags are registered in static initializers. - */ - static ProtocolTags tags; - return tags; - } - - private: - sys::Mutex lock; - vector<string> tags; -}; - -Url::Invalid::Invalid(const string& s) : Exception(s) {} - -Url Url::getHostNameUrl(uint16_t port) { - Address address("tcp", std::string(), port); - if (!sys::SystemInfo::getLocalHostname(address)) - throw Url::Invalid(QPID_MSG("Cannot get host name: " << qpid::sys::strError(errno))); - return Url(address); -} - -Url Url::getIpAddressesUrl(uint16_t port) { - Url url; - sys::SystemInfo::getLocalIpAddresses(port, url); - return url; -} - -string Url::str() const { - if (cache.empty() && !this->empty()) { - ostringstream os; - os << *this; - cache = os.str(); - } - return cache; -} - -ostream& operator<<(ostream& os, const Url& url) { - os << "amqp:"; - if (!url.getUser().empty()) os << url.getUser(); - if (!url.getPass().empty()) os << "/" << url.getPass(); - if (!(url.getUser().empty() && url.getPass().empty())) os << "@"; - Url::const_iterator i = url.begin(); - if (i!=url.end()) { - os << *i++; - while (i != url.end()) - os << "," << *i++; - } - return os; -} - -static const std::string TCP = "tcp"; - -/** Simple recursive-descent parser for this grammar: -url = ["amqp:"][ user ["/" password] "@" ] protocol_addr *("," protocol_addr) -protocol_addr = tcp_addr / rmda_addr / ssl_addr / .. others plug-in -tcp_addr = ["tcp:"] host [":" port] -rdma_addr = "rdma:" host [":" port] -ssl_addr = "ssl:" host [":" port] -*/ -class UrlParser { - public: - UrlParser(Url& u, const char* s) : url(u), text(s), end(s+strlen(s)), i(s) {} - bool parse() { - literal("amqp:"); // Optional - userPass(); // Optional - return list(&UrlParser::protocolAddr, &UrlParser::comma) && i == end; - } - - private: - typedef bool (UrlParser::*Rule)(); - - bool userPass() { - const char* at = std::find(i, end, '@'); - if (at == end) return false; - const char* slash = std::find(i, at, '/'); - url.setUser(string(i, slash)); - const char* pass = (slash == at) ? slash : slash+1; - url.setPass(string(pass, at)); - i = at+1; - return true; - } - - bool comma() { return literal(","); } - - bool protocolAddr() { - Address addr(Address::TCP, "", Address::AMQP_PORT); // Set up defaults - protocolTag(addr.protocol); // Optional - bool ok = (host(addr.host) && - (literal(":") ? port(addr.port) : true)); - if (ok) url.push_back(addr); - return ok; - } - - bool protocolTag(string& result) { - const char* j = std::find(i,end,':'); - if (j != end) { - string tag(i,j); - if (ProtocolTags::instance().find(tag)) { - i = j+1; - result = tag; - return true; - } - } - return false; - } - - // TODO aconway 2008-11-20: this does not fully implement - // http://www.ietf.org/rfc/rfc3986.txt. Works for DNS names and - // ipv4 literals but won't handle ipv6. - // - bool host(string& h) { - const char* start=i; - while (unreserved() || pctEncoded()) - ; - if (start == i) return false;//host is required - else h.assign(start, i); - return true; - } - - bool unreserved() { return (::isalnum(*i) || ::strchr("-._~", *i)) && advance(); } - - bool pctEncoded() { return literal("%") && hexDigit() && hexDigit(); } - - bool hexDigit() { return i < end && ::strchr("01234567890abcdefABCDEF", *i) && advance(); } - - bool port(uint16_t& p) { return decimalInt(p); } - - template <class IntType> bool decimalInt(IntType& n) { - const char* start = i; - while (decDigit()) - ; - try { - n = lexical_cast<IntType>(string(start, i)); - return true; - } catch(...) { return false; } - } - - bool decDigit() { return i < end && ::isdigit(*i) && advance(); } - - bool literal(const char* s) { - int n = ::strlen(s); - if (n <= end-i && equal(s, s+n, i)) return advance(n); - return false; - }; - - bool noop() { return true; } - - /** List of item, separated by separator, with min & max bounds. */ - bool list(Rule item, Rule separator, size_t min=0, size_t max=UNLIMITED) { - assert(max > 0); - assert(max >= min); - if (!(this->*item)()) return min == 0; // Empty list. - size_t n = 1; - while (n < max && i < end) { - if (!(this->*separator)()) break; - if (i == end || !(this->*item)()) return false; // Separator with no item. - ++n; - } - return n >= min; - } - - /** List of items with no separator */ - bool list(Rule item, size_t min=0, size_t max=UNLIMITED) { return list(item, &UrlParser::noop, min, max); } - - bool advance(size_t n=1) { - if (i+n > end) return false; - i += n; - return true; - } - - static const size_t UNLIMITED = size_t(~1); - static const std::string LOCALHOST; - - Url& url; - const char* text; - const char* end; - const char* i; -}; - -const string UrlParser::LOCALHOST("127.0.0.1"); - -void Url::parse(const char* url) { - parseNoThrow(url); - if (empty()) - throw Url::Invalid(QPID_MSG("Invalid URL: " << url)); -} - -void Url::parseNoThrow(const char* url) { - cache.clear(); - if (!UrlParser(*this, url).parse()) - clear(); -} - -void Url::throwIfEmpty() const { - if (empty()) - throw Url::Invalid("URL contains no addresses"); -} - -std::string Url::getUser() const { return user; } -std::string Url::getPass() const { return pass; } -void Url::setUser(const std::string& s) { user = s; } -void Url::setPass(const std::string& s) { pass = s; } - -std::istream& operator>>(std::istream& is, Url& url) { - std::string s; - is >> s; - url.parse(s); - return is; -} - -void Url::addProtocol(const std::string& tag) { ProtocolTags::instance().add(tag); } - -} // namespace qpid diff --git a/cpp/src/qpid/Version.h b/cpp/src/qpid/Version.h deleted file mode 100755 index b4805a3757..0000000000 --- a/cpp/src/qpid/Version.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef QPID_VERSION_H -#define QPID_VERSION_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <string> - -#ifdef HAVE_CONFIG_H -# include "config.h" -#else -# error "config.h not generated" -#endif - -namespace qpid { - const std::string product = PACKAGE_NAME; - const std::string version = PACKAGE_VERSION; -# if HAVE_SASL - const std::string saslName = BROKER_SASL_NAME; -# else - const std::string saslName = "qpidd-no-sasl"; -# endif -} - -#endif /*!QPID_VERSION_H*/ diff --git a/cpp/src/qpid/acl/Acl.cpp b/cpp/src/qpid/acl/Acl.cpp deleted file mode 100644 index 4b3dda7962..0000000000 --- a/cpp/src/qpid/acl/Acl.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/acl/Acl.h" -#include "qpid/acl/AclData.h" -#include "qpid/acl/AclValidator.h" -#include "qpid/sys/Mutex.h" - -#include "qpid/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/log/Logger.h" -#include "qpid/types/Variant.h" -#include "qmf/org/apache/qpid/acl/Package.h" -#include "qmf/org/apache/qpid/acl/EventAllow.h" -#include "qmf/org/apache/qpid/acl/EventDeny.h" -#include "qmf/org/apache/qpid/acl/EventFileLoaded.h" -#include "qmf/org/apache/qpid/acl/EventFileLoadFailed.h" - -#include <map> - -#include <boost/shared_ptr.hpp> -#include <boost/utility/in_place_factory.hpp> - -using namespace std; -using namespace qpid::acl; -using qpid::broker::Broker; -using namespace qpid::sys; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::acl; - -Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(false), mgmtObject(0) -{ - - agent = broker->getManagementAgent(); - - if (agent != 0){ - _qmf::Package packageInit(agent); - mgmtObject = new _qmf::Acl (agent, this, broker); - agent->addObject (mgmtObject); - } - std::string errorString; - if (!readAclFile(errorString)){ - throw Exception("Could not read ACL file " + errorString); - if (mgmtObject!=0) mgmtObject->set_enforcingAcl(0); - } - QPID_LOG(info, "ACL Plugin loaded"); - if (mgmtObject!=0) mgmtObject->set_enforcingAcl(1); -} - - bool Acl::authorise(const std::string& id, const Action& action, const ObjectType& objType, const std::string& name, std::map<Property, std::string>* params) - { - boost::shared_ptr<AclData> dataLocal; - { - Mutex::ScopedLock locker(dataLock); - dataLocal = data; //rcu copy - } - - // add real ACL check here... - AclResult aclreslt = dataLocal->lookup(id,action,objType,name,params); - - - return result(aclreslt, id, action, objType, name); - } - - bool Acl::authorise(const std::string& id, const Action& action, const ObjectType& objType, const std::string& ExchangeName, const std::string& RoutingKey) - { - boost::shared_ptr<AclData> dataLocal; - { - Mutex::ScopedLock locker(dataLock); - dataLocal = data; //rcu copy - } - - // only use dataLocal here... - AclResult aclreslt = dataLocal->lookup(id,action,objType,ExchangeName,RoutingKey); - - return result(aclreslt, id, action, objType, ExchangeName); - } - - - bool Acl::result(const AclResult& aclreslt, const std::string& id, const Action& action, const ObjectType& objType, const std::string& name) - { - switch (aclreslt) - { - case ALLOWLOG: - QPID_LOG(info, "ACL Allow id:" << id <<" action:" << AclHelper::getActionStr(action) << - " ObjectType:" << AclHelper::getObjectTypeStr(objType) << " Name:" << name ); - agent->raiseEvent(_qmf::EventAllow(id, AclHelper::getActionStr(action), - AclHelper::getObjectTypeStr(objType), - name, types::Variant::Map())); - case ALLOW: - return true; - case DENY: - if (mgmtObject!=0) mgmtObject->inc_aclDenyCount(); - return false; - case DENYLOG: - if (mgmtObject!=0) mgmtObject->inc_aclDenyCount(); - default: - QPID_LOG(info, "ACL Deny id:" << id << " action:" << AclHelper::getActionStr(action) << " ObjectType:" << AclHelper::getObjectTypeStr(objType) << " Name:" << name); - agent->raiseEvent(_qmf::EventDeny(id, AclHelper::getActionStr(action), - AclHelper::getObjectTypeStr(objType), - name, types::Variant::Map())); - return false; - } - return false; - } - - bool Acl::readAclFile(std::string& errorText) - { - // only set transferAcl = true if a rule implies the use of ACL on transfer, else keep false for performance reasons. - return readAclFile(aclValues.aclFile, errorText); - } - - bool Acl::readAclFile(std::string& aclFile, std::string& errorText) { - boost::shared_ptr<AclData> d(new AclData); - AclReader ar; - if (ar.read(aclFile, d)){ - agent->raiseEvent(_qmf::EventFileLoadFailed("", ar.getError())); - errorText = ar.getError(); - QPID_LOG(error,ar.getError()); - return false; - } - - AclValidator validator; - validator.validate(d); - - { - Mutex::ScopedLock locker(dataLock); - data = d; - } - transferAcl = data->transferAcl; // any transfer ACL - - if (data->transferAcl){ - QPID_LOG(debug,"Transfer ACL is Enabled!"); - } - - data->aclSource = aclFile; - if (mgmtObject!=0){ - mgmtObject->set_transferAcl(transferAcl?1:0); - mgmtObject->set_policyFile(aclFile); - sys::AbsTime now = sys::AbsTime::now(); - int64_t ns = sys::Duration(sys::EPOCH, now); - mgmtObject->set_lastAclLoad(ns); - agent->raiseEvent(_qmf::EventFileLoaded("")); - } - return true; - } - - Acl::~Acl(){} - - ManagementObject* Acl::GetManagementObject(void) const - { - return (ManagementObject*) mgmtObject; - } - - Manageable::status_t Acl::ManagementMethod (uint32_t methodId, Args& /*args*/, string& text) - { - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - QPID_LOG (debug, "Queue::ManagementMethod [id=" << methodId << "]"); - - switch (methodId) - { - case _qmf::Acl::METHOD_RELOADACLFILE : - readAclFile(text); - if (text.empty()) - status = Manageable::STATUS_OK; - else - status = Manageable::STATUS_USER; - break; - } - - return status; -} diff --git a/cpp/src/qpid/acl/Acl.h b/cpp/src/qpid/acl/Acl.h deleted file mode 100644 index 77f43838de..0000000000 --- a/cpp/src/qpid/acl/Acl.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef QPID_ACL_ACL_H -#define QPID_ACL_ACL_H - - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#include "qpid/acl/AclReader.h" -#include "qpid/RefCounted.h" -#include "qpid/broker/AclModule.h" -#include "qpid/management/Manageable.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/acl/Acl.h" -#include "qpid/sys/Mutex.h" - -#include <map> -#include <string> - - -namespace qpid { -namespace broker { -class Broker; -} - -namespace acl { - -struct AclValues { - std::string aclFile; -}; - - -class Acl : public broker::AclModule, public RefCounted, public management::Manageable -{ - -private: - acl::AclValues aclValues; - broker::Broker* broker; - bool transferAcl; - boost::shared_ptr<AclData> data; - qmf::org::apache::qpid::acl::Acl* mgmtObject; // mgnt owns lifecycle - qpid::management::ManagementAgent* agent; - mutable qpid::sys::Mutex dataLock; - -public: - Acl (AclValues& av, broker::Broker& b); - - void initialize(); - - inline virtual bool doTransferAcl() {return transferAcl;}; - - // create specilied authorise methods for cases that need faster matching as needed. - virtual bool authorise(const std::string& id, const Action& action, const ObjectType& objType, const std::string& name, std::map<Property, std::string>* params=0); - virtual bool authorise(const std::string& id, const Action& action, const ObjectType& objType, const std::string& ExchangeName,const std::string& RoutingKey); - - virtual ~Acl(); -private: - bool result(const AclResult& aclreslt, const std::string& id, const Action& action, const ObjectType& objType, const std::string& name); - bool readAclFile(std::string& errorText); - bool readAclFile(std::string& aclFile, std::string& errorText); - virtual qpid::management::ManagementObject* GetManagementObject(void) const; - virtual management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args, std::string& text); - -}; - - - -}} // namespace qpid::acl - -#endif // QPID_ACL_ACL_H diff --git a/cpp/src/qpid/acl/AclData.cpp b/cpp/src/qpid/acl/AclData.cpp deleted file mode 100644 index 658529b270..0000000000 --- a/cpp/src/qpid/acl/AclData.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/acl/AclData.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/IntegerTypes.h" -#include <boost/lexical_cast.hpp> - -namespace qpid { -namespace acl { - -AclData::AclData():decisionMode(qpid::acl::DENY),transferAcl(false),aclSource("UNKNOWN") -{ - for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++){ - actionList[cnt]=0; - } - -} - -void AclData::clear () -{ - for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++){ - if (actionList[cnt]){ - for (unsigned int cnt1=0; cnt1< qpid::acl::OBJECTSIZE; cnt1++) - delete actionList[cnt][cnt1]; - } - delete[] actionList[cnt]; - } - -} - -bool AclData::matchProp(const std::string & src, const std::string& src1) -{ - // allow wildcard on the end of strings... - if (src.data()[src.size()-1]=='*') { - return (src.compare(0, src.size()-1, src1, 0,src.size()-1 ) == 0); - } else { - return (src.compare(src1)==0) ; - } -} - -AclResult AclData::lookup(const std::string& id, const Action& action, const ObjectType& objType, - const std::string& name, std::map<Property, std::string>* params) { - - QPID_LOG(debug, "ACL: Lookup for id:" << id << " action:" << AclHelper::getActionStr((Action) action) - << " objectType:" << AclHelper::getObjectTypeStr((ObjectType) objType) << " name:" << name - << " with params " << AclHelper::propertyMapToString(params)); - - AclResult aclresult = decisionMode; - if (actionList[action] && actionList[action][objType]) { - AclData::actObjItr itrRule = actionList[action][objType]->find(id); - if (itrRule == actionList[action][objType]->end()) - itrRule = actionList[action][objType]->find("*"); - - if (itrRule != actionList[action][objType]->end()) { - - QPID_LOG(debug, "ACL: checking the following rules for : " << itrRule->first ); - - //loop the vector - for (ruleSetItr i = itrRule->second.begin(); i < itrRule->second.end(); i++) { - QPID_LOG(debug, "ACL: checking rule " << i->toString()); - // loop the names looking for match - bool match = true; - for (propertyMapItr pMItr = i->props.begin(); (pMItr != i->props.end()) && match; pMItr++) { - //match name is exists first - if (pMItr->first == acl::PROP_NAME) { - if (matchProp(pMItr->second, name)){ - QPID_LOG(debug, "ACL: name '" << name << "' matched with name '" - << pMItr->second << "' given in the rule"); - }else{ - match = false; - QPID_LOG(debug, "ACL: name '" << name << "' didn't match with name '" - << pMItr->second << "' given in the rule"); - } - } else if (params) { //match pMItr against params - propertyMapItr paramItr = params->find(pMItr->first); - if (paramItr == params->end()) { - match = false; - QPID_LOG(debug, "ACL: the given parameter map in lookup doesn't contain the property '" - << AclHelper::getPropertyStr(pMItr->first) << "'"); - }else if ( pMItr->first == acl::PROP_MAXQUEUECOUNT || pMItr->first == acl::PROP_MAXQUEUESIZE ) { - if ( pMItr->first == paramItr->first ) { - - uint64_t aclMax = 0; - uint64_t paramMax = 0; - - try{ - aclMax = boost::lexical_cast<uint64_t>(pMItr->second); - }catch(const boost::bad_lexical_cast&){ - match = false; - QPID_LOG(error,"Error evaluating rule. " << - "Illegal value given in ACL source <" << aclSource << - "> for property '" << - AclHelper::getPropertyStr(pMItr->first) << "' : " << - boost::lexical_cast<std::string>(pMItr->second)); - break; - } - - try{ - paramMax = boost::lexical_cast<uint64_t>(paramItr->second); - }catch(const boost::bad_lexical_cast&){ - match = false; - QPID_LOG(error,"Error evaluating rule. " << - "Illegal value given in lookup for property '" << - AclHelper::getPropertyStr(pMItr->first) << "' : " << - boost::lexical_cast<std::string>(paramItr->second)); - break; - } - - QPID_LOG(debug, "ACL: Numeric comparison for property " << - AclHelper::getPropertyStr(paramItr->first) << - " (value given in lookup = " << - boost::lexical_cast<std::string>(paramItr->second) << - ", value give in rule = " << - boost::lexical_cast<std::string>(pMItr->second) << " )"); - - if (( aclMax ) && ( paramMax == 0 || paramMax > aclMax)){ - match = decisionMode == qpid::acl::ALLOW ; - QPID_LOG(debug, "ACL: Limit exceeded and match=" << - (match ? "true": "false") << - " as decision mode is " << AclHelper::getAclResultStr(decisionMode)); - } - } - }else if (matchProp(pMItr->second, paramItr->second)) { - QPID_LOG(debug, "ACL: the pair(" - << AclHelper::getPropertyStr(paramItr->first) << "," << paramItr->second - << ") given in lookup matched the pair(" - << AclHelper::getPropertyStr(pMItr->first) << "," << pMItr->second << ") given in the rule"); - } else { - QPID_LOG(debug, "ACL: the pair(" - << AclHelper::getPropertyStr(paramItr->first) << "," << paramItr->second - << ") given in lookup doesn't match the pair(" - << AclHelper::getPropertyStr(pMItr->first) << "," << pMItr->second << ") given in the rule"); - match = false; - } - } - } - if (match) - { - aclresult = getACLResult(i->logOnly, i->log); - QPID_LOG(debug,"Successful match, the decision is:" << AclHelper::getAclResultStr(aclresult)); - return aclresult; - } - } - } - } - - QPID_LOG(debug,"No successful match, defaulting to the decision mode " << AclHelper::getAclResultStr(aclresult)); - return aclresult; -} - -AclResult AclData::lookup(const std::string& id, const Action& action, const ObjectType& objType, const std::string& /*Exchange*/ name, const std::string& RoutingKey) -{ - - QPID_LOG(debug, "ACL: Lookup for id:" << id << " action:" << AclHelper::getActionStr((Action) action) - << " objectType:" << AclHelper::getObjectTypeStr((ObjectType) objType) << " exchange name:" << name - << " with routing key " << RoutingKey); - - AclResult aclresult = decisionMode; - - if (actionList[action] && actionList[action][objType]){ - AclData::actObjItr itrRule = actionList[action][objType]->find(id); - - if (itrRule == actionList[action][objType]->end()) - itrRule = actionList[action][objType]->find("*"); - - if (itrRule != actionList[action][objType]->end() ) { - - QPID_LOG(debug, "ACL: checking the following rules for : " << itrRule->first ); - - //loop the vector - for (ruleSetItr i=itrRule->second.begin(); i<itrRule->second.end(); i++) { - QPID_LOG(debug, "ACL: checking rule " << i->toString()); - - // loop the names looking for match - bool match =true; - for (propertyMapItr pMItr = i->props.begin(); (pMItr != i->props.end()) && match; pMItr++) - { - //match name is exists first - if (pMItr->first == acl::PROP_NAME){ - if (matchProp(pMItr->second, name)){ - QPID_LOG(debug, "ACL: name '" << name << "' matched with name '" - << pMItr->second << "' given in the rule"); - - }else{ - match= false; - QPID_LOG(debug, "ACL: name '" << name << "' didn't match with name '" - << pMItr->second << "' given in the rule"); - } - }else if (pMItr->first == acl::PROP_ROUTINGKEY){ - if (matchProp(pMItr->second, RoutingKey)){ - QPID_LOG(debug, "ACL: name '" << name << "' matched with routing_key '" - << pMItr->second << "' given in the rule"); - }else{ - match= false; - QPID_LOG(debug, "ACL: name '" << name << "' didn't match with routing_key '" - << pMItr->second << "' given in the rule"); - } - } - } - if (match){ - aclresult = getACLResult(i->logOnly, i->log); - QPID_LOG(debug,"Successful match, the decision is:" << AclHelper::getAclResultStr(aclresult)); - return aclresult; - } - } - } - } - QPID_LOG(debug,"No successful match, defaulting to the decision mode " << AclHelper::getAclResultStr(aclresult)); - return aclresult; - -} - - -AclResult AclData::getACLResult(bool logOnly, bool log) -{ - switch (decisionMode) - { - case qpid::acl::ALLOWLOG: - case qpid::acl::ALLOW: - if (logOnly) return qpid::acl::ALLOWLOG; - if (log) - return qpid::acl::DENYLOG; - else - return qpid::acl::DENY; - - - case qpid::acl::DENYLOG: - case qpid::acl::DENY: - if (logOnly) return qpid::acl::DENYLOG; - if (log) - return qpid::acl::ALLOWLOG; - else - return qpid::acl::ALLOW; - } - - QPID_LOG(error, "ACL Decision Failed, setting DENY"); - return qpid::acl::DENY; -} - -AclData::~AclData() -{ - clear(); -} - -}} diff --git a/cpp/src/qpid/acl/AclData.h b/cpp/src/qpid/acl/AclData.h deleted file mode 100644 index efd3b60145..0000000000 --- a/cpp/src/qpid/acl/AclData.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef QPID_ACL_ACLDATA_H -#define QPID_ACL_ACLDATA_H - - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/broker/AclModule.h" -#include <vector> -#include <sstream> - -namespace qpid { -namespace acl { - -class AclData { - - -public: - - typedef std::map<qpid::acl::Property, std::string> propertyMap; - typedef propertyMap::const_iterator propertyMapItr; - struct rule { - - bool log; - bool logOnly; // this is a rule is to log only - - // key value map - //?? - propertyMap props; - - - rule (propertyMap& p):log(false),logOnly(false),props(p) {}; - - std::string toString () const { - std::ostringstream ruleStr; - ruleStr << "[log=" << log << ", logOnly=" << logOnly << " props{"; - for (propertyMapItr pMItr = props.begin(); pMItr != props.end(); pMItr++) { - ruleStr << " " << AclHelper::getPropertyStr((Property) pMItr-> first) << "=" << pMItr->second; - } - ruleStr << " }]"; - return ruleStr.str(); - } - }; - typedef std::vector<rule> ruleSet; - typedef ruleSet::const_iterator ruleSetItr; - typedef std::map<std::string, ruleSet > actionObject; // user - typedef actionObject::iterator actObjItr; - typedef actionObject* aclAction; - - // Action*[] -> Object*[] -> map<user -> set<Rule> > - aclAction* actionList[qpid::acl::ACTIONSIZE]; - qpid::acl::AclResult decisionMode; // determines if the rule set is a deny or allow mode. - bool transferAcl; - std::string aclSource; - - AclResult lookup(const std::string& id, const Action& action, const ObjectType& objType, const std::string& name, std::map<Property, std::string>* params=0); - AclResult lookup(const std::string& id, const Action& action, const ObjectType& objType, const std::string& ExchangeName, const std::string& RoutingKey); - AclResult getACLResult(bool logOnly, bool log); - - bool matchProp(const std::string & src, const std::string& src1); - void clear (); - - AclData(); - virtual ~AclData(); -}; - -}} // namespace qpid::acl - -#endif // QPID_ACL_ACLDATA_H diff --git a/cpp/src/qpid/acl/AclPlugin.cpp b/cpp/src/qpid/acl/AclPlugin.cpp deleted file mode 100644 index e4d721ea44..0000000000 --- a/cpp/src/qpid/acl/AclPlugin.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <sstream> -#include "qpid/acl/Acl.h" -#include "qpid/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/log/Statement.h" - -#include <boost/shared_ptr.hpp> -#include <boost/utility/in_place_factory.hpp> - -namespace qpid { -namespace acl { - -using namespace std; - -/** Note separating options from values to work around boost version differences. - * Old boost takes a reference to options objects, but new boost makes a copy. - * New boost allows a shared_ptr but that's not compatible with old boost. - */ -struct AclOptions : public Options { - AclValues& values; - - AclOptions(AclValues& v) : Options("ACL Options"), values(v) { - addOptions() - ("acl-file", optValue(values.aclFile, "FILE"), "The policy file to load from, loaded from data dir"); - } -}; - -struct AclPlugin : public Plugin { - - AclValues values; - AclOptions options; - boost::intrusive_ptr<Acl> acl; - - AclPlugin() : options(values) {} - - Options* getOptions() { return &options; } - - void init(broker::Broker& b) { - if (values.aclFile.empty()){ - QPID_LOG(info, "Policy file not specified. ACL Disabled, no ACL checking being done!"); - return; - } - - if (acl) throw Exception("ACL plugin cannot be initialized twice in one process."); - - if (values.aclFile.at(0) != '/' && !b.getDataDir().getPath().empty()) { - std::ostringstream oss; - oss << b.getDataDir().getPath() << "/" << values.aclFile; - values.aclFile = oss.str(); - } - - acl = new Acl(values, b); - b.setAcl(acl.get()); - b.addFinalizer(boost::bind(&AclPlugin::shutdown, this)); - } - - template <class T> bool init(Plugin::Target& target) { - T* t = dynamic_cast<T*>(&target); - if (t) init(*t); - return t; - } - - void earlyInitialize(Plugin::Target&) {} - - void initialize(Plugin::Target& target) { - init<broker::Broker>(target); - } - - void shutdown() { acl = 0; } -}; - -static AclPlugin instance; // Static initialization. - -// For test purposes. -boost::intrusive_ptr<Acl> getGlobalAcl() { return instance.acl; } - -}} // namespace qpid::acl diff --git a/cpp/src/qpid/acl/AclReader.cpp b/cpp/src/qpid/acl/AclReader.cpp deleted file mode 100644 index 31c69e69b5..0000000000 --- a/cpp/src/qpid/acl/AclReader.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/acl/AclReader.h" - -#include <cctype> -#include <cstring> -#include <fstream> -#include <sstream> -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" - -#include <iomanip> // degug -#include <iostream> // debug - -#define ACL_FORMAT_ERR_LOG_PREFIX "ACL format error: " << fileName << ":" << lineNumber << ": " - -namespace qpid { -namespace acl { - -AclReader::aclRule::aclRule(const AclResult r, const std::string n, const groupMap& groups) : res(r), actionAll(true), objStatus(NONE) { - processName(n, groups); -} -AclReader::aclRule::aclRule(const AclResult r, const std::string n, const groupMap& groups, const Action a) : res(r), actionAll(false), action(a), objStatus(NONE) { - processName(n, groups); -} - -void AclReader::aclRule::setObjectType(const ObjectType o) { - objStatus = VALUE; - object = o; -} - -void AclReader::aclRule::setObjectTypeAll() { - objStatus = ALL; -} - -bool AclReader::aclRule::addProperty(const Property p, const std::string v) { - return props.insert(propNvPair(p, v)).second; -} - -bool AclReader::aclRule::validate(const AclHelper::objectMapPtr& /*validationMap*/) { - // TODO - invalid rules won't ever be called in real life... - return true; -} - -// Debug aid -std::string AclReader::aclRule::toString() { - std::ostringstream oss; - oss << AclHelper::getAclResultStr(res) << " ["; - for (nsCitr itr = names.begin(); itr != names.end(); itr++) { - if (itr != names.begin()) oss << ", "; - oss << *itr; - } - oss << "]"; - if (actionAll) { - oss << " *"; - } else { - oss << " " << AclHelper::getActionStr(action); - } - if (objStatus == ALL) { - oss << " *"; - } else if (objStatus == VALUE) { - oss << " " << AclHelper::getObjectTypeStr(object); - } - for (pmCitr i=props.begin(); i!=props.end(); i++) { - oss << " " << AclHelper::getPropertyStr(i->first) << "=" << i->second; - } - return oss.str(); -} - -void AclReader::loadDecisionData(boost::shared_ptr<AclData> d) { - d->clear(); - QPID_LOG(debug, "ACL Load Rules"); - int cnt = rules.size(); - bool foundmode = false; - - for (rlCitr i = rules.end(); cnt; cnt--) { - i--; - QPID_LOG(debug, "ACL Processing " << std::setfill(' ') << std::setw(2) - << cnt << " " << (*i)->toString()); - - if (!foundmode && (*i)->actionAll && (*i)->names.size() == 1 - && (*((*i)->names.begin())).compare("*") == 0) { - d->decisionMode = (*i)->res; - QPID_LOG(debug, "ACL FoundMode " - << AclHelper::getAclResultStr(d->decisionMode)); - foundmode = true; - } else { - AclData::rule rule((*i)->props); - bool addrule = true; - - switch ((*i)->res) { - case qpid::acl::ALLOWLOG: - rule.log = true; - if (d->decisionMode == qpid::acl::ALLOW || - d->decisionMode == qpid::acl::ALLOWLOG) - rule.logOnly = true; - break; - case qpid::acl::ALLOW: - if (d->decisionMode == qpid::acl::ALLOW || - d->decisionMode == qpid::acl::ALLOWLOG) - addrule = false; - break; - case qpid::acl::DENYLOG: - rule.log = true; - if (d->decisionMode == qpid::acl::DENY || - d->decisionMode == qpid::acl::DENYLOG) - rule.logOnly = true; - break; - case qpid::acl::DENY: - if (d->decisionMode == qpid::acl::DENY || - d->decisionMode == qpid::acl::DENYLOG) - addrule = false; - break; - default: - throw Exception("Invalid ACL Result loading rules."); - } - - // Action -> Object -> map<user -> set<Rule> > - if (addrule) { - std::ostringstream actionstr; - for (int acnt = ((*i)->actionAll ? 0 : (*i)->action); - acnt < acl::ACTIONSIZE; - (*i)->actionAll ? acnt++ : acnt = acl::ACTIONSIZE) { - - if (acnt == acl::ACT_PUBLISH) - d->transferAcl = true; // we have transfer ACL - - actionstr << AclHelper::getActionStr((Action) acnt) << ","; - - //find the Action, create if not exist - if (d->actionList[acnt] == NULL) { - d->actionList[acnt] = - new AclData::aclAction[qpid::acl::OBJECTSIZE]; - for (int j = 0; j < qpid::acl::OBJECTSIZE; j++) - d->actionList[acnt][j] = NULL; - } - - // optimize this loop to limit to valid options only!! - for (int ocnt = ((*i)->objStatus != aclRule::VALUE ? 0 - : (*i)->object); - ocnt < acl::OBJECTSIZE; - (*i)->objStatus != aclRule::VALUE ? ocnt++ : ocnt = acl::OBJECTSIZE) { - - //find the Object, create if not exist - if (d->actionList[acnt][ocnt] == NULL) - d->actionList[acnt][ocnt] = - new AclData::actionObject; - - // add users and Rule to object set - bool allNames = false; - // check to see if names.begin is '*' - if ((*(*i)->names.begin()).compare("*") == 0) - allNames = true; - - for (nsCitr itr = (allNames ? names.begin() - : (*i)->names.begin()); - itr != (allNames ? names.end() : (*i)->names.end()); - itr++) { - - AclData::actObjItr itrRule = - d->actionList[acnt][ocnt]->find(*itr); - - if (itrRule == d->actionList[acnt][ocnt]->end()) { - AclData::ruleSet rSet; - rSet.push_back(rule); - d->actionList[acnt][ocnt]->insert - (make_pair(std::string(*itr), rSet)); - } else { - // TODO add code to check for dead rules - // allow peter create queue name=tmp <-- dead rule!! - // allow peter create queue - - itrRule->second.push_back(rule); - } - } - - } - } - - std::ostringstream objstr; - for (int ocnt = ((*i)->objStatus != aclRule::VALUE ? 0 : (*i)->object); - ocnt < acl::OBJECTSIZE; - (*i)->objStatus != aclRule::VALUE ? ocnt++ : ocnt = acl::OBJECTSIZE) { - objstr << AclHelper::getObjectTypeStr((ObjectType) ocnt) << ","; - } - - bool allNames = ((*(*i)->names.begin()).compare("*") == 0); - std::ostringstream userstr; - for (nsCitr itr = (allNames ? names.begin() : (*i)->names.begin()); - itr != (allNames ? names.end() : (*i)->names.end()); - itr++) { - userstr << *itr << ","; - } - - QPID_LOG(debug, "ACL: Adding actions {" << - actionstr.str().substr(0,actionstr.str().length()-1) - << "} to objects {" << - objstr.str().substr(0,objstr.str().length()-1) - << "} with props " << - AclHelper::propertyMapToString(&rule.props) - << " for users {" << - userstr.str().substr(0,userstr.str().length()-1) - << "}" ); - } else { - QPID_LOG(debug, "ACL Skipping based on Mode:" - << AclHelper::getAclResultStr(d->decisionMode)); - } - } - - } - -} - - -void AclReader::aclRule::processName(const std::string& name, const groupMap& groups) { - if (name.compare("all") == 0) { - names.insert("*"); - } else { - gmCitr itr = groups.find(name); - if (itr == groups.end()) { - names.insert(name); - } else { - names.insert(itr->second->begin(), itr->second->end()); - } - } -} - -AclReader::AclReader() : lineNumber(0), contFlag(false), validationMap(new AclHelper::objectMap) { - AclHelper::loadValidationMap(validationMap); - names.insert("*"); -} - -AclReader::~AclReader() {} - -std::string AclReader::getError() { - return errorStream.str(); -} - -int AclReader::read(const std::string& fn, boost::shared_ptr<AclData> d) { - fileName = fn; - lineNumber = 0; - char buff[1024]; - std::ifstream ifs(fn.c_str(), std::ios_base::in); - if (!ifs.good()) { - errorStream << "Unable to open ACL file \"" << fn << "\": eof=" << (ifs.eof()?"T":"F") << "; fail=" << (ifs.fail()?"T":"F") << "; bad=" << (ifs.bad()?"T":"F"); - return -1; - } - try { - bool err = false; - while (ifs.good()) { - ifs.getline(buff, 1024); - lineNumber++; - if (std::strlen(buff) > 0 && buff[0] != '#') // Ignore blank lines and comments - err |= !processLine(buff); - } - if (!ifs.eof()) - { - errorStream << "Unable to read ACL file \"" << fn << "\": eof=" << (ifs.eof()?"T":"F") << "; fail=" << (ifs.fail()?"T":"F") << "; bad=" << (ifs.bad()?"T":"F"); - ifs.close(); - return -2; - } - ifs.close(); - if (err) return -3; - QPID_LOG(notice, "Read ACL file \"" << fn << "\""); - } catch (const std::exception& e) { - errorStream << "Unable to read ACL file \"" << fn << "\": " << e.what(); - ifs.close(); - return -4; - } catch (...) { - errorStream << "Unable to read ACL file \"" << fn << "\": Unknown exception"; - ifs.close(); - return -5; - } - printNames(); - printRules(); - loadDecisionData(d); - - return 0; -} - -bool AclReader::processLine(char* line) { - bool ret = false; - std::vector<std::string> toks; - - // Check for continuation - char* contCharPtr = std::strrchr(line, '\\'); - bool cont = contCharPtr != 0; - if (cont) *contCharPtr = 0; - - int numToks = tokenize(line, toks); - - if (cont && numToks == 0){ - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line \"" << lineNumber << "\" contains an illegal extension."; - return false; - } - - if (numToks && (toks[0].compare("group") == 0 || contFlag)) { - ret = processGroupLine(toks, cont); - } else if (numToks && toks[0].compare("acl") == 0) { - ret = processAclLine(toks); - } else { - // Check for whitespace only line, ignore these - bool ws = true; - for (unsigned i=0; i<std::strlen(line) && ws; i++) { - if (!std::isspace(line[i])) ws = false; - } - if (ws) { - ret = true; - } else { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Non-continuation line must start with \"group\" or \"acl\"."; - ret = false; - } - } - contFlag = cont; - return ret; -} - -int AclReader::tokenize(char* line, std::vector<std::string>& toks) { - const char* tokChars = " \t\n\f\v\r"; - int cnt = 0; - char* cp = std::strtok(line, tokChars); - while (cp != 0) { - toks.push_back(std::string(cp)); - cnt++; - cp = std::strtok(0, tokChars); - } - return cnt; -} - -// Return true if the line is successfully processed without errors -// If cont is true, then groupName must be set to the continuation group name -bool AclReader::processGroupLine(tokList& toks, const bool cont) { - const unsigned toksSize = toks.size(); - - if (contFlag) { - gmCitr citr = groups.find(groupName); - for (unsigned i = 0; i < toksSize; i++) { - if (!isValidUserName(toks[i])) return false; - addName(toks[i], citr->second); - } - } else { - const unsigned minimumSize = (cont ? 2 : 3); - if (toksSize < minimumSize) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Insufficient tokens for group definition."; - return false; - } - if (!isValidGroupName(toks[1])) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Group name \"" << toks[1] << "\" contains illegal characters."; - return false; - } - gmCitr citr = addGroup(toks[1]); - if (citr == groups.end()) return false; - for (unsigned i = 2; i < toksSize; i++) { - if (!isValidUserName(toks[i])) return false; - addName(toks[i], citr->second); - } - } - return true; -} - -// Return true if sucessfully added group -AclReader::gmCitr AclReader::addGroup(const std::string& newGroupName) { - gmCitr citr = groups.find(newGroupName); - if (citr != groups.end()) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Duplicate group name \"" << newGroupName << "\"."; - return groups.end(); - } - groupPair p(newGroupName, nameSetPtr(new nameSet)); - gmRes res = groups.insert(p); - assert(res.second); - groupName = newGroupName; - return res.first; -} - -void AclReader::addName(const std::string& name, nameSetPtr groupNameSet) { - gmCitr citr = groups.find(name); - if (citr != groups.end() && citr->first != name){ - // This is a previously defined group: add all the names in that group to this group - groupNameSet->insert(citr->second->begin(), citr->second->end()); - } else { - // Not a known group name - groupNameSet->insert(name); - addName(name); - } -} - -void AclReader::addName(const std::string& name) { - names.insert(name); -} - -// Debug aid -void AclReader::printNames() const { - QPID_LOG(debug, "Group list: " << groups.size() << " groups found:" ); - std::string tmp; - for (gmCitr i=groups.begin(); i!= groups.end(); i++) { - tmp += " \""; - tmp += i->first; - tmp += "\":"; - for (nsCitr j=i->second->begin(); j!=i->second->end(); j++) { - tmp += " "; - tmp += *j; - } - QPID_LOG(debug, tmp); - tmp.clear(); - } - QPID_LOG(debug, "Name list: " << names.size() << " names found:" ); - tmp.clear(); - for (nsCitr k=names.begin(); k!=names.end(); k++) { - tmp += " "; - tmp += *k; - } - QPID_LOG(debug, tmp); -} - -bool AclReader::processAclLine(tokList& toks) { - const unsigned toksSize = toks.size(); - if (toksSize < 4) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Insufficient tokens for acl definition."; - return false; - } - - AclResult res; - try { - res = AclHelper::getAclResult(toks[1]); - } catch (...) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Unknown ACL permission \"" << toks[1] << "\"."; - return false; - } - - bool actionAllFlag = toks[3].compare("all") == 0; - bool userAllFlag = toks[2].compare("all") == 0; - Action action; - if (actionAllFlag) { - - if (userAllFlag && toksSize > 4) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Tokens found after action \"all\"."; - return false; - } - action = ACT_CONSUME; // dummy; compiler must initialize action for this code path - } else { - try { - action = AclHelper::getAction(toks[3]); - } catch (...) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Unknown action \"" << toks[3] << "\"."; - return false; - } - } - - // Create rule obj; then add object (if any) and properties (if any) - aclRulePtr rule; - if (actionAllFlag) { - rule.reset(new aclRule(res, toks[2], groups)); - } else { - rule.reset(new aclRule(res, toks[2], groups, action)); - } - - if (toksSize >= 5) { // object name-value pair - if (toks[4].compare("all") == 0) { - rule->setObjectTypeAll(); - } else { - try { - rule->setObjectType(AclHelper::getObjectType(toks[4])); - } catch (...) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Unknown object \"" << toks[4] << "\"."; - return false; - } - } - } - - if (toksSize >= 6) { // property name-value pair(s) - for (unsigned i=5; i<toksSize; i++) { - nvPair propNvp = splitNameValuePair(toks[i]); - if (propNvp.second.size() == 0) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - <<", Badly formed property name-value pair \"" - << propNvp.first << "\". (Must be name=value)"; - return false; - } - Property prop; - try { - prop = AclHelper::getProperty(propNvp.first); - } catch (...) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Unknown property \"" << propNvp.first << "\"."; - return false; - } - rule->addProperty(prop, propNvp.second); - } - } - // Check if name (toks[2]) is group; if not, add as name of individual - if (toks[2].compare("all") != 0) { - if (groups.find(toks[2]) == groups.end()) { - addName(toks[2]); - } - } - - // If rule validates, add to rule list - if (!rule->validate(validationMap)) { - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Invalid object/action/property combination."; - return false; - } - rules.push_back(rule); - - return true; -} - -// Debug aid -void AclReader::printRules() const { - QPID_LOG(debug, "Rule list: " << rules.size() << " ACL rules found:"); - int cnt = 0; - for (rlCitr i=rules.begin(); i<rules.end(); i++,cnt++) { - QPID_LOG(debug, " " << std::setfill(' ') << std::setw(2) << cnt << " " << (*i)->toString()); - } -} - -// Static function -// Return true if the name is well-formed (ie contains legal characters) -bool AclReader::isValidGroupName(const std::string& name) { - for (unsigned i=0; i<name.size(); i++) { - const char ch = name.at(i); - if (!std::isalnum(ch) && ch != '-' && ch != '_') return false; - } - return true; -} - -// Static function -// Split name-value pair around '=' char of the form "name=value" -AclReader::nvPair AclReader::splitNameValuePair(const std::string& nvpString) { - std::size_t pos = nvpString.find("="); - if (pos == std::string::npos || pos == nvpString.size() - 1) { - return nvPair(nvpString, ""); - } - return nvPair(nvpString.substr(0, pos), nvpString.substr(pos+1)); -} - -// Returns true if a username has the name@realm format -bool AclReader::isValidUserName(const std::string& name){ - size_t pos = name.find('@'); - if ( pos == std::string::npos || pos == name.length() -1){ - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Username '" << name << "' must contain a realm"; - return false; - } - for (unsigned i=0; i<name.size(); i++) { - const char ch = name.at(i); - if (!std::isalnum(ch) && ch != '-' && ch != '_' && ch != '@' && ch != '.' && ch != '/'){ - errorStream << ACL_FORMAT_ERR_LOG_PREFIX << "Line : " << lineNumber - << ", Username \"" << name << "\" contains illegal characters."; - return false; - } - } - return true; -} - -}} // namespace qpid::acl diff --git a/cpp/src/qpid/acl/AclReader.h b/cpp/src/qpid/acl/AclReader.h deleted file mode 100644 index 62c6f38f37..0000000000 --- a/cpp/src/qpid/acl/AclReader.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef QPID_ACL_ACLREADER_H -#define QPID_ACL_ACLREADER_H - - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include <map> -#include <set> -#include <string> -#include <vector> -#include <sstream> -#include "qpid/acl/AclData.h" -#include "qpid/broker/AclModule.h" - -namespace qpid { -namespace acl { - -class AclReader { - typedef std::set<std::string> nameSet; - typedef nameSet::const_iterator nsCitr; - typedef boost::shared_ptr<nameSet> nameSetPtr; - - typedef std::pair<std::string, nameSetPtr> groupPair; - typedef std::map<std::string, nameSetPtr> groupMap; - typedef groupMap::const_iterator gmCitr; - typedef std::pair<gmCitr, bool> gmRes; - - typedef std::pair<Property, std::string> propNvPair; - typedef std::map<Property, std::string> propMap; - typedef propMap::const_iterator pmCitr; - - class aclRule { - public: - enum objectStatus {NONE, VALUE, ALL}; - AclResult res; - nameSet names; - bool actionAll; // True if action is set to keyword "all" - Action action; // Ignored if action is set to keyword "all" - objectStatus objStatus; - ObjectType object; // Ignored for all status values except VALUE - propMap props; - public: - aclRule(const AclResult r, const std::string n, const groupMap& groups); // action = "all" - aclRule(const AclResult r, const std::string n, const groupMap& groups, const Action a); - void setObjectType(const ObjectType o); - void setObjectTypeAll(); - bool addProperty(const Property p, const std::string v); - bool validate(const AclHelper::objectMapPtr& validationMap); - std::string toString(); // debug aid - private: - void processName(const std::string& name, const groupMap& groups); - }; - typedef boost::shared_ptr<aclRule> aclRulePtr; - typedef std::vector<aclRulePtr> ruleList; - typedef ruleList::const_iterator rlCitr; - - typedef std::vector<std::string> tokList; - typedef tokList::const_iterator tlCitr; - - typedef std::set<std::string> keywordSet; - typedef keywordSet::const_iterator ksCitr; - typedef std::pair<std::string, std::string> nvPair; // Name-Value pair - - std::string fileName; - int lineNumber; - bool contFlag; - std::string groupName; - nameSet names; - groupMap groups; - ruleList rules; - AclHelper::objectMapPtr validationMap; - std::ostringstream errorStream; - - public: - AclReader(); - virtual ~AclReader(); - int read(const std::string& fn, boost::shared_ptr<AclData> d); - std::string getError(); - - private: - bool processLine(char* line); - void loadDecisionData( boost::shared_ptr<AclData> d); - int tokenize(char* line, tokList& toks); - - bool processGroupLine(tokList& toks, const bool cont); - gmCitr addGroup(const std::string& groupName); - void addName(const std::string& name, nameSetPtr groupNameSet); - void addName(const std::string& name); - void printNames() const; // debug aid - - bool processAclLine(tokList& toks); - void printRules() const; // debug aid - bool isValidUserName(const std::string& name); - - static bool isValidGroupName(const std::string& name); - static nvPair splitNameValuePair(const std::string& nvpString); -}; - -}} // namespace qpid::acl - -#endif // QPID_ACL_ACLREADER_H diff --git a/cpp/src/qpid/acl/AclValidator.cpp b/cpp/src/qpid/acl/AclValidator.cpp deleted file mode 100644 index 57b68e520a..0000000000 --- a/cpp/src/qpid/acl/AclValidator.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/acl/AclValidator.h" -#include "qpid/acl/AclData.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/IntegerTypes.h" -#include <boost/lexical_cast.hpp> -#include <boost/bind.hpp> -#include <numeric> -#include <sstream> - -namespace qpid { -namespace acl { - -AclValidator::IntPropertyType::IntPropertyType(int64_t i,int64_t j) : min(i), max(j){ -} - -bool AclValidator::IntPropertyType::validate(const std::string& val) { - int64_t v; - try - { - v = boost::lexical_cast<int64_t>(val); - }catch(const boost::bad_lexical_cast&){ - return 0; - } - - if (v < min || v >= max){ - return 0; - }else{ - return 1; - } -} - -std::string AclValidator::IntPropertyType::allowedValues() { - return "values should be between " + - boost::lexical_cast<std::string>(min) + " and " + - boost::lexical_cast<std::string>(max); -} - -AclValidator::EnumPropertyType::EnumPropertyType(std::vector<std::string>& allowed): values(allowed){ -} - -bool AclValidator::EnumPropertyType::validate(const std::string& val) { - for (std::vector<std::string>::iterator itr = values.begin(); itr != values.end(); ++itr ){ - if (val.compare(*itr) == 0){ - return 1; - } - } - - return 0; -} - -std::string AclValidator::EnumPropertyType::allowedValues() { - std::ostringstream oss; - oss << "possible values are one of { "; - for (std::vector<std::string>::iterator itr = values.begin(); itr != values.end(); itr++ ){ - oss << "'" << *itr << "' "; - } - oss << "}"; - return oss.str(); -} - -AclValidator::AclValidator(){ - validators.insert(Validator(acl::PROP_MAXQUEUESIZE, - boost::shared_ptr<PropertyType>( - new IntPropertyType(0,std::numeric_limits<int64_t>::max())) - ) - ); - - validators.insert(Validator(acl::PROP_MAXQUEUECOUNT, - boost::shared_ptr<PropertyType>( - new IntPropertyType(0,std::numeric_limits<int64_t>::max())) - ) - ); - - std::string policyTypes[] = {"ring", "ring_strict", "flow_to_disk", "reject"}; - std::vector<std::string> v(policyTypes, policyTypes + sizeof(policyTypes) / sizeof(std::string)); - validators.insert(Validator(acl::PROP_POLICYTYPE, - boost::shared_ptr<PropertyType>(new EnumPropertyType(v)) - ) - ); - -} - -AclValidator::~AclValidator(){ -} - -/* Iterate through the data model and validate the parameters. */ -void AclValidator::validate(boost::shared_ptr<AclData> d) { - - for (unsigned int cnt=0; cnt< qpid::acl::ACTIONSIZE; cnt++){ - - if (d->actionList[cnt]){ - - for (unsigned int cnt1=0; cnt1< qpid::acl::OBJECTSIZE; cnt1++){ - - if (d->actionList[cnt][cnt1]){ - - std::for_each(d->actionList[cnt][cnt1]->begin(), - d->actionList[cnt][cnt1]->end(), - boost::bind(&AclValidator::validateRuleSet, this, _1)); - }//if - }//for - }//if - }//for -} - -void AclValidator::validateRuleSet(std::pair<const std::string, qpid::acl::AclData::ruleSet>& rules){ - std::for_each(rules.second.begin(), - rules.second.end(), - boost::bind(&AclValidator::validateRule, this, _1)); -} - -void AclValidator::validateRule(qpid::acl::AclData::rule& rule){ - std::for_each(rule.props.begin(), - rule.props.end(), - boost::bind(&AclValidator::validateProperty, this, _1)); -} - -void AclValidator::validateProperty(std::pair<const qpid::acl::Property, std::string>& prop){ - ValidatorItr itr = validators.find(prop.first); - if (itr != validators.end()){ - QPID_LOG(debug,"Found validator for property " << itr->second->allowedValues()); - - if (!itr->second->validate(prop.second)){ - throw Exception( prop.second + " is not a valid value for '" + - AclHelper::getPropertyStr(prop.first) + "', " + - itr->second->allowedValues()); - } - } -} - -}} diff --git a/cpp/src/qpid/acl/AclValidator.h b/cpp/src/qpid/acl/AclValidator.h deleted file mode 100644 index 966e5d326b..0000000000 --- a/cpp/src/qpid/acl/AclValidator.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QPID_ACL_ACLVALIDATOR_H -#define QPID_ACL_ACLVALIDATOR_H - - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/broker/AclModule.h" -#include "qpid/acl/AclData.h" -#include "qpid/sys/IntegerTypes.h" -#include <boost/shared_ptr.hpp> -#include <vector> -#include <sstream> - -namespace qpid { -namespace acl { - -class AclValidator { - - /* Base Property */ - class PropertyType{ - - public: - virtual ~PropertyType(){}; - virtual bool validate(const std::string& val)=0; - virtual std::string allowedValues()=0; - }; - - class IntPropertyType : public PropertyType{ - int64_t min; - int64_t max; - - public: - IntPropertyType(int64_t min,int64_t max); - virtual ~IntPropertyType (){}; - virtual bool validate(const std::string& val); - virtual std::string allowedValues(); - }; - - class EnumPropertyType : public PropertyType{ - std::vector<std::string> values; - - public: - EnumPropertyType(std::vector<std::string>& allowed); - virtual ~EnumPropertyType (){}; - virtual bool validate(const std::string& val); - virtual std::string allowedValues(); - }; - - typedef std::pair<acl::Property,boost::shared_ptr<PropertyType> > Validator; - typedef std::map<acl::Property,boost::shared_ptr<PropertyType> > ValidatorMap; - typedef ValidatorMap::iterator ValidatorItr; - - ValidatorMap validators; - -public: - - void validateRuleSet(std::pair<const std::string, qpid::acl::AclData::ruleSet>& rules); - void validateRule(qpid::acl::AclData::rule& rule); - void validateProperty(std::pair<const qpid::acl::Property, std::string>& prop); - void validate(boost::shared_ptr<AclData> d); - AclValidator(); - ~AclValidator(); -}; - -}} // namespace qpid::acl - -#endif // QPID_ACL_ACLVALIDATOR_H diff --git a/cpp/src/qpid/acl/management-schema.xml b/cpp/src/qpid/acl/management-schema.xml deleted file mode 100644 index 7f48a9be34..0000000000 --- a/cpp/src/qpid/acl/management-schema.xml +++ /dev/null @@ -1,44 +0,0 @@ -<schema package="org.apache.qpid.acl"> - -<!-- - * Copyright (c) 2008 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. ---> - - <class name="Acl"> - <property name="brokerRef" type="objId" references="org.apache.qpid.broker:Broker" access="RO" index="y" parentRef="y"/> - <property name="policyFile" type="lstr" access="RO" desc="Name of the policy file"/> - <property name="enforcingAcl" type="bool" access="RO" desc="Currently Enforcing ACL"/> - <property name="transferAcl" type="bool" access="RO" desc="Any transfer ACL rules in force"/> - <property name="lastAclLoad" type="absTime" access="RO" desc="Timestamp of last successful load of ACL"/> - <statistic name="aclDenyCount" type="count64" unit="request" desc="Number of ACL requests denied"/> - - <method name="reloadACLFile" desc="Reload the ACL file"/> - </class> - - <eventArguments> - <arg name="action" type="sstr"/> - <arg name="arguments" type="map"/> - <arg name="objectName" type="sstr"/> - <arg name="objectType" type="sstr"/> - <arg name="reason" type="lstr"/> - <arg name="userId" type="sstr"/> - </eventArguments> - - <event name="allow" sev="inform" args="userId, action, objectType, objectName, arguments"/> - <event name="deny" sev="notice" args="userId, action, objectType, objectName, arguments"/> - <event name="fileLoaded" sev="inform" args="userId"/> - <event name="fileLoadFailed" sev="error" args="userId, reason"/> - -</schema> diff --git a/cpp/src/qpid/agent/ManagementAgentImpl.cpp b/cpp/src/qpid/agent/ManagementAgentImpl.cpp deleted file mode 100644 index 633401ef5b..0000000000 --- a/cpp/src/qpid/agent/ManagementAgentImpl.cpp +++ /dev/null @@ -1,1390 +0,0 @@ - -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/management/Manageable.h" -#include "qpid/management/ManagementObject.h" -#include "qpid/log/Statement.h" -#include "qpid/agent/ManagementAgentImpl.h" -#include "qpid/amqp_0_10/Codecs.h" -#include <list> -#include <string.h> -#include <stdlib.h> -#include <sys/types.h> -#include <iostream> -#include <fstream> -#include <boost/lexical_cast.hpp> - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::management; -using namespace qpid::sys; -using namespace std; -using std::stringstream; -using std::ofstream; -using std::ifstream; -using std::string; -using std::endl; -using qpid::types::Variant; -using qpid::amqp_0_10::MapCodec; -using qpid::amqp_0_10::ListCodec; - -namespace { - qpid::sys::Mutex lock; - bool disabled = false; - ManagementAgent* agent = 0; - int refCount = 0; - - const string defaultVendorName("vendor"); - const string defaultProductName("product"); - - // Create a valid binding key substring by - // replacing all '.' chars with '_' - const string keyifyNameStr(const string& name) - { - string n2 = name; - - size_t pos = n2.find('.'); - while (pos != n2.npos) { - n2.replace(pos, 1, "_"); - pos = n2.find('.', pos); - } - return n2; - } -} - -ManagementAgent::Singleton::Singleton(bool disableManagement) -{ - sys::Mutex::ScopedLock _lock(lock); - if (disableManagement && !disabled) { - disabled = true; - assert(refCount == 0); // can't disable after agent has been allocated - } - if (refCount == 0 && !disabled) - agent = new ManagementAgentImpl(); - refCount++; -} - -ManagementAgent::Singleton::~Singleton() -{ - sys::Mutex::ScopedLock _lock(lock); - refCount--; - if (refCount == 0 && !disabled) { - delete agent; - agent = 0; - } -} - -ManagementAgent* ManagementAgent::Singleton::getInstance() -{ - return agent; -} - -const string ManagementAgentImpl::storeMagicNumber("MA02"); - -ManagementAgentImpl::ManagementAgentImpl() : - interval(10), extThread(false), pipeHandle(0), notifyCallback(0), notifyContext(0), - notifyable(0), inCallback(false), - initialized(false), connected(false), useMapMsg(false), lastFailure("never connected"), - topicExchange("qmf.default.topic"), directExchange("qmf.default.direct"), - schemaTimestamp(Duration(EPOCH, now())), - publishAllData(true), requestedBrokerBank(0), requestedAgentBank(0), - assignedBrokerBank(0), assignedAgentBank(0), bootSequence(0), - maxV2ReplyObjs(10), // KAG todo: make this a tuneable parameter - connThreadBody(*this), connThread(connThreadBody), - pubThreadBody(*this), pubThread(pubThreadBody) -{ -} - -ManagementAgentImpl::~ManagementAgentImpl() -{ - // shutdown & cleanup all threads - connThreadBody.close(); - pubThreadBody.close(); - - connThread.join(); - pubThread.join(); - - if (pipeHandle) { - delete pipeHandle; - pipeHandle = 0; - } -} - -void ManagementAgentImpl::setName(const string& vendor, const string& product, const string& instance) -{ - if (vendor.find(':') != vendor.npos) { - throw Exception("vendor string cannot contain a ':' character."); - } - if (product.find(':') != product.npos) { - throw Exception("product string cannot contain a ':' character."); - } - - attrMap["_vendor"] = vendor; - attrMap["_product"] = product; - if (!instance.empty()) { - attrMap["_instance"] = instance; - } -} - - -void ManagementAgentImpl::getName(string& vendor, string& product, string& instance) -{ - vendor = std::string(attrMap["_vendor"]); - product = std::string(attrMap["_product"]); - instance = std::string(attrMap["_instance"]); -} - - -const std::string& ManagementAgentImpl::getAddress() -{ - return name_address; -} - - -void ManagementAgentImpl::init(const string& brokerHost, - uint16_t brokerPort, - uint16_t intervalSeconds, - bool useExternalThread, - const string& _storeFile, - const string& uid, - const string& pwd, - const string& mech, - const string& proto) -{ - management::ConnectionSettings settings; - settings.protocol = proto; - settings.host = brokerHost; - settings.port = brokerPort; - settings.username = uid; - settings.password = pwd; - settings.mechanism = mech; - settings.heartbeat = 10; - init(settings, intervalSeconds, useExternalThread, _storeFile); -} - -void ManagementAgentImpl::init(const qpid::management::ConnectionSettings& settings, - uint16_t intervalSeconds, - bool useExternalThread, - const string& _storeFile) -{ - std::string cfgVendor, cfgProduct, cfgInstance; - - interval = intervalSeconds; - extThread = useExternalThread; - storeFile = _storeFile; - nextObjectId = 1; - - // - // Convert from management::ConnectionSettings to client::ConnectionSettings - // - connectionSettings.protocol = settings.protocol; - connectionSettings.host = settings.host; - connectionSettings.port = settings.port; - connectionSettings.virtualhost = settings.virtualhost; - connectionSettings.username = settings.username; - connectionSettings.password = settings.password; - connectionSettings.mechanism = settings.mechanism; - connectionSettings.locale = settings.locale; - connectionSettings.heartbeat = settings.heartbeat; - connectionSettings.maxChannels = settings.maxChannels; - connectionSettings.maxFrameSize = settings.maxFrameSize; - connectionSettings.bounds = settings.bounds; - connectionSettings.tcpNoDelay = settings.tcpNoDelay; - connectionSettings.service = settings.service; - connectionSettings.minSsf = settings.minSsf; - connectionSettings.maxSsf = settings.maxSsf; - - retrieveData(cfgVendor, cfgProduct, cfgInstance); - - bootSequence++; - if ((bootSequence & 0xF000) != 0) - bootSequence = 1; - - // setup the agent's name. The name may be set via a call to setName(). If setName() - // has not been called, the name can be read from the configuration file. If there is - // no name in the configuration file, a unique default name is provided. - if (attrMap.empty()) { - // setName() never called by application, so use names retrieved from config, otherwise defaults. - setName(cfgVendor.empty() ? defaultVendorName : cfgVendor, - cfgProduct.empty() ? defaultProductName : cfgProduct, - cfgInstance.empty() ? qpid::types::Uuid(true).str() : cfgInstance); - } else if (attrMap.find("_instance") == attrMap.end()) { - // setName() called, but instance was not specified, use config or generate a uuid - setName(attrMap["_vendor"].asString(), attrMap["_product"].asString(), - cfgInstance.empty() ? qpid::types::Uuid(true).str() : cfgInstance); - } - - name_address = attrMap["_vendor"].asString() + ":" + attrMap["_product"].asString() + ":" + attrMap["_instance"].asString(); - vendorNameKey = keyifyNameStr(attrMap["_vendor"].asString()); - productNameKey = keyifyNameStr(attrMap["_product"].asString()); - instanceNameKey = keyifyNameStr(attrMap["_instance"].asString()); - attrMap["_name"] = name_address; - - storeData(true); - - QPID_LOG(info, "QMF Agent Initialized: broker=" << settings.host << ":" << settings.port << - " interval=" << intervalSeconds << " storeFile=" << _storeFile << " name=" << name_address); - - initialized = true; -} - -void ManagementAgentImpl::registerClass(const string& packageName, - const string& className, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall) -{ - sys::Mutex::ScopedLock lock(agentLock); - PackageMap::iterator pIter = findOrAddPackage(packageName); - addClassLocal(ManagementItem::CLASS_KIND_TABLE, pIter, className, md5Sum, schemaCall); -} - -void ManagementAgentImpl::registerEvent(const string& packageName, - const string& eventName, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall) -{ - sys::Mutex::ScopedLock lock(agentLock); - PackageMap::iterator pIter = findOrAddPackage(packageName); - addClassLocal(ManagementItem::CLASS_KIND_EVENT, pIter, eventName, md5Sum, schemaCall); -} - -// old-style add object: 64bit id - deprecated -ObjectId ManagementAgentImpl::addObject(ManagementObject* object, - uint64_t persistId) -{ - std::string key; - if (persistId) { - key = boost::lexical_cast<std::string>(persistId); - } - return addObject(object, key, persistId != 0); -} - - -// new style add object - use this approach! -ObjectId ManagementAgentImpl::addObject(ManagementObject* object, - const std::string& key, - bool persistent) -{ - sys::Mutex::ScopedLock lock(addLock); - - uint16_t sequence = persistent ? 0 : bootSequence; - - ObjectId objectId(&attachment, 0, sequence); - if (key.empty()) - objectId.setV2Key(*object); // let object generate the key - else - objectId.setV2Key(key); - objectId.setAgentName(name_address); - - object->setObjectId(objectId); - newManagementObjects[objectId] = boost::shared_ptr<ManagementObject>(object); - return objectId; -} - - -void ManagementAgentImpl::raiseEvent(const ManagementEvent& event, severity_t severity) -{ - static const std::string severityStr[] = { - "emerg", "alert", "crit", "error", "warn", - "note", "info", "debug" - }; - string content; - stringstream key; - Variant::Map headers; - - { - sys::Mutex::ScopedLock lock(agentLock); - Buffer outBuffer(eventBuffer, MA_BUFFER_SIZE); - uint8_t sev = (severity == SEV_DEFAULT) ? event.getSeverity() : (uint8_t) severity; - - // key << "console.event." << assignedBrokerBank << "." << assignedAgentBank << "." << - // event.getPackageName() << "." << event.getEventName(); - key << "agent.ind.event." << keyifyNameStr(event.getPackageName()) - << "." << keyifyNameStr(event.getEventName()) - << "." << severityStr[sev] - << "." << vendorNameKey - << "." << productNameKey - << "." << instanceNameKey; - - Variant::Map map_; - Variant::Map schemaId; - Variant::Map values; - - map_["_schema_id"] = mapEncodeSchemaId(event.getPackageName(), - event.getEventName(), - event.getMd5Sum(), - ManagementItem::CLASS_KIND_EVENT); - event.mapEncode(values); - map_["_values"] = values; - map_["_timestamp"] = uint64_t(Duration(EPOCH, now())); - map_["_severity"] = sev; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_event"; - headers["qmf.agent"] = name_address; - - Variant::List list; - list.push_back(map_); - ListCodec::encode(list, content); - } - - connThreadBody.sendBuffer(content, "", headers, topicExchange, key.str(), "amqp/list"); -} - -uint32_t ManagementAgentImpl::pollCallbacks(uint32_t callLimit) -{ - sys::Mutex::ScopedLock lock(agentLock); - - if (inCallback) { - QPID_LOG(critical, "pollCallbacks invoked from the agent's thread!"); - return 0; - } - - for (uint32_t idx = 0; callLimit == 0 || idx < callLimit; idx++) { - if (methodQueue.empty()) - break; - - QueuedMethod* item = methodQueue.front(); - methodQueue.pop_front(); - { - sys::Mutex::ScopedUnlock unlock(agentLock); - invokeMethodRequest(item->body, item->cid, item->replyToExchange, item->replyToKey, item->userId); - delete item; - } - } - - if (pipeHandle != 0) { - char rbuf[100]; - while (pipeHandle->read(rbuf, 100) > 0) ; // Consume all signaling bytes - } - return methodQueue.size(); -} - -int ManagementAgentImpl::getSignalFd() -{ - if (extThread) { - if (pipeHandle == 0) - pipeHandle = new PipeHandle(true); - return pipeHandle->getReadHandle(); - } - - return -1; -} - -void ManagementAgentImpl::setSignalCallback(cb_t callback, void* context) -{ - sys::Mutex::ScopedLock lock(agentLock); - notifyCallback = callback; - notifyContext = context; -} - -void ManagementAgentImpl::setSignalCallback(Notifyable& _notifyable) -{ - sys::Mutex::ScopedLock lock(agentLock); - notifyable = &_notifyable; -} - -void ManagementAgentImpl::startProtocol() -{ - sendHeartbeat(); - { - sys::Mutex::ScopedLock lock(agentLock); - publishAllData = true; - } -} - -void ManagementAgentImpl::storeData(bool requested) -{ - if (!storeFile.empty()) { - ofstream outFile(storeFile.c_str()); - uint32_t brokerBankToWrite = requested ? requestedBrokerBank : assignedBrokerBank; - uint32_t agentBankToWrite = requested ? requestedAgentBank : assignedAgentBank; - - if (outFile.good()) { - outFile << storeMagicNumber << " " << brokerBankToWrite << " " << - agentBankToWrite << " " << bootSequence << endl; - - if (attrMap.find("_vendor") != attrMap.end()) - outFile << "vendor=" << attrMap["_vendor"] << endl; - if (attrMap.find("_product") != attrMap.end()) - outFile << "product=" << attrMap["_product"] << endl; - if (attrMap.find("_instance") != attrMap.end()) - outFile << "instance=" << attrMap["_instance"] << endl; - - outFile.close(); - } - } -} - -void ManagementAgentImpl::retrieveData(std::string& vendor, std::string& product, std::string& inst) -{ - vendor.clear(); - product.clear(); - inst.clear(); - - if (!storeFile.empty()) { - ifstream inFile(storeFile.c_str()); - string mn; - - if (inFile.good()) { - inFile >> mn; - if (mn == storeMagicNumber) { - std::string inText; - - inFile >> requestedBrokerBank; - inFile >> requestedAgentBank; - inFile >> bootSequence; - - while (inFile.good()) { - std::getline(inFile, inText); - if (!inText.compare(0, 7, "vendor=")) { - vendor = inText.substr(7); - QPID_LOG(debug, "read vendor name [" << vendor << "] from configuration file."); - } else if (!inText.compare(0, 8, "product=")) { - product = inText.substr(8); - QPID_LOG(debug, "read product name [" << product << "] from configuration file."); - } else if (!inText.compare(0, 9, "instance=")) { - inst = inText.substr(9); - QPID_LOG(debug, "read instance name [" << inst << "] from configuration file."); - } - } - } - inFile.close(); - } - } -} - -void ManagementAgentImpl::sendHeartbeat() -{ - static const string addr_key_base("agent.ind.heartbeat."); - - Variant::Map map; - Variant::Map headers; - string content; - std::stringstream addr_key; - - addr_key << addr_key_base << vendorNameKey - << "." << productNameKey - << "." << instanceNameKey; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_agent_heartbeat_indication"; - headers["qmf.agent"] = name_address; - - getHeartbeatContent(map); - MapCodec::encode(map, content); - - // Set TTL (in msecs) on outgoing heartbeat indications based on the interval - // time to prevent stale heartbeats from getting to the consoles. - - connThreadBody.sendBuffer(content, "", headers, topicExchange, addr_key.str(), - "amqp/map", interval * 2 * 1000); - - QPID_LOG(trace, "SENT AgentHeartbeat name=" << name_address); -} - -void ManagementAgentImpl::sendException(const string& rte, const string& rtk, const string& cid, - const string& text, uint32_t code) -{ - Variant::Map map; - Variant::Map headers; - Variant::Map values; - string content; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_exception"; - headers["qmf.agent"] = name_address; - - values["error_code"] = code; - values["error_text"] = text; - map["_values"] = values; - - MapCodec::encode(map, content); - connThreadBody.sendBuffer(content, cid, headers, rte, rtk); - - QPID_LOG(trace, "SENT Exception code=" << code <<" text=" << text); -} - -void ManagementAgentImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence, const string& rte, const string& rtk) -{ - string packageName; - SchemaClassKey key; - uint32_t outLen(0); - char localBuffer[MA_BUFFER_SIZE]; - Buffer outBuffer(localBuffer, MA_BUFFER_SIZE); - bool found(false); - - inBuffer.getShortString(packageName); - inBuffer.getShortString(key.name); - inBuffer.getBin128(key.hash); - - QPID_LOG(trace, "RCVD SchemaRequest: package=" << packageName << " class=" << key.name); - - { - sys::Mutex::ScopedLock lock(agentLock); - PackageMap::iterator pIter = packages.find(packageName); - if (pIter != packages.end()) { - ClassMap& cMap = pIter->second; - ClassMap::iterator cIter = cMap.find(key); - if (cIter != cMap.end()) { - SchemaClass& schema = cIter->second; - string body; - - encodeHeader(outBuffer, 's', sequence); - schema.writeSchemaCall(body); - outBuffer.putRawData(body); - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - found = true; - } - } - } - - if (found) { - connThreadBody.sendBuffer(outBuffer, outLen, rte, rtk); - QPID_LOG(trace, "SENT SchemaInd: package=" << packageName << " class=" << key.name); - } -} - -void ManagementAgentImpl::handleConsoleAddedIndication() -{ - sys::Mutex::ScopedLock lock(agentLock); - publishAllData = true; - - QPID_LOG(trace, "RCVD ConsoleAddedInd"); -} - -void ManagementAgentImpl::invokeMethodRequest(const string& body, const string& cid, const string& rte, const string& rtk, const string& userId) -{ - string methodName; - bool failed = false; - Variant::Map inMap; - Variant::Map outMap; - Variant::Map::const_iterator oid, mid; - string content; - - MapCodec::decode(body, inMap); - - if ((oid = inMap.find("_object_id")) == inMap.end() || - (mid = inMap.find("_method_name")) == inMap.end()) { - sendException(rte, rtk, cid, Manageable::StatusText(Manageable::STATUS_PARAMETER_INVALID), - Manageable::STATUS_PARAMETER_INVALID); - failed = true; - } else { - string methodName; - ObjectId objId; - Variant::Map inArgs; - Variant::Map callMap; - - try { - // conversions will throw if input is invalid. - objId = ObjectId(oid->second.asMap()); - methodName = mid->second.getString(); - - mid = inMap.find("_arguments"); - if (mid != inMap.end()) { - inArgs = (mid->second).asMap(); - } - - QPID_LOG(trace, "Invoking Method: name=" << methodName << " args=" << inArgs); - - boost::shared_ptr<ManagementObject> oPtr; - { - sys::Mutex::ScopedLock lock(agentLock); - ObjectMap::iterator iter = managementObjects.find(objId); - if (iter != managementObjects.end() && !iter->second->isDeleted()) - oPtr = iter->second; - } - - if (oPtr.get() == 0) { - sendException(rte, rtk, cid, Manageable::StatusText(Manageable::STATUS_UNKNOWN_OBJECT), - Manageable::STATUS_UNKNOWN_OBJECT); - failed = true; - } else { - oPtr->doMethod(methodName, inArgs, callMap, userId); - - if (callMap["_status_code"].asUint32() == 0) { - outMap["_arguments"] = Variant::Map(); - for (Variant::Map::const_iterator iter = callMap.begin(); - iter != callMap.end(); iter++) - if (iter->first != "_status_code" && iter->first != "_status_text") - outMap["_arguments"].asMap()[iter->first] = iter->second; - } else { - sendException(rte, rtk, cid, callMap["_status_text"], callMap["_status_code"]); - failed = true; - } - } - - } catch(types::InvalidConversion& e) { - sendException(rte, rtk, cid, e.what(), Manageable::STATUS_EXCEPTION); - failed = true; - } - } - - if (!failed) { - Variant::Map headers; - headers["method"] = "response"; - headers["qmf.agent"] = name_address; - headers["qmf.opcode"] = "_method_response"; - QPID_LOG(trace, "SENT MethodResponse map=" << outMap); - MapCodec::encode(outMap, content); - connThreadBody.sendBuffer(content, cid, headers, rte, rtk); - } -} - -void ManagementAgentImpl::handleGetQuery(const string& body, const string& cid, const string& rte, const string& rtk) -{ - moveNewObjectsLH(); - - Variant::Map inMap; - Variant::Map::const_iterator i; - Variant::Map headers; - - MapCodec::decode(body, inMap); - QPID_LOG(trace, "RCVD GetQuery: map=" << inMap << " cid=" << cid); - - headers["method"] = "response"; - headers["qmf.opcode"] = "_query_response"; - headers["qmf.agent"] = name_address; - headers["partial"] = Variant(); - - Variant::List list_; - Variant::Map map_; - Variant::Map values; - Variant::Map oidMap; - string content; - - /* - * Unpack the _what element of the query. Currently we only support OBJECT queries. - */ - i = inMap.find("_what"); - if (i == inMap.end()) { - sendException(rte, rtk, cid, "_what element missing in Query"); - return; - } - - if (i->second.getType() != qpid::types::VAR_STRING) { - sendException(rte, rtk, cid, "_what element is not a string"); - return; - } - - if (i->second.asString() == "OBJECT") { - headers["qmf.content"] = "_data"; - /* - * Unpack the _object_id element of the query if it is present. If it is present, find that one - * object and return it. If it is not present, send a class-based result. - */ - i = inMap.find("_object_id"); - if (i != inMap.end() && i->second.getType() == qpid::types::VAR_MAP) { - ObjectId objId(i->second.asMap()); - boost::shared_ptr<ManagementObject> object; - - { - sys::Mutex::ScopedLock lock(agentLock); - ObjectMap::iterator iter = managementObjects.find(objId); - if (iter != managementObjects.end()) - object = iter->second; - } - - if (object.get() != 0) { - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - object->mapEncodeValues(values, true, true); // write both stats and properties - objId.mapEncode(oidMap); - map_["_values"] = values; - map_["_object_id"] = oidMap; - object->writeTimestamps(map_); - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - object->getMd5Sum()); - list_.push_back(map_); - headers.erase("partial"); - - ListCodec::encode(list_, content); - connThreadBody.sendBuffer(content, cid, headers, rte, rtk, "amqp/list"); - QPID_LOG(trace, "SENT QueryResponse (query by object_id) to=" << rte << "/" << rtk); - return; - } - } else { // match using schema_id, if supplied - - string className; - string packageName; - - i = inMap.find("_schema_id"); - if (i != inMap.end() && i->second.getType() == qpid::types::VAR_MAP) { - const Variant::Map& schemaIdMap(i->second.asMap()); - - Variant::Map::const_iterator s_iter = schemaIdMap.find("_class_name"); - if (s_iter != schemaIdMap.end() && s_iter->second.getType() == qpid::types::VAR_STRING) - className = s_iter->second.asString(); - - s_iter = schemaIdMap.find("_package_name"); - if (s_iter != schemaIdMap.end() && s_iter->second.getType() == qpid::types::VAR_STRING) - packageName = s_iter->second.asString(); - - typedef list<boost::shared_ptr<ManagementObject> > StageList; - StageList staging; - - { - sys::Mutex::ScopedLock lock(agentLock); - for (ObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - iter++) { - ManagementObject* object = iter->second.get(); - if (object->getClassName() == className && - (packageName.empty() || object->getPackageName() == packageName)) - staging.push_back(iter->second); - } - } - - unsigned int objCount = 0; - for (StageList::iterator iter = staging.begin(); iter != staging.end(); iter++) { - ManagementObject* object = iter->get(); - if (object->getClassName() == className && - (packageName.empty() || object->getPackageName() == packageName)) { - - values.clear(); - oidMap.clear(); - map_.clear(); - - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - object->mapEncodeValues(values, true, true); // write both stats and properties - object->getObjectId().mapEncode(oidMap); - map_["_values"] = values; - map_["_object_id"] = oidMap; - object->writeTimestamps(map_); - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - object->getMd5Sum()); - list_.push_back(map_); - - if (++objCount >= maxV2ReplyObjs) { - objCount = 0; - ListCodec::encode(list_, content); - connThreadBody.sendBuffer(content, cid, headers, rte, rtk, "amqp/list"); - QPID_LOG(trace, "SENT QueryResponse (query by schema_id) to=" << rte << "/" << rtk); - content.clear(); - list_.clear(); - } - } - } - } - } - - // Send last "non-partial" message to indicate CommandComplete - headers.erase("partial"); - ListCodec::encode(list_, content); - connThreadBody.sendBuffer(content, cid, headers, rte, rtk, "amqp/list"); - QPID_LOG(trace, "SENT QueryResponse (last message, no 'partial' indicator) to=" << rte << "/" << rtk); - - } else if (i->second.asString() == "SCHEMA_ID") { - headers["qmf.content"] = "_schema_id"; - /** - * @todo - support for a predicate. For now, send a list of all known schema class keys. - */ - for (PackageMap::iterator pIter = packages.begin(); - pIter != packages.end(); pIter++) { - for (ClassMap::iterator cIter = pIter->second.begin(); - cIter != pIter->second.end(); cIter++) { - - list_.push_back(mapEncodeSchemaId( pIter->first, - cIter->first.name, - cIter->first.hash, - cIter->second.kind )); - } - } - - headers.erase("partial"); - ListCodec::encode(list_, content); - connThreadBody.sendBuffer(content, cid, headers, rte, rtk, "amqp/list"); - QPID_LOG(trace, "SENT QueryResponse (SchemaId) to=" << rte << "/" << rtk); - - } else { - // Unknown query target - sendException(rte, rtk, cid, "Query for _what => '" + i->second.asString() + "' not supported"); - } -} - -void ManagementAgentImpl::handleLocateRequest(const string&, const string& cid, const string& rte, const string& rtk) -{ - QPID_LOG(trace, "RCVD AgentLocateRequest"); - - Variant::Map map; - Variant::Map headers; - string content; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_agent_locate_response"; - headers["qmf.agent"] = name_address; - - getHeartbeatContent(map); - MapCodec::encode(map, content); - connThreadBody.sendBuffer(content, cid, headers, rte, rtk); - - QPID_LOG(trace, "SENT AgentLocateResponse replyTo=" << rte << "/" << rtk); - - { - sys::Mutex::ScopedLock lock(agentLock); - publishAllData = true; - } -} - -void ManagementAgentImpl::handleMethodRequest(const string& body, const string& cid, const string& rte, const string& rtk, const string& userId) -{ - if (extThread) { - sys::Mutex::ScopedLock lock(agentLock); - - methodQueue.push_back(new QueuedMethod(cid, rte, rtk, body, userId)); - if (pipeHandle != 0) { - pipeHandle->write("X", 1); - } else if (notifyable != 0) { - inCallback = true; - { - sys::Mutex::ScopedUnlock unlock(agentLock); - notifyable->notify(); - } - inCallback = false; - } else if (notifyCallback != 0) { - inCallback = true; - { - sys::Mutex::ScopedUnlock unlock(agentLock); - notifyCallback(notifyContext); - } - inCallback = false; - } - } else { - invokeMethodRequest(body, cid, rte, rtk, userId); - } - - QPID_LOG(trace, "RCVD MethodRequest"); -} - -void ManagementAgentImpl::received(Message& msg) -{ - string replyToExchange; - string replyToKey; - framing::MessageProperties mp = msg.getMessageProperties(); - if (mp.hasReplyTo()) { - const framing::ReplyTo& rt = mp.getReplyTo(); - replyToExchange = rt.getExchange(); - replyToKey = rt.getRoutingKey(); - } - - string userId; - if (mp.hasUserId()) - userId = mp.getUserId(); - - if (mp.hasAppId() && mp.getAppId() == "qmf2") - { - string opcode = mp.getApplicationHeaders().getAsString("qmf.opcode"); - string cid = msg.getMessageProperties().getCorrelationId(); - - if (opcode == "_agent_locate_request") handleLocateRequest(msg.getData(), cid, replyToExchange, replyToKey); - else if (opcode == "_method_request") handleMethodRequest(msg.getData(), cid, replyToExchange, replyToKey, userId); - else if (opcode == "_query_request") handleGetQuery(msg.getData(), cid, replyToExchange, replyToKey); - else { - QPID_LOG(warning, "Support for QMF V2 Opcode [" << opcode << "] TBD!!!"); - } - return; - } - - // old preV2 binary messages - - uint32_t sequence; - string data = msg.getData(); - Buffer inBuffer(const_cast<char*>(data.c_str()), data.size()); - uint8_t opcode; - - - if (checkHeader(inBuffer, &opcode, &sequence)) - { - if (opcode == 'S') handleSchemaRequest(inBuffer, sequence, replyToExchange, replyToKey); - else if (opcode == 'x') handleConsoleAddedIndication(); - else - QPID_LOG(warning, "Ignoring old-format QMF Request! opcode=" << char(opcode)); - } -} - - -void ManagementAgentImpl::encodeHeader(Buffer& buf, uint8_t opcode, uint32_t seq) -{ - buf.putOctet('A'); - buf.putOctet('M'); - buf.putOctet('2'); - buf.putOctet(opcode); - buf.putLong (seq); -} - -Variant::Map ManagementAgentImpl::mapEncodeSchemaId(const string& pname, - const string& cname, - const uint8_t *md5Sum, - uint8_t type) -{ - Variant::Map map_; - - map_["_package_name"] = pname; - map_["_class_name"] = cname; - map_["_hash"] = types::Uuid(md5Sum); - if (type == ManagementItem::CLASS_KIND_EVENT) - map_["_type"] = "_event"; - else - map_["_type"] = "_data"; - - return map_; -} - - -bool ManagementAgentImpl::checkHeader(Buffer& buf, uint8_t *opcode, uint32_t *seq) -{ - if (buf.getSize() < 8) - return false; - - uint8_t h1 = buf.getOctet(); - uint8_t h2 = buf.getOctet(); - uint8_t h3 = buf.getOctet(); - - *opcode = buf.getOctet(); - *seq = buf.getLong(); - - return h1 == 'A' && h2 == 'M' && h3 == '2'; -} - -ManagementAgentImpl::PackageMap::iterator ManagementAgentImpl::findOrAddPackage(const string& name) -{ - PackageMap::iterator pIter = packages.find(name); - if (pIter != packages.end()) - return pIter; - - // No such package found, create a new map entry. - pair<PackageMap::iterator, bool> result = - packages.insert(pair<string, ClassMap>(name, ClassMap())); - - return result.first; -} - -void ManagementAgentImpl::moveNewObjectsLH() -{ - sys::Mutex::ScopedLock lock(addLock); - for (ObjectMap::iterator iter = newManagementObjects.begin(); - iter != newManagementObjects.end(); - iter++) - managementObjects[iter->first] = iter->second; - newManagementObjects.clear(); -} - -void ManagementAgentImpl::addClassLocal(uint8_t classKind, - PackageMap::iterator pIter, - const string& className, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall) -{ - SchemaClassKey key; - ClassMap& cMap = pIter->second; - - key.name = className; - memcpy(&key.hash, md5Sum, 16); - - ClassMap::iterator cIter = cMap.find(key); - if (cIter != cMap.end()) - return; - - // No such class found, create a new class with local information. - cMap.insert(pair<SchemaClassKey, SchemaClass>(key, SchemaClass(schemaCall, classKind))); - schemaTimestamp = Duration(EPOCH, now()); - QPID_LOG(trace, "Updated schema timestamp, now=" << uint64_t(schemaTimestamp)); -} - -void ManagementAgentImpl::encodePackageIndication(Buffer& buf, - PackageMap::iterator pIter) -{ - buf.putShortString((*pIter).first); - - QPID_LOG(trace, "SENT PackageInd: package=" << (*pIter).first); -} - -void ManagementAgentImpl::encodeClassIndication(Buffer& buf, - PackageMap::iterator pIter, - ClassMap::iterator cIter) -{ - SchemaClassKey key = (*cIter).first; - - buf.putOctet((*cIter).second.kind); - buf.putShortString((*pIter).first); - buf.putShortString(key.name); - buf.putBin128(key.hash); - - QPID_LOG(trace, "SENT ClassInd: package=" << (*pIter).first << " class=" << key.name); -} - -struct MessageItem { - string content; - Variant::Map headers; - string key; - MessageItem(const Variant::Map& h, const string& k) : headers(h), key(k) {} -}; - -void ManagementAgentImpl::periodicProcessing() -{ - string addr_key_base = "agent.ind.data."; - list<ObjectId> deleteList; - list<boost::shared_ptr<MessageItem> > message_list; - - sendHeartbeat(); - - { - sys::Mutex::ScopedLock lock(agentLock); - - if (!connected) - return; - - moveNewObjectsLH(); - - // - // Clear the been-here flag on all objects in the map. - // - for (ObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - iter++) { - ManagementObject* object = iter->second.get(); - object->setFlags(0); - if (publishAllData) { - object->setForcePublish(true); - } - } - - publishAllData = false; - - // - // Process the entire object map. - // - uint32_t v2Objs = 0; - - for (ObjectMap::iterator baseIter = managementObjects.begin(); - baseIter != managementObjects.end(); - baseIter++) { - ManagementObject* baseObject = baseIter->second.get(); - - // - // Skip until we find a base object requiring a sent message. - // - if (baseObject->getFlags() == 1 || - (!baseObject->getConfigChanged() && - !baseObject->getInstChanged() && - !baseObject->getForcePublish() && - !baseObject->isDeleted())) - continue; - - std::string packageName = baseObject->getPackageName(); - std::string className = baseObject->getClassName(); - - Variant::List list_; - std::stringstream addr_key; - Variant::Map headers; - - addr_key << addr_key_base; - addr_key << keyifyNameStr(packageName) - << "." << keyifyNameStr(className) - << "." << vendorNameKey - << "." << productNameKey - << "." << instanceNameKey; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = name_address; - - for (ObjectMap::iterator iter = baseIter; - iter != managementObjects.end(); - iter++) { - ManagementObject* object = iter->second.get(); - bool send_stats, send_props; - if (baseObject->isSameClass(*object) && object->getFlags() == 0) { - object->setFlags(1); - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - send_props = (object->getConfigChanged() || object->getForcePublish() || object->isDeleted()); - send_stats = (object->hasInst() && (object->getInstChanged() || object->getForcePublish())); - - if (send_stats || send_props) { - Variant::Map map_; - Variant::Map values; - Variant::Map oid; - - object->getObjectId().mapEncode(oid); - map_["_object_id"] = oid; - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - object->getMd5Sum()); - object->writeTimestamps(map_); - object->mapEncodeValues(values, send_props, send_stats); - map_["_values"] = values; - list_.push_back(map_); - - if (++v2Objs >= maxV2ReplyObjs) { - v2Objs = 0; - boost::shared_ptr<MessageItem> item(new MessageItem(headers, addr_key.str())); - ListCodec::encode(list_, item->content); - message_list.push_back(item); - list_.clear(); - } - } - - if (object->isDeleted()) - deleteList.push_back(iter->first); - object->setForcePublish(false); - } - } - - if (!list_.empty()) { - boost::shared_ptr<MessageItem> item(new MessageItem(headers, addr_key.str())); - ListCodec::encode(list_, item->content); - message_list.push_back(item); - } - } - - // Delete flagged objects - for (list<ObjectId>::reverse_iterator iter = deleteList.rbegin(); - iter != deleteList.rend(); - iter++) - managementObjects.erase(*iter); - } - - while (!message_list.empty()) { - boost::shared_ptr<MessageItem> item(message_list.front()); - message_list.pop_front(); - connThreadBody.sendBuffer(item->content, "", item->headers, topicExchange, item->key, "amqp/list"); - QPID_LOG(trace, "SENT DataIndication"); - } -} - - -void ManagementAgentImpl::getHeartbeatContent(qpid::types::Variant::Map& map) -{ - map["_values"] = attrMap; - map["_values"].asMap()["_timestamp"] = uint64_t(Duration(EPOCH, now())); - map["_values"].asMap()["_heartbeat_interval"] = interval; - map["_values"].asMap()["_epoch"] = bootSequence; - map["_values"].asMap()["_schema_updated"] = uint64_t(schemaTimestamp); -} - -void ManagementAgentImpl::ConnectionThread::run() -{ - static const int delayMin(1); - static const int delayMax(128); - static const int delayFactor(2); - int delay(delayMin); - string dest("qmfagent"); - ConnectionThread::shared_ptr tmp; - - sessionId.generate(); - queueName << "qmfagent-" << sessionId; - - while (true) { - try { - if (agent.initialized) { - QPID_LOG(debug, "QMF Agent attempting to connect to the broker..."); - connection.open(agent.connectionSettings); - session = connection.newSession(queueName.str()); - subscriptions.reset(new client::SubscriptionManager(session)); - - session.queueDeclare(arg::queue=queueName.str(), arg::autoDelete=true, - arg::exclusive=true); - session.exchangeBind(arg::exchange="amq.direct", arg::queue=queueName.str(), - arg::bindingKey=queueName.str()); - session.exchangeBind(arg::exchange=agent.directExchange, arg::queue=queueName.str(), - arg::bindingKey=agent.name_address); - session.exchangeBind(arg::exchange=agent.topicExchange, arg::queue=queueName.str(), - arg::bindingKey="console.#"); - - subscriptions->subscribe(agent, queueName.str(), dest); - QPID_LOG(info, "Connection established with broker"); - { - sys::Mutex::ScopedLock _lock(connLock); - if (shutdown) - return; - operational = true; - agent.connected = true; - agent.startProtocol(); - try { - sys::Mutex::ScopedUnlock _unlock(connLock); - subscriptions->run(); - } catch (exception) {} - - QPID_LOG(warning, "Connection to the broker has been lost"); - - operational = false; - agent.connected = false; - tmp = subscriptions; - subscriptions.reset(); - } - tmp.reset(); // frees the subscription outside the lock - delay = delayMin; - connection.close(); - } - } catch (exception &e) { - if (delay < delayMax) - delay *= delayFactor; - QPID_LOG(debug, "Connection failed: exception=" << e.what()); - } - - { - // sleep for "delay" seconds, but peridically check if the - // agent is shutting down so we don't hang for up to delayMax - // seconds during agent shutdown - sys::Mutex::ScopedLock _lock(connLock); - if (shutdown) - return; - sleeping = true; - int totalSleep = 0; - do { - sys::Mutex::ScopedUnlock _unlock(connLock); - ::sleep(delayMin); - totalSleep += delayMin; - } while (totalSleep < delay && !shutdown); - sleeping = false; - if (shutdown) - return; - } - } -} - -ManagementAgentImpl::ConnectionThread::~ConnectionThread() -{ -} - -void ManagementAgentImpl::ConnectionThread::sendBuffer(Buffer& buf, - uint32_t length, - const string& exchange, - const string& routingKey) -{ - Message msg; - string data; - - buf.getRawData(data, length); - msg.setData(data); - sendMessage(msg, exchange, routingKey); -} - - - -void ManagementAgentImpl::ConnectionThread::sendBuffer(const string& data, - const string& cid, - const Variant::Map headers, - const string& exchange, - const string& routingKey, - const string& contentType, - uint64_t ttl_msec) -{ - Message msg; - Variant::Map::const_iterator i; - - if (!cid.empty()) - msg.getMessageProperties().setCorrelationId(cid); - - if (!contentType.empty()) - msg.getMessageProperties().setContentType(contentType); - - if (ttl_msec) - msg.getDeliveryProperties().setTtl(ttl_msec); - - for (i = headers.begin(); i != headers.end(); ++i) { - msg.getHeaders().setString(i->first, i->second.asString()); - } - - msg.setData(data); - sendMessage(msg, exchange, routingKey); -} - - - - - -void ManagementAgentImpl::ConnectionThread::sendMessage(Message msg, - const string& exchange, - const string& routingKey) -{ - ConnectionThread::shared_ptr s; - { - sys::Mutex::ScopedLock _lock(connLock); - if (!operational) - return; - s = subscriptions; - } - - msg.getDeliveryProperties().setRoutingKey(routingKey); - msg.getMessageProperties().setReplyTo(ReplyTo("amq.direct", queueName.str())); - msg.getMessageProperties().getApplicationHeaders().setString("qmf.agent", agent.name_address); - msg.getMessageProperties().setAppId("qmf2"); - try { - session.messageTransfer(arg::content=msg, arg::destination=exchange); - } catch(exception& e) { - QPID_LOG(error, "Exception caught in sendMessage: " << e.what()); - // Bounce the connection - if (s) - s->stop(); - } -} - - - -void ManagementAgentImpl::ConnectionThread::bindToBank(uint32_t brokerBank, uint32_t agentBank) -{ - stringstream key; - key << "agent." << brokerBank << "." << agentBank; - session.exchangeBind(arg::exchange="qpid.management", arg::queue=queueName.str(), - arg::bindingKey=key.str()); -} - -void ManagementAgentImpl::ConnectionThread::close() -{ - ConnectionThread::shared_ptr s; - { - sys::Mutex::ScopedLock _lock(connLock); - shutdown = true; - s = subscriptions; - } - if (s) - s->stop(); -} - -bool ManagementAgentImpl::ConnectionThread::isSleeping() const -{ - sys::Mutex::ScopedLock _lock(connLock); - return sleeping; -} - - -void ManagementAgentImpl::PublishThread::run() -{ - uint16_t totalSleep; - - while (!shutdown) { - agent.periodicProcessing(); - totalSleep = 0; - while (totalSleep++ < agent.getInterval() && !shutdown) { - ::sleep(1); - } - } -} diff --git a/cpp/src/qpid/agent/ManagementAgentImpl.h b/cpp/src/qpid/agent/ManagementAgentImpl.h deleted file mode 100644 index bf340777d1..0000000000 --- a/cpp/src/qpid/agent/ManagementAgentImpl.h +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef _qpid_agent_ManagementAgentImpl_ -#define _qpid_agent_ManagementAgentImpl_ - -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/agent/ManagementAgent.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/Session.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/Message.h" -#include "qpid/client/MessageListener.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/PipeHandle.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/Uuid.h" -#include <iostream> -#include <sstream> -#include <deque> - -namespace qpid { -namespace management { - -class ManagementAgentImpl : public ManagementAgent, public client::MessageListener -{ - public: - - ManagementAgentImpl(); - virtual ~ManagementAgentImpl(); - - // - // Methods from ManagementAgent - // - int getMaxThreads() { return 1; } - void setName(const std::string& vendor, - const std::string& product, - const std::string& instance=""); - void getName(std::string& vendor, std::string& product, std::string& instance); - const std::string& getAddress(); - void init(const std::string& brokerHost = "localhost", - uint16_t brokerPort = 5672, - uint16_t intervalSeconds = 10, - bool useExternalThread = false, - const std::string& storeFile = "", - const std::string& uid = "guest", - const std::string& pwd = "guest", - const std::string& mech = "PLAIN", - const std::string& proto = "tcp"); - void init(const management::ConnectionSettings& settings, - uint16_t intervalSeconds = 10, - bool useExternalThread = false, - const std::string& storeFile = ""); - bool isConnected() { return connected; } - std::string& getLastFailure() { return lastFailure; } - void registerClass(const std::string& packageName, - const std::string& className, - uint8_t* md5Sum, - management::ManagementObject::writeSchemaCall_t schemaCall); - void registerEvent(const std::string& packageName, - const std::string& eventName, - uint8_t* md5Sum, - management::ManagementObject::writeSchemaCall_t schemaCall); - ObjectId addObject(management::ManagementObject* objectPtr, uint64_t persistId = 0); - ObjectId addObject(management::ManagementObject* objectPtr, const std::string& key, - bool persistent); - void raiseEvent(const management::ManagementEvent& event, severity_t severity = SEV_DEFAULT); - uint32_t pollCallbacks(uint32_t callLimit = 0); - int getSignalFd(); - void setSignalCallback(cb_t callback, void* context); - void setSignalCallback(Notifyable& n); - - uint16_t getInterval() { return interval; } - void periodicProcessing(); - - // these next are here to support the hot-wiring of state between clustered brokers - uint64_t getNextObjectId(void) { return nextObjectId; } - void setNextObjectId(uint64_t o) { nextObjectId = o; } - - uint16_t getBootSequence(void) { return bootSequence; } - void setBootSequence(uint16_t b) { bootSequence = b; } - - private: - - struct SchemaClassKey { - std::string name; - uint8_t hash[16]; - }; - - struct SchemaClassKeyComp { - bool operator() (const SchemaClassKey& lhs, const SchemaClassKey& rhs) const - { - if (lhs.name != rhs.name) - return lhs.name < rhs.name; - else - for (int i = 0; i < 16; i++) - if (lhs.hash[i] != rhs.hash[i]) - return lhs.hash[i] < rhs.hash[i]; - return false; - } - }; - - struct SchemaClass { - management::ManagementObject::writeSchemaCall_t writeSchemaCall; - uint8_t kind; - - SchemaClass(const management::ManagementObject::writeSchemaCall_t call, - const uint8_t _kind) : writeSchemaCall(call), kind(_kind) {} - }; - - struct QueuedMethod { - QueuedMethod(const std::string& _cid, const std::string& _rte, const std::string& _rtk, const std::string& _body, const std::string& _uid) : - cid(_cid), replyToExchange(_rte), replyToKey(_rtk), body(_body), userId(_uid) {} - - std::string cid; - std::string replyToExchange; - std::string replyToKey; - std::string body; - std::string userId; - }; - - typedef std::deque<QueuedMethod*> MethodQueue; - typedef std::map<SchemaClassKey, SchemaClass, SchemaClassKeyComp> ClassMap; - typedef std::map<std::string, ClassMap> PackageMap; - - PackageMap packages; - AgentAttachment attachment; - - typedef std::map<ObjectId, boost::shared_ptr<ManagementObject> > ObjectMap; - - ObjectMap managementObjects; - ObjectMap newManagementObjects; - MethodQueue methodQueue; - - void received (client::Message& msg); - - qpid::types::Variant::Map attrMap; - std::string name_address; - std::string vendorNameKey; // vendor name with "." --> "_" - std::string productNameKey; // product name with "." --> "_" - std::string instanceNameKey; // agent instance with "." --> "_" - uint16_t interval; - bool extThread; - sys::PipeHandle* pipeHandle; - uint64_t nextObjectId; - cb_t notifyCallback; - void* notifyContext; - Notifyable* notifyable; - bool inCallback; - std::string storeFile; - sys::Mutex agentLock; - sys::Mutex addLock; - framing::Uuid systemId; - client::ConnectionSettings connectionSettings; - bool initialized; - bool connected; - bool useMapMsg; - std::string lastFailure; - std::string topicExchange; - std::string directExchange; - qpid::sys::Duration schemaTimestamp; - - bool publishAllData; - uint32_t requestedBrokerBank; - uint32_t requestedAgentBank; - uint32_t assignedBrokerBank; - uint32_t assignedAgentBank; - uint16_t bootSequence; - - // Maximum # of objects allowed in a single V2 response - // message. - uint32_t maxV2ReplyObjs; - - static const uint8_t DEBUG_OFF = 0; - static const uint8_t DEBUG_CONN = 1; - static const uint8_t DEBUG_PROTO = 2; - static const uint8_t DEBUG_PUBLISH = 3; - -# define MA_BUFFER_SIZE 65536 - char outputBuffer[MA_BUFFER_SIZE]; - char eventBuffer[MA_BUFFER_SIZE]; - - friend class ConnectionThread; - class ConnectionThread : public sys::Runnable - { - typedef boost::shared_ptr<client::SubscriptionManager> shared_ptr; - - bool operational; - ManagementAgentImpl& agent; - framing::Uuid sessionId; - client::Connection connection; - client::Session session; - ConnectionThread::shared_ptr subscriptions; - std::stringstream queueName; - mutable sys::Mutex connLock; - bool shutdown; - bool sleeping; - void run(); - public: - ConnectionThread(ManagementAgentImpl& _agent) : - operational(false), agent(_agent), - shutdown(false), sleeping(false) {} - ~ConnectionThread(); - void sendBuffer(qpid::framing::Buffer& buf, - uint32_t length, - const std::string& exchange, - const std::string& routingKey); - void sendBuffer(const std::string& data, - const std::string& cid, - const qpid::types::Variant::Map headers, - const std::string& exchange, - const std::string& routingKey, - const std::string& contentType="amqp/map", - uint64_t ttl_msec=0); - void sendMessage(qpid::client::Message msg, - const std::string& exchange, - const std::string& routingKey); - void bindToBank(uint32_t brokerBank, uint32_t agentBank); - void close(); - bool isSleeping() const; - }; - - class PublishThread : public sys::Runnable - { - ManagementAgentImpl& agent; - void run(); - bool shutdown; - public: - PublishThread(ManagementAgentImpl& _agent) : - agent(_agent), shutdown(false) {} - void close() { shutdown = true; } - }; - - ConnectionThread connThreadBody; - sys::Thread connThread; - PublishThread pubThreadBody; - sys::Thread pubThread; - - static const std::string storeMagicNumber; - - void startProtocol(); - void storeData(bool requested=false); - void retrieveData(std::string& vendor, std::string& product, std::string& inst); - PackageMap::iterator findOrAddPackage(const std::string& name); - void moveNewObjectsLH(); - void addClassLocal (uint8_t classKind, - PackageMap::iterator pIter, - const std::string& className, - uint8_t* md5Sum, - management::ManagementObject::writeSchemaCall_t schemaCall); - void encodePackageIndication (framing::Buffer& buf, - PackageMap::iterator pIter); - void encodeClassIndication (framing::Buffer& buf, - PackageMap::iterator pIter, - ClassMap::iterator cIter); - void encodeHeader (framing::Buffer& buf, uint8_t opcode, uint32_t seq = 0); - qpid::types::Variant::Map mapEncodeSchemaId(const std::string& pname, - const std::string& cname, - const uint8_t *md5Sum, - uint8_t type=ManagementItem::CLASS_KIND_TABLE); - bool checkHeader (framing::Buffer& buf, uint8_t *opcode, uint32_t *seq); - void sendHeartbeat(); - void sendException(const std::string& replyToExchange, const std::string& replyToKey, const std::string& cid, - const std::string& text, uint32_t code=1); - void handlePackageRequest (qpid::framing::Buffer& inBuffer); - void handleClassQuery (qpid::framing::Buffer& inBuffer); - void handleSchemaRequest (qpid::framing::Buffer& inBuffer, uint32_t sequence, const std::string& rte, const std::string& rtk); - void invokeMethodRequest (const std::string& body, const std::string& cid, const std::string& rte, const std::string& rtk, const std::string& userId); - - void handleGetQuery (const std::string& body, const std::string& cid, const std::string& rte, const std::string& rtk); - void handleLocateRequest (const std::string& body, const std::string& sequence, const std::string& rte, const std::string& rtk); - void handleMethodRequest (const std::string& body, const std::string& sequence, const std::string& rte, const std::string& rtk, const std::string& userId); - void handleConsoleAddedIndication(); - void getHeartbeatContent (qpid::types::Variant::Map& map); -}; - -}} - -#endif /*!_qpid_agent_ManagementAgentImpl_*/ diff --git a/cpp/src/qpid/amqp_0_10/Array.cpp b/cpp/src/qpid/amqp_0_10/Array.cpp deleted file mode 100644 index 2ee47546f2..0000000000 --- a/cpp/src/qpid/amqp_0_10/Array.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/Array.h" - -namespace qpid { -namespace amqp_0_10 { - -std::ostream& operator<<(std::ostream& o, const Array& a) { - std::ostream_iterator<UnknownType> i(o, " "); - o << "Array<" << typeName(a.getType()) << "["; - std::copy(a.begin(), a.end(), i); - o << "]"; - return o; -} - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Array.h b/cpp/src/qpid/amqp_0_10/Array.h deleted file mode 100644 index 6e8a419df7..0000000000 --- a/cpp/src/qpid/amqp_0_10/Array.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef QPID_AMQP_0_10_ARRAY_H -#define QPID_AMQP_0_10_ARRAY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/TypeForCode.h" -#include "qpid/amqp_0_10/CodeForType.h" -#include "qpid/amqp_0_10/UnknownType.h" -#include "qpid/amqp_0_10/exceptions.h" -#include "qpid/amqp_0_10/Codec.h" -#include <vector> -#include <ostream> - -namespace qpid { -namespace amqp_0_10 { - -template <class T> class ArrayDomain : public std::vector<T> { - public: - template <class S> void serialize(S& s) { s.split(*this); } - - template <class S> void encode(S& s) const { - s(contentSize())(CodeForType<T>::value)(uint32_t(this->size())); - s(this->begin(), this->end()); - } - - void encode(Codec::Size& s) const { s.raw(0, contentSize() + 4/*size*/); } - - template <class S> void decode(S& s) { - uint32_t size; uint8_t type; uint32_t count; - s(size); - typename S::ScopedLimit l(s, size); - s(type); - if (type != CodeForType<T>::value) - throw InvalidArgumentException(QPID_MSG("Array domain expected type " << CodeForType<T>::value << " but found " << type)); - s(count); - this->resize(count); - s(this->begin(), this->end()); - } - - private: - uint32_t contentSize() const { - return Codec::size(this->begin(), this->end()) + sizeof(uint32_t) /*count*/ + sizeof(uint8_t) /*type*/; - } -}; - -template <class T> -std::ostream& operator<<(std::ostream& o, const ArrayDomain<T>& ad) { - std::ostream_iterator<T> i(o, " "); - o << "Array<" << typeName(CodeForType<T>::value) << ">["; - std::copy(ad.begin(), ad.end(), i); - o << "]"; - return o; -} - -/** A non-domain array is represented as and array of UnknownType. - * Special case templat. - */ -template<> class ArrayDomain<UnknownType> : public std::vector<UnknownType> { - public: - ArrayDomain(uint8_t type_=0) : type(type_) {} - - template <class S> void serialize(S& s) { s.split(*this); } - - template <class S> void encode(S& s) const { - s(contentSize())(type)(uint32_t(this->size())); - s(this->begin(), this->end()); - } - - void encode(Codec::Size& s) const { s.raw(0, contentSize() + 4/*size*/); } - - template <class S> void decode(S& s) { - uint32_t size; uint32_t count; - s(size); - typename S::ScopedLimit l(s, size); - s(type)(count); - this->clear(); - this->resize(count, UnknownType(type)); - s(this->begin(), this->end()); - } - - uint8_t getType() const { return type; } - - private: - uint32_t contentSize() const { - return Codec::size(this->begin(), this->end()) + sizeof(uint32_t) /*count*/ + sizeof(uint8_t) /*type*/; - } - uint8_t type; -}; - -std::ostream& operator<<(std::ostream& o, const Array& a); - -// FIXME aconway 2008-04-08: hack to supress encoding of -// command-fragments and in-doubt as there is a problem with the spec -// (command-fragments does not have a one byte type code.) -namespace session { class CommandFragment; } -namespace dtx { class Xid; } - -template <> struct ArrayDomain<session::CommandFragment> : public Void {}; -template <> struct ArrayDomain<dtx::Xid> : public Void {}; -inline std::ostream& operator<<(std::ostream& o, const ArrayDomain<session::CommandFragment>&) { return o; } -inline std::ostream& operator<<(std::ostream& o, const ArrayDomain<dtx::Xid>&) { return o; } - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_ARRAY_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Body.h b/cpp/src/qpid/amqp_0_10/Body.h deleted file mode 100644 index c96931551c..0000000000 --- a/cpp/src/qpid/amqp_0_10/Body.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef QPID_AMQP_0_10_BODY_H -#define QPID_AMQP_0_10_BODY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include <ostream> - -namespace qpid { -namespace amqp_0_10 { - -/** Holds data from a body frame. */ -class Body { - public: - Body() {} - Body(size_t size_) : str(size_, '\0') {} - Body(const char* data_, size_t size_) : str(data_, size_) {} - - size_t size() const { return str.size(); }; - const char* data() const { return str.data(); } - char* data() { return const_cast<char*>(str.data()); } - - template <class S> void serialize(S& s) { s.raw(data(), size()); } - - private: - std::string str; - - friend std::ostream& operator<<(std::ostream&, const Body&); -}; - -inline std::ostream& operator<<(std::ostream& o, const Body& b) { - return o << b.str.substr(0, 16) << "... (" << b.size() << ")"; -} - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_BODY_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Codec.h b/cpp/src/qpid/amqp_0_10/Codec.h deleted file mode 100644 index fd006a348e..0000000000 --- a/cpp/src/qpid/amqp_0_10/Codec.h +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef QPID_AMQP_0_10_CODEC_H -#define QPID_AMQP_0_10_CODEC_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/built_in_types.h" -#include "qpid/Serializer.h" -#include <boost/type_traits/is_integral.hpp> -#include <boost/type_traits/is_float.hpp> -#include <boost/type_traits/is_arithmetic.hpp> -#include <boost/detail/endian.hpp> -#include <boost/static_assert.hpp> -#include <iterator> - -namespace qpid { -namespace amqp_0_10 { - -template <class T> void reverse(T& t) { - char*p =reinterpret_cast<char*>(&t); - std::reverse(p, p+sizeof(T)); -} - -#ifdef BOOST_LITTLE_ENDIAN -template <class T> void bigEndian(T& t) { reverse(t); } -template <class T> void littleEndian(T&) {} -#else -template <class T> void littleEndian(T& t) { reverse(t); } -template <class T> void bigEndian(T&) {} -#endif - -/** - * AMQP 0-10 encoding and decoding. - */ -struct Codec { - /** Encode to an output byte iterator */ - template <class OutIter> - class Encoder : public EncoderBase<Encoder<OutIter> > - { - public: - typedef EncoderBase<Encoder<OutIter> > Base; - typedef OutIter Iterator; - - Encoder(OutIter o, size_t limit=Base::maxLimit()) : out(o) { - this->setLimit(limit); - } - - using EncoderBase<Encoder<OutIter> >::operator(); - - Encoder& operator()(bool x) { raw(x); return *this;} - Encoder& operator()(char x) { raw(x); return *this; } - Encoder& operator()(int8_t x) { raw(x); return *this; } - Encoder& operator()(uint8_t x) { raw(x); return *this; } - - Encoder& operator()(int16_t x) { return networkByteOrder(x); } - Encoder& operator()(int32_t x) { return networkByteOrder(x); } - Encoder& operator()(int64_t x) { return networkByteOrder(x); } - - Encoder& operator()(uint16_t x) { return networkByteOrder(x); } - Encoder& operator()(uint32_t x) { return networkByteOrder(x); } - Encoder& operator()(uint64_t x) { return networkByteOrder(x); } - - Encoder& operator()(float x) { return networkByteOrder(x); } - Encoder& operator()(double x) { return networkByteOrder(x); } - - void raw(const void* p, size_t n) { - this->addBytes(n); - out = std::copy((const char*)p, (const char*)p+n, out); - } - - void raw(char b) { this->addBytes(1); *out++=b; } - - template <class T> Encoder& littleEnd(T x) { - littleEndian(x); raw(&x, sizeof(x)); return *this; - } - - OutIter pos() const { return out; } - - private: - - template <class T> Encoder& networkByteOrder(T x) { - bigEndian(x); raw(&x, sizeof(x)); return *this; - } - - OutIter out; - }; - - template <class InIter> - class Decoder : public DecoderBase<Decoder<InIter> > { - public: - typedef DecoderBase<Decoder<InIter> > Base; - typedef InIter Iterator; - - Decoder(InIter i, size_t limit=Base::maxLimit()) : in(i) { - this->setLimit(limit); - } - - using DecoderBase<Decoder<InIter> >::operator(); - - // FIXME aconway 2008-03-10: wrong encoding, need packing support - Decoder& operator()(bool& x) { raw((char&)x); return *this; } - - Decoder& operator()(char& x) { raw((char&)x); return *this; } - Decoder& operator()(int8_t& x) { raw((char&)x); return *this; } - Decoder& operator()(uint8_t& x) { raw((char&)x); return *this; } - - Decoder& operator()(int16_t& x) { return networkByteOrder(x); } - Decoder& operator()(int32_t& x) { return networkByteOrder(x); } - Decoder& operator()(int64_t& x) { return networkByteOrder(x); } - - Decoder& operator()(uint16_t& x) { return networkByteOrder(x); } - Decoder& operator()(uint32_t& x) { return networkByteOrder(x); } - Decoder& operator()(uint64_t& x) { return networkByteOrder(x); } - - Decoder& operator()(float& x) { return networkByteOrder(x); } - Decoder& operator()(double& x) { return networkByteOrder(x); } - - void raw(void *p, size_t n) { - this->addBytes(n); - std::copy(in, in+n, (char*)p); - std::advance(in, n); - } - - void raw(char &b) { this->addBytes(1); b=*in++; } - - template <class T> Decoder& littleEnd(T& x) { - raw(&x, sizeof(x)); littleEndian(x); return *this; - } - - InIter pos() const { return in; } - - private: - - template <class T> Decoder& networkByteOrder(T& x) { - raw(&x, sizeof(x)); bigEndian(x); return *this; - } - - InIter in; - }; - - - class Size : public EncoderBase<Size> { - public: - Size() : size(0) {} - - operator size_t() const { return size; } - - using EncoderBase<Size>::operator(); - - // FIXME aconway 2008-03-10: wrong encoding, need packing support - Size& operator()(bool x) { size += sizeof(x); return *this; } - - Size& operator()(char x) { size += sizeof(x); return *this; } - Size& operator()(int8_t x) { size += sizeof(x); return *this; } - Size& operator()(uint8_t x) { size += sizeof(x); return *this; } - - Size& operator()(int16_t x) { size += sizeof(x); return *this; } - Size& operator()(int32_t x) { size += sizeof(x); return *this; } - Size& operator()(int64_t x) { size += sizeof(x); return *this; } - - Size& operator()(uint16_t x) { size += sizeof(x); return *this; } - Size& operator()(uint32_t x) { size += sizeof(x); return *this; } - Size& operator()(uint64_t x) { size += sizeof(x); return *this; } - - Size& operator()(float x) { size += sizeof(x); return *this; } - Size& operator()(double x) { size += sizeof(x); return *this; } - - // FIXME aconway 2008-04-03: optimize op()(Iter,Iter) - // for Iter with fixed-size value_type: - // distance(begin,end)*sizeof(value_type) - - void raw(const void*, size_t n){ size += n; } - - template <class T> Size& littleEnd(T) { size+= sizeof(T); return *this; } - - private: - size_t size; - }; - - // FIXME aconway 2008-03-11: rename to encoder(), decoder() - template <class InIter> static Decoder<InIter> decode(const InIter &i) { - return Decoder<InIter>(i); - } - - template <class OutIter> static Encoder<OutIter> encode(OutIter i) { - return Encoder<OutIter>(i); - } - - template <class T> static size_t size(const T& x) { return Size()(x); } - template <class Iter> static size_t size(const Iter& a, const Iter& z) { return Size()(a,z); } -}; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_CODEC_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Codecs.cpp b/cpp/src/qpid/amqp_0_10/Codecs.cpp deleted file mode 100644 index b976a5d09b..0000000000 --- a/cpp/src/qpid/amqp_0_10/Codecs.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/List.h" -#include "qpid/log/Statement.h" -#include <algorithm> -#include <functional> -#include <limits> - -using namespace qpid::framing; -using namespace qpid::types; - -namespace qpid { -namespace amqp_0_10 { - -namespace { -const std::string iso885915("iso-8859-15"); -const std::string utf8("utf8"); -const std::string utf16("utf16"); -const std::string binary("binary"); -const std::string amqp0_10_binary("amqp0-10:binary"); -const std::string amqp0_10_bit("amqp0-10:bit"); -const std::string amqp0_10_datetime("amqp0-10:datetime"); -const std::string amqp0_10_struct("amqp0-10:struct"); -} - -template <class T, class U, class F> void convert(const T& from, U& to, F f) -{ - std::transform(from.begin(), from.end(), std::inserter(to, to.begin()), f); -} - -Variant::Map::value_type toVariantMapEntry(const FieldTable::value_type& in); -FieldTable::value_type toFieldTableEntry(const Variant::Map::value_type& in); -Variant toVariant(boost::shared_ptr<FieldValue> in); -boost::shared_ptr<FieldValue> toFieldValue(const Variant& in); - -template <class T, class U, class F> void translate(boost::shared_ptr<FieldValue> in, U& u, F f) -{ - T t; - getEncodedValue<T>(in, t); - convert(t, u, f); -} - -template <class T, class U, class F> T* toFieldValueCollection(const U& u, F f) -{ - typename T::ValueType t; - convert(u, t, f); - return new T(t); -} - -FieldTableValue* toFieldTableValue(const Variant::Map& map) -{ - FieldTable ft; - convert(map, ft, &toFieldTableEntry); - return new FieldTableValue(ft); -} - -ListValue* toListValue(const Variant::List& list) -{ - List l; - convert(list, l, &toFieldValue); - return new ListValue(l); -} - -void setEncodingFor(Variant& out, uint8_t code) -{ - switch(code){ - case 0x80: - case 0x90: - case 0xa0: - out.setEncoding(amqp0_10_binary); - break; - case 0x84: - case 0x94: - out.setEncoding(iso885915); - break; - case 0x85: - case 0x95: - out.setEncoding(utf8); - break; - case 0x86: - case 0x96: - out.setEncoding(utf16); - break; - case 0xab: - out.setEncoding(amqp0_10_struct); - break; - default: - //do nothing - break; - } -} - -qpid::types::Uuid getUuid(FieldValue& value) -{ - unsigned char data[16]; - value.getFixedWidthValue<16>(data); - return qpid::types::Uuid(data); -} - -Variant toVariant(boost::shared_ptr<FieldValue> in) -{ - Variant out; - //based on AMQP 0-10 typecode, pick most appropriate variant type - switch (in->getType()) { - //Fixed Width types: - case 0x01: out.setEncoding(amqp0_10_binary); - case 0x02: out = in->getIntegerValue<int8_t>(); break; - case 0x03: out = in->getIntegerValue<uint8_t>(); break; - case 0x04: break; //TODO: iso-8859-15 char - case 0x08: out = static_cast<bool>(in->getIntegerValue<uint8_t>()); break; - case 0x10: out.setEncoding(amqp0_10_binary); - case 0x11: out = in->getIntegerValue<int16_t, 2>(); break; - case 0x12: out = in->getIntegerValue<uint16_t, 2>(); break; - case 0x20: out.setEncoding(amqp0_10_binary); - case 0x21: out = in->getIntegerValue<int32_t, 4>(); break; - case 0x22: out = in->getIntegerValue<uint32_t, 4>(); break; - case 0x23: out = in->get<float>(); break; - case 0x27: break; //TODO: utf-32 char - case 0x30: out.setEncoding(amqp0_10_binary); - case 0x31: out = in->getIntegerValue<int64_t, 8>(); break; - case 0x38: out.setEncoding(amqp0_10_datetime); //treat datetime as uint64_t, but set encoding - case 0x32: out = in->getIntegerValue<uint64_t, 8>(); break; - case 0x33: out = in->get<double>(); break; - - case 0x48: out = getUuid(*in); break; - - //TODO: figure out whether and how to map values with codes 0x40-0xd8 - - case 0xf0: break;//void, which is the default value for Variant - case 0xf1: out.setEncoding(amqp0_10_bit); break;//treat 'bit' as void, which is the default value for Variant - - //Variable Width types: - //strings: - case 0x80: - case 0x84: - case 0x85: - case 0x86: - case 0x90: - case 0x94: - case 0x95: - case 0x96: - case 0xa0: - case 0xab: - out = in->get<std::string>(); - setEncodingFor(out, in->getType()); - break; - - case 0xa8: - out = Variant::Map(); - translate<FieldTable>(in, out.asMap(), &toVariantMapEntry); - break; - - case 0xa9: - out = Variant::List(); - translate<List>(in, out.asList(), &toVariant); - break; - case 0xaa: //convert amqp0-10 array into variant list - out = Variant::List(); - translate<Array>(in, out.asList(), &toVariant); - break; - - default: - //error? - break; - } - return out; -} - -boost::shared_ptr<FieldValue> convertString(const std::string& value, const std::string& encoding) -{ - bool large = value.size() > std::numeric_limits<uint16_t>::max(); - if (encoding.empty() || encoding == amqp0_10_binary || encoding == binary) { - if (large) { - return boost::shared_ptr<FieldValue>(new Var32Value(value, 0xa0)); - } else { - return boost::shared_ptr<FieldValue>(new Var16Value(value, 0x90)); - } - } else if (encoding == utf8) { - if (!large) - return boost::shared_ptr<FieldValue>(new Str16Value(value)); - throw Exception(QPID_MSG("Could not encode utf8 character string - too long (" << value.size() << " bytes)")); - } else if (encoding == utf16) { - if (!large) - return boost::shared_ptr<FieldValue>(new Var16Value(value, 0x96)); - throw Exception(QPID_MSG("Could not encode utf16 character string - too long (" << value.size() << " bytes)")); - } else if (encoding == iso885915) { - if (!large) - return boost::shared_ptr<FieldValue>(new Var16Value(value, 0x94)); - throw Exception(QPID_MSG("Could not encode iso-8859-15 character string - too long (" << value.size() << " bytes)")); - } else { - // the encoding was not recognised - QPID_LOG(warning, "Unknown byte encoding: [" << encoding << "], encoding as vbin32."); - return boost::shared_ptr<FieldValue>(new Var32Value(value, 0xa0)); - } -} - -boost::shared_ptr<FieldValue> toFieldValue(const Variant& in) -{ - boost::shared_ptr<FieldValue> out; - switch (in.getType()) { - case VAR_VOID: out = boost::shared_ptr<FieldValue>(new VoidValue()); break; - case VAR_BOOL: out = boost::shared_ptr<FieldValue>(new BoolValue(in.asBool())); break; - case VAR_UINT8: out = boost::shared_ptr<FieldValue>(new Unsigned8Value(in.asUint8())); break; - case VAR_UINT16: out = boost::shared_ptr<FieldValue>(new Unsigned16Value(in.asUint16())); break; - case VAR_UINT32: out = boost::shared_ptr<FieldValue>(new Unsigned32Value(in.asUint32())); break; - case VAR_UINT64: out = boost::shared_ptr<FieldValue>(new Unsigned64Value(in.asUint64())); break; - case VAR_INT8: out = boost::shared_ptr<FieldValue>(new Integer8Value(in.asInt8())); break; - case VAR_INT16: out = boost::shared_ptr<FieldValue>(new Integer16Value(in.asInt16())); break; - case VAR_INT32: out = boost::shared_ptr<FieldValue>(new Integer32Value(in.asInt32())); break; - case VAR_INT64: out = boost::shared_ptr<FieldValue>(new Integer64Value(in.asInt64())); break; - case VAR_FLOAT: out = boost::shared_ptr<FieldValue>(new FloatValue(in.asFloat())); break; - case VAR_DOUBLE: out = boost::shared_ptr<FieldValue>(new DoubleValue(in.asDouble())); break; - case VAR_STRING: out = convertString(in.asString(), in.getEncoding()); break; - case VAR_UUID: out = boost::shared_ptr<FieldValue>(new UuidValue(in.asUuid().data())); break; - case VAR_MAP: - out = boost::shared_ptr<FieldValue>(toFieldTableValue(in.asMap())); - break; - case VAR_LIST: - out = boost::shared_ptr<FieldValue>(toListValue(in.asList())); - break; - } - return out; -} - -Variant::Map::value_type toVariantMapEntry(const FieldTable::value_type& in) -{ - return Variant::Map::value_type(in.first, toVariant(in.second)); -} - -FieldTable::value_type toFieldTableEntry(const Variant::Map::value_type& in) -{ - return FieldTable::value_type(in.first, toFieldValue(in.second)); -} - -struct EncodeBuffer -{ - char* data; - Buffer buffer; - - EncodeBuffer(size_t size) : data(new char[size]), buffer(data, size) {} - ~EncodeBuffer() { delete[] data; } - - template <class T> void encode(T& t) { t.encode(buffer); } - - void getData(std::string& s) { - s.assign(data, buffer.getSize()); - } -}; - -struct DecodeBuffer -{ - Buffer buffer; - - DecodeBuffer(const std::string& s) : buffer(const_cast<char*>(s.data()), s.size()) {} - - template <class T> void decode(T& t) { t.decode(buffer); } - -}; - -template <class T, class U, class F> void _encode(const U& value, std::string& data, F f) -{ - T t; - convert(value, t, f); - EncodeBuffer buffer(t.encodedSize()); - buffer.encode(t); - buffer.getData(data); -} - -template <class T, class U, class F> void _decode(const std::string& data, U& value, F f) -{ - T t; - DecodeBuffer buffer(data); - buffer.decode(t); - convert(t, value, f); -} - -void MapCodec::encode(const Variant::Map& value, std::string& data) -{ - _encode<FieldTable>(value, data, &toFieldTableEntry); -} - -void MapCodec::decode(const std::string& data, Variant::Map& value) -{ - _decode<FieldTable>(data, value, &toVariantMapEntry); -} - -size_t MapCodec::encodedSize(const Variant::Map& value) -{ - std::string encoded; - encode(value, encoded); - return encoded.size(); -} - -void ListCodec::encode(const Variant::List& value, std::string& data) -{ - _encode<List>(value, data, &toFieldValue); -} - -void ListCodec::decode(const std::string& data, Variant::List& value) -{ - _decode<List>(data, value, &toVariant); -} - -size_t ListCodec::encodedSize(const Variant::List& value) -{ - std::string encoded; - encode(value, encoded); - return encoded.size(); -} - -void translate(const Variant::Map& from, FieldTable& to) -{ - convert(from, to, &toFieldTableEntry); -} - -void translate(const FieldTable& from, Variant::Map& to) -{ - convert(from, to, &toVariantMapEntry); -} - -const std::string ListCodec::contentType("amqp/list"); -const std::string MapCodec::contentType("amqp/map"); - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Command.h b/cpp/src/qpid/amqp_0_10/Command.h deleted file mode 100644 index b1d3607a84..0000000000 --- a/cpp/src/qpid/amqp_0_10/Command.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_AMQP_0_10_COMMAND_H -#define QPID_AMQP_0_10_COMMAND_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/Control.h" -#include "qpid/amqp_0_10/structs.h" - -namespace qpid { -namespace amqp_0_10 { - -struct CommandVisitor; -struct ConstCommandVisitor; -struct CommandHolder; -struct Command - : public Action, - public Visitable<CommandVisitor, ConstCommandVisitor, CommandHolder> -{ - using Action::getCommand; - Command* getCommand() { return this; } - uint8_t getCode() const; - uint8_t getClassCode() const; - const char* getName() const; - const char* getClassName() const; - - session::Header sessionHeader; -}; - -std::ostream& operator<<(std::ostream&, const Command&); - -template <class T> -struct CommandPacker : Packer<T> { - CommandPacker(T& t) : Packer<T>(t) {} - - template <class S> void serialize(S& s) { - s(this->data.sessionHeader); - Packer<T>::serialize(s); - } -}; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_COMMAND_H*/ diff --git a/cpp/src/qpid/amqp_0_10/CommmandPacker.h b/cpp/src/qpid/amqp_0_10/CommmandPacker.h deleted file mode 100644 index 51ebfe8186..0000000000 --- a/cpp/src/qpid/amqp_0_10/CommmandPacker.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_AMQP_0_10_COMMMANDPACKER_H -#define QPID_AMQP_0_10_COMMMANDPACKER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/structs.h" - -namespace qpid { -namespace amqp_0_10 { - -/** - * Packer for commands - serialize session.header before pack bits. - */ -template <class T> -class CommmandPacker : public Packer<T> -{ - public: - CommmandPacker(T& t) : Packer<T>(t) {} - template <class S> void serialize(S& s) { s.split(*this); } - - template <class S> void encode(S& s) const { - s.sessionHeader( - Packer<T>::encode(s); - } - - template <class S> void decode(S& s) { - Bits bits; - s.littleEnd(bits); - PackedDecoder<S, Bits> decode(s, bits); - data.serialize(decode); - } - - - protected: - T& data; - - -}; -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_COMMMANDPACKER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Connection.cpp b/cpp/src/qpid/amqp_0_10/Connection.cpp deleted file mode 100644 index bf2e7d5713..0000000000 --- a/cpp/src/qpid/amqp_0_10/Connection.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/Connection.h" -#include "qpid/log/Statement.h" -#include "qpid/amqp_0_10/exceptions.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/ProtocolInitiation.h" - -namespace qpid { -namespace amqp_0_10 { - -using sys::Mutex; - -Connection::Connection(sys::OutputControl& o, const std::string& id, bool _isClient) - : pushClosed(false), popClosed(false), output(o), identifier(id), initialized(false), - isClient(_isClient), buffered(0), version(0,10) -{} - -void Connection::setInputHandler(std::auto_ptr<sys::ConnectionInputHandler> c) { - connection = c; -} - -size_t Connection::decode(const char* buffer, size_t size) { - framing::Buffer in(const_cast<char*>(buffer), size); - if (isClient && !initialized) { - //read in protocol header - framing::ProtocolInitiation pi; - if (pi.decode(in)) { - if(!(pi==version)) - throw Exception(QPID_MSG("Unsupported version: " << pi - << " supported version " << version)); - QPID_LOG(trace, "RECV " << identifier << " INIT(" << pi << ")"); - } - initialized = true; - } - framing::AMQFrame frame; - while(frame.decode(in)) { - QPID_LOG(trace, "RECV [" << identifier << "]: " << frame); - connection->received(frame); - } - return in.getPosition(); -} - -bool Connection::canEncode() { - Mutex::ScopedLock l(frameQueueLock); - if (!popClosed) { - Mutex::ScopedUnlock u(frameQueueLock); - connection->doOutput(); - } - return !popClosed && ((!isClient && !initialized) || !frameQueue.empty()); -} - -bool Connection::isClosed() const { - Mutex::ScopedLock l(frameQueueLock); - return pushClosed && popClosed; -} - -size_t Connection::encode(const char* buffer, size_t size) { - { // Swap frameQueue data into workQueue to avoid holding lock while we encode. - Mutex::ScopedLock l(frameQueueLock); - if (popClosed) return 0; // Can't pop any more frames. - assert(workQueue.empty()); - workQueue.swap(frameQueue); - } - framing::Buffer out(const_cast<char*>(buffer), size); - if (!isClient && !initialized) { - framing::ProtocolInitiation pi(getVersion()); - pi.encode(out); - initialized = true; - QPID_LOG(trace, "SENT " << identifier << " INIT(" << pi << ")"); - } - size_t frameSize=0; - size_t encoded=0; - while (!workQueue.empty() && ((frameSize=workQueue.front().encodedSize()) <= out.available())) { - workQueue.front().encode(out); - QPID_LOG(trace, "SENT [" << identifier << "]: " << workQueue.front()); - workQueue.pop_front(); - encoded += frameSize; - if (workQueue.empty() && out.available() > 0) connection->doOutput(); - } - assert(workQueue.empty() || workQueue.front().encodedSize() <= size); - if (!workQueue.empty() && workQueue.front().encodedSize() > size) - throw InternalErrorException(QPID_MSG("Frame too large for buffer.")); - { - Mutex::ScopedLock l(frameQueueLock); - buffered -= encoded; - // Put back any frames we did not encode. - frameQueue.insert(frameQueue.begin(), workQueue.begin(), workQueue.end()); - workQueue.clear(); - if (frameQueue.empty() && pushClosed) - popClosed = true; - } - return out.getPosition(); -} - -void Connection::abort() { output.abort(); } -void Connection::activateOutput() { output.activateOutput(); } -void Connection::giveReadCredit(int32_t credit) { output.giveReadCredit(credit); } - -void Connection::close() { - // No more frames can be pushed onto the queue. - // Frames aleady on the queue can be popped. - Mutex::ScopedLock l(frameQueueLock); - pushClosed = true; -} - -void Connection::closed() { - connection->closed(); -} - -void Connection::send(framing::AMQFrame& f) { - { - Mutex::ScopedLock l(frameQueueLock); - if (!pushClosed) - frameQueue.push_back(f); - buffered += f.encodedSize(); - } - activateOutput(); -} - -framing::ProtocolVersion Connection::getVersion() const { - return version; -} - -void Connection::setVersion(const framing::ProtocolVersion& v) { - version = v; -} - -size_t Connection::getBuffered() const { - Mutex::ScopedLock l(frameQueueLock); - return buffered; -} - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Connection.h b/cpp/src/qpid/amqp_0_10/Connection.h deleted file mode 100644 index 995d824796..0000000000 --- a/cpp/src/qpid/amqp_0_10/Connection.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QPID_AMQP_0_10_CONNECTION_H -#define QPID_AMQP_0_10_CONNECTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/AMQFrame.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/ConnectionInputHandler.h" -#include "qpid/sys/ConnectionOutputHandler.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/BrokerImportExport.h" -#include <boost/intrusive_ptr.hpp> -#include <memory> -#include <deque> - -namespace qpid { - -namespace sys { -class ConnectionInputHandlerFactory; -} - -namespace amqp_0_10 { - -class Connection : public sys::ConnectionCodec, - public sys::ConnectionOutputHandler -{ - typedef std::deque<framing::AMQFrame> FrameQueue; - - FrameQueue frameQueue; - FrameQueue workQueue; - bool pushClosed, popClosed; - mutable sys::Mutex frameQueueLock; - sys::OutputControl& output; - std::auto_ptr<sys::ConnectionInputHandler> connection; - std::string identifier; - bool initialized; - bool isClient; - size_t buffered; - framing::ProtocolVersion version; - - public: - QPID_BROKER_EXTERN Connection(sys::OutputControl&, const std::string& id, bool isClient); - QPID_BROKER_EXTERN void setInputHandler(std::auto_ptr<sys::ConnectionInputHandler> c); - size_t decode(const char* buffer, size_t size); - size_t encode(const char* buffer, size_t size); - bool isClosed() const; - bool canEncode(); - void abort(); - void activateOutput(); - void giveReadCredit(int32_t); - void closed(); // connection closed by peer. - void close(); // closing from this end. - void send(framing::AMQFrame&); - framing::ProtocolVersion getVersion() const; - size_t getBuffered() const; - - /** Used by cluster code to set a special version on "update" connections. */ - // FIXME aconway 2009-07-30: find a cleaner mechanism for this. - void setVersion(const framing::ProtocolVersion&); -}; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_CONNECTION_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Control.h b/cpp/src/qpid/amqp_0_10/Control.h deleted file mode 100644 index ce188ae6d8..0000000000 --- a/cpp/src/qpid/amqp_0_10/Control.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef QPID_AMQP_0_10_CONTROL_H -#define QPID_AMQP_0_10_CONTROL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/Struct.h" - -namespace qpid { -namespace amqp_0_10 { - -struct Command; -struct Control; - -struct Action { // Base for commands & controls - virtual ~Action() {} - virtual Command* getCommand() { return 0; } - virtual Control* getControl() { return 0; } - - virtual const Command* getCommand() const { - return const_cast<Action*>(this)->getCommand(); - } - virtual const Control* getControl() const { - return const_cast<Action*>(this)->getControl(); - } - static const uint8_t SIZE=0; - static const uint8_t PACK=2; -}; - -struct ControlVisitor; -struct ConstControlVisitor; -struct ControlHolder; -struct Control - : public Action, - public Visitable<ControlVisitor, ConstControlVisitor, ControlHolder> -{ - using Action::getControl; - Control* getControl() { return this; } - uint8_t getCode() const; - uint8_t getClassCode() const; - const char* getName() const; - const char* getClassName() const; -}; -std::ostream& operator<<(std::ostream&, const Control&); - -template <SegmentType E> struct ActionType; -template <> struct ActionType<CONTROL> { typedef Control type; }; -template <> struct ActionType<COMMAND> { typedef Command type; }; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_CONTROL_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Decimal.h b/cpp/src/qpid/amqp_0_10/Decimal.h deleted file mode 100644 index 50fc457c76..0000000000 --- a/cpp/src/qpid/amqp_0_10/Decimal.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef TESTS_DECIMAL_H -#define TESTS_DECIMAL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <ostream> - -namespace qpid { -namespace amqp_0_10 { - -template <class E, class M> struct Decimal { - E exponent; - M mantissa; - - Decimal(E exp=0, M man=0) : exponent(exp), mantissa(man) {} - - bool operator==(const Decimal& d) const { - return exponent == d.exponent && mantissa == d.mantissa; - } - - // TODO aconway 2008-02-20: We could provide arithmetic operators - // if anybody really cares about this type. - - template <class S> void serialize(S& s) { s(exponent)(mantissa); } -}; - -template<class E, class M> -inline std::ostream& operator<<(std::ostream& o, const Decimal<E,M>& d) { - return o << "Decimal{" << d.mantissa << "/10^" << (int)d.exponent << "}"; -} -}} - -#endif /*!TESTS_DECIMAL_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Exception.h b/cpp/src/qpid/amqp_0_10/Exception.h deleted file mode 100644 index 6d526c1706..0000000000 --- a/cpp/src/qpid/amqp_0_10/Exception.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef QPID_AMQP_0_10_EXCEPTION_H -#define QPID_AMQP_0_10_EXCEPTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Exception.h" -#include "qpid/amqp_0_10/specification_fwd.h" - -namespace qpid { -namespace amqp_0_10 { - -/** - * Raised when the connection is unexpectedly closed. Sessions with - * non-0 timeout may be available for re-attachment on another connection. - */ -struct ConnectionException : public qpid::Exception { - // FIXME aconway 2008-04-04: Merge qpid::ConnectionException - // into this when the old code is removed. - typedef connection::CloseCode Code; - ConnectionException(Code c, const std::string m) - : qpid::Exception(m), code(c) {} - Code code; -}; - -/** - * Raised when a session is unexpectedly detached for any reason, or - * if an attempt is made to use a session that is not attached. - */ -struct SessionException : public qpid::Exception { - // FIXME aconway 2008-04-04: should not have a code at this level. - // Leave in place till old preview code is gone. - SessionException(int /*code*/, const std::string& msg) : qpid::Exception(msg) {} -}; - -/** Raised when the state of a session has been destroyed */ -struct SessionDestroyedException : public SessionException { - // FIXME aconway 2008-04-04: should not have a code at this level. - // Leave in place till old preview code is gone. - SessionDestroyedException(int code, const std::string& msg) : SessionException(code, msg){} -}; - -/** Raised when a session is destroyed due to an execution.exception */ -struct SessionAbortedException : public SessionDestroyedException { - typedef execution::ErrorCode Code; - SessionAbortedException(Code c, const std::string m) - : SessionDestroyedException(c, m), code(c) {} - Code code; -}; - -/** - * Raised when a session with 0 timeout is unexpectedly detached - * and therefore expires and is destroyed. - */ -struct SessionExpiredException : public SessionDestroyedException { - typedef session::DetachCode Code; - SessionExpiredException(Code c, const std::string m) - : SessionDestroyedException(c, m), code(c) {} - Code code; -}; - -/** - * Raised when a session with non-0 timeout is unexpectedly detached - * or if an attempt is made to use a session that is not attached. - * - * The session is not necessarily destroyed, it may be possible to - * re-attach. - */ -struct SessionDetachedException : public SessionException { - typedef session::DetachCode Code; - SessionDetachedException(Code c, const std::string m) - : SessionException(c, m), code(c) {} - Code code; -}; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_EXCEPTION_H*/ diff --git a/cpp/src/qpid/amqp_0_10/FrameHeader.cpp b/cpp/src/qpid/amqp_0_10/FrameHeader.cpp deleted file mode 100644 index 371e3c1bcb..0000000000 --- a/cpp/src/qpid/amqp_0_10/FrameHeader.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/FrameHeader.h" -#include <ios> -#include <iomanip> -#include <ostream> - -using namespace std; - -namespace qpid { -namespace amqp_0_10 { - -bool FrameHeader::operator==(const FrameHeader& x) const { - return flags == x.flags && - type == x.type && - size == x.size && - track == x.track && - channel == x.channel; -} - -std::ostream& operator<<(std::ostream& o, const FrameHeader& f) { - std::ios::fmtflags saveFlags = o.flags(); - return o << "Frame[" - << "flags=" << std::hex << std::showbase << int(f.getFlags()) << std::setiosflags(saveFlags) - << " type=" << f.getType() - << " size=" << f.getSize() - << " track=" << int(f.getTrack()) - << " channel=" << f.getChannel() - << "]"; -} - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/FrameHeader.h b/cpp/src/qpid/amqp_0_10/FrameHeader.h deleted file mode 100644 index b2f0619f9b..0000000000 --- a/cpp/src/qpid/amqp_0_10/FrameHeader.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef QPID_AMQP_0_10_FRAMEHEADER_H -#define QPID_AMQP_0_10_FRAMEHEADER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/built_in_types.h" -#include <boost/shared_array.hpp> -#include <string.h> -#include <assert.h> -#include <iosfwd> - -namespace qpid { -namespace amqp_0_10 { - -enum FrameFlags { FIRST_SEGMENT=8, LAST_SEGMENT=4, FIRST_FRAME=2, LAST_FRAME=1 }; - -class FrameHeader { - public: - static const size_t SIZE=12; - static uint8_t trackFor(SegmentType type) { return type == 0 ? 0 : 1; } - - FrameHeader(uint8_t flags_=0, SegmentType type_=SegmentType(), uint16_t size_=0, uint8_t track_=0, uint16_t channel_=0) - : flags(flags_), type(type_), size(size_), track(track_), channel(channel_) - {} - - uint8_t getFlags() const { return flags; } - SegmentType getType() const { return type; } - /** @return size total size of of frame, including frame header. */ - uint16_t getSize() const { return size; } - /** @return size of frame data, excluding frame header. */ - uint16_t getDataSize() const { return size - SIZE; } - uint8_t getTrack() const { return track; } - uint16_t getChannel() const { return channel; } - - void setFlags(uint8_t flags_) { flags=flags_; } - /** Also sets the track. There is no setTrack() */ - void setType(SegmentType type_) { type=type_; track=trackFor(type); } - /** @param size total size of of frame, including frame header. */ - void setSize(uint16_t size_) { size = size_; } - /** @param size size of frame data, excluding frame header. */ - void setDataSize(uint16_t size_) { size = size_+SIZE; } - void setChannel(uint8_t channel_) { channel=channel_; } - - bool allFlags(uint8_t f) const { return (flags & f) == f; } - bool anyFlags(uint8_t f) const { return (flags & f); } - - void raiseFlags(uint8_t f) { flags |= f; } - void clearFlags(uint8_t f) { flags &= ~f; } - - bool isComplete() const { return allFlags(FIRST_FRAME | LAST_FRAME); } - - bool operator==(const FrameHeader&) const; - - template <class S> void serialize(S& s) { - uint8_t pad8=0; uint32_t pad32=0; - s(flags)(type)(size)(pad8)(track)(channel)(pad32); - } - - private: - uint8_t flags; - SegmentType type; - uint16_t size; - uint8_t track; - uint16_t channel; -}; - -std::ostream& operator<<(std::ostream&, const FrameHeader&); - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_FRAMEHEADER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Header.cpp b/cpp/src/qpid/amqp_0_10/Header.cpp deleted file mode 100644 index d83814e969..0000000000 --- a/cpp/src/qpid/amqp_0_10/Header.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/Header.h" - -namespace qpid { -namespace amqp_0_10 { - -std::ostream& operator<<(std::ostream& o, const Header& h) { - o << "Header["; - std::ostream_iterator<Struct32> i(o, " "); - std::copy(h.begin(), h.end(), i); - o << "]"; - return o; -} - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Header.h b/cpp/src/qpid/amqp_0_10/Header.h deleted file mode 100644 index 0ce6ad9135..0000000000 --- a/cpp/src/qpid/amqp_0_10/Header.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef QPID_AMQP_0_10_HEADER_H -#define QPID_AMQP_0_10_HEADER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/built_in_types.h" -#include "qpid/amqp_0_10/Struct32.h" -#include <vector> -#include <ostream> - -namespace qpid { -namespace amqp_0_10 { - -class Header : public std::vector<Struct32> { - public: - Header() {} - - template <class S> void serialize(S& s) { s.split(*this); } - template <class S> void encode(S& s) const { s(this->begin(), this->end()); } - template <class S> void decode(S& s); -}; - -template <class S> void Header::decode(S& s) { - this->clear(); - while (s.bytesRemaining() > 0) { - this->push_back(Struct32()); - s(this->back()); - } -} - -std::ostream& operator<<(std::ostream& o, const Header&); - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_HEADER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Holder.h b/cpp/src/qpid/amqp_0_10/Holder.h deleted file mode 100644 index 605d2e0ed5..0000000000 --- a/cpp/src/qpid/amqp_0_10/Holder.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef QPID_AMQP_0_10_HOLDER_H -#define QPID_AMQP_0_10_HOLDER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/Blob.h" -#include "qpid/amqp_0_10/apply.h" - -namespace qpid { -namespace amqp_0_10 { - -using framing::in_place; - -template <class Invokable> struct InvokeVisitor { - typedef void result_type; - Invokable& target; - InvokeVisitor(Invokable& i) : target(i) {} - - template <class Action> - void operator()(const Action& action) { action.invoke(target); } -}; - -template <class DerivedHolder, class BaseHeld, size_t Size> -class Holder : public framing::Blob<Size, BaseHeld> { - typedef framing::Blob<Size, BaseHeld> Base; - - public: - - Holder() {} - template <class T> explicit Holder(const T& value) : Base(value) {} - - using Base::operator=; - Holder& operator=(const BaseHeld& rhs); - - uint8_t getCode() const { return this->get()->getCode(); } - uint8_t getClassCode() const { return this->get()->getClassCode(); } - - template <class Invokable> void invoke(Invokable& i) const { - InvokeVisitor<Invokable> v(i); - apply(v, *this->get()); - } - - template <class S> void encode(S& s) const { - s(getClassCode())(getCode()); - } - - template <class S> void decode(S& s) { - uint8_t code, classCode; - s(classCode)(code); - static_cast<DerivedHolder*>(this)->set(classCode, code); - } - - template <class S> void serialize(S& s) { - s.split(*this); - qpid::amqp_0_10::apply(s, *this->get()); - } - - template <class T> T* getIf() { - return (getClassCode()==T::CLASS_CODE && getCode()==T::CODE) ? static_cast<T*>(this->get()) : 0; - } - - template <class T> const T* getIf() const { - return (getClassCode()==T::CLASS_CODE && getCode()==T::CODE) ? static_cast<T*>(this->get()) : 0; - } - - private: - struct Assign : public ApplyFunctor<void> { - Holder& holder; - Assign(Holder& x) : holder(x) {} - template <class T> void operator()(const T& rhs) { holder=rhs; } - }; -}; - -template <class D, class B, size_t S> -Holder<D,B,S>& Holder<D,B,S>::operator=(const B& rhs) { - Assign assign(*this); - qpid::amqp_0_10::apply(assign, rhs); - return *this; -} - - - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_HOLDER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Map.cpp b/cpp/src/qpid/amqp_0_10/Map.cpp deleted file mode 100644 index af3b302d25..0000000000 --- a/cpp/src/qpid/amqp_0_10/Map.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/Map.h" -#include "qpid/amqp_0_10/Struct32.h" -#include "qpid/amqp_0_10/Array.h" -#include <ostream> - -namespace qpid { -namespace amqp_0_10 { - -MapValue::MapValue() : code(codeFor(uint8_t(0))), blob(in_place<uint8_t>(0)) {} - -MapValue::MapValue(const MapValue& x) : code(x.code), blob(x.blob) {} - -bool MapValue::operator==(const MapValue& x) const { - return code == x.code; // FIXME aconway 2008-04-01: incomplete -} - -struct OstreamVisitor : public MapValue::Visitor<std::ostream&> { - std::ostream& out; - OstreamVisitor(std::ostream& o) : out(o) {} - template <class T> std::ostream& operator()(const T& t) { - return out << t; - } -}; - -std::ostream& operator<<(std::ostream& o, const MapValue& m) { - o << typeName(m.getCode()) << ":"; - const_cast<MapValue&>(m).apply_visitor(OstreamVisitor(o)); - return o; -} - -std::ostream& operator<<(std::ostream& o, const Map::value_type& v) { - return o << v.first << "=" << v.second; -} -std::ostream& operator<<(std::ostream& o, const Map& map) { - o << "map["; - std::ostream_iterator<Map::value_type> i(o, " "); - std::copy(map.begin(), map.end(), i); - return o << "]"; -} - -uint32_t Map::contentSize() const { - // FIXME aconway 2008-04-03: preview to 0-10 mapping: +4 for count. - return /*4 +*/ Codec::Size()(begin(), end()); -} - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Map.h b/cpp/src/qpid/amqp_0_10/Map.h deleted file mode 100644 index 4093b1a0aa..0000000000 --- a/cpp/src/qpid/amqp_0_10/Map.h +++ /dev/null @@ -1,188 +0,0 @@ -#ifndef QPID_AMQP_0_10_MAP_H -#define QPID_AMQP_0_10_MAP_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on ang - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Exception.h" -#include "qpid/amqp_0_10/built_in_types.h" -#include "qpid/amqp_0_10/UnknownType.h" -#include "qpid/amqp_0_10/CodeForType.h" -#include "qpid/amqp_0_10/TypeForCode.h" -#include "qpid/amqp_0_10/Codec.h" -#include "qpid/framing/Blob.h" -#include <map> -#include <string> -#include <iosfwd> - -namespace qpid { -namespace amqp_0_10 { - -class Map; - -class MapValue { - public: - struct BadTypeException : public Exception {}; - - template <class R> struct Visitor { typedef R result_type; }; - - MapValue(); - MapValue(const MapValue& x); - template <class T> explicit MapValue(const T& t); - template <class T> MapValue& operator=(const T& t); - - template <class T> T* get(); - template <class T> const T* get() const; - - template <class V> typename V::result_type apply_visitor(V&); - template <class V> typename V::result_type apply_visitor(const V&); - - uint8_t getCode() const { return code; } - - bool operator==(const MapValue&) const; - - template <class S> void serialize(S& s) { s(code); s.split(*this); } - template <class S> void encode(S& s) const { - const_cast<MapValue*>(this)->apply_visitor(s); - } - template <class S> void decode(S& s) { - DecodeVisitor<S> dv(blob, s); - qpid::amqp_0_10::apply_visitor(dv, code); - } - - - private: - // TODO aconway 2008-04-15: Estimate required size, we will get a - // compile error from static_assert in Blob.h if the estimate is too - // low. We can't use sizeof() directly because #include Struct32.h - // creates a circular dependency. Needs a better solution. - static const size_t SIZE=256; - typedef framing::Blob<SIZE> Blob; - - template <class V> struct VisitVisitor; - template <class T> struct GetVisitor; - template <class D> struct DecodeVisitor; - - uint8_t code; - Blob blob; -}; - -class Map : public std::map<Str8, MapValue> { - public: - template <class S> void serialize(S& s) { s.split(*this); } - template <class S> void encode(S& s) const; - // Shortcut calculation for size. - void encode(Codec::Size& s) const { s.raw(0, contentSize() + 4/*size*/); } - - template <class S> void decode(S& s); - - private: - uint32_t contentSize() const; -}; - -std::ostream& operator<<(std::ostream&, const MapValue&); -std::ostream& operator<<(std::ostream&, const Map::value_type&); -std::ostream& operator<<(std::ostream&, const Map&); - -using framing::in_place; - -template <class T> MapValue::MapValue(const T& t) : code(codeFor(t)), blob(in_place<t>()) {} - -template <class T> MapValue& MapValue::operator=(const T& t) { - code=codeFor(t); - blob=t; - return *this; -} - -template <class V> struct MapValue::VisitVisitor { - typedef typename V::result_type result_type; - V& visitor; - Blob& blob; - VisitVisitor(V& v, Blob& b) : visitor(v), blob(b) {} - - template <class T> result_type operator()(T*) { - return visitor(*reinterpret_cast<T*>(blob.get())); - } -}; - -template <class V> typename V::result_type MapValue::apply_visitor(V& v) { - VisitVisitor<V> visitor(v, blob); - return qpid::amqp_0_10::apply_visitor(visitor, code); -} - -template <class R> struct MapValue::GetVisitor { - typedef R* result_type; - const MapValue::Blob& blob; - - GetVisitor(const MapValue::Blob& b) : blob(b) {} - - R* operator()(R& r) { return &r; } - template <class T> R* operator()(T&) { return 0; } -}; - -template <class D> struct MapValue::DecodeVisitor { - typedef void result_type; - MapValue::Blob& blob; - D& decoder; - DecodeVisitor(Blob& b, D& d) : blob(b), decoder(d) {} - - template <class T> void operator()(T*) { - T t; - decoder(t); - blob = t; - } -}; - -template <class T> T* MapValue::get() { return apply_visitor(GetVisitor<T>(blob)); } -template <class T> const T* MapValue::get() const { return apply_visitor(GetVisitor<const T>()); } - -template <class V> typename V::result_type MapValue::apply_visitor(const V& v) { - return apply_visitor(const_cast<V&>(v)); -} - -template <class S> void Map::encode(S& s) const { - // FIXME aconway 2008-04-03: replace preview mapping with 0-10 mapping: - // s(contentSize())(uint32_t(size())); // size, count - s(contentSize()); - for (const_iterator i = begin(); i != end(); ++i) - s(i->first)(i->second); // key (type value) -} - -template <class S> void Map::decode(S& s) { - uint32_t decodedSize /*, count*/; - // FIXME aconway 2008-04-03: replace preview mapping with 0-10 mapping: - // s(contentSize())(uint32_t(size())); // size, count - // s(decodedSize)(count); - s(decodedSize); - typename S::ScopedLimit l(s, decodedSize); // Make sure we don't overrun. - // FIXME aconway 2008-04-03: replace preview with 0-10: - // for ( ; count > 0; --count) { - while (s.bytesRemaining() > 0) { - key_type k; MapValue v; - s(k)(v); - insert(value_type(k,v)); - } -} - - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_MAP_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Packer.h b/cpp/src/qpid/amqp_0_10/Packer.h deleted file mode 100644 index c38e3a7efa..0000000000 --- a/cpp/src/qpid/amqp_0_10/Packer.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef QPID_PACKER_H -#define QPID_PACKER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/optional.hpp> -#include <boost/none.hpp> -#include "qpid/amqp_0_10/built_in_types.h" - -namespace qpid { -namespace amqp_0_10 { - -/** Serialization for optional values */ -template <class T> struct SerializableOptional { - boost::optional<T>& optional; - SerializableOptional(boost::optional<T>& x) : optional(x) {} - template <class S> void serialize(S& s) { - if (optional) - s(*optional); - } -}; - -}} - - -namespace boost { // For argument dependent lookup. - -template <class T> -qpid::amqp_0_10::SerializableOptional<T> serializable(boost::optional<T>& x) { - return qpid::amqp_0_10::SerializableOptional<T>(x); -} - -} // namespace boost - -namespace qpid { -namespace amqp_0_10 { - -/** "Encoder" that encodes a struct as a set of bit flags - * for all non-empty members. - */ -class PackBits { - public: - PackBits() : bit(1), bits(0) {} - - void setBit(bool b) { if (b) bits |= bit; bit <<= 1; } - uint32_t getBits() { return bits; } - - /** The bit is always set for non-optional values. */ - template <class T> - PackBits& operator()(const T&) { setBit(1); return *this; } - - /** For optional values the bit is set if the value is present. */ - template <class T> PackBits& operator()(const boost::optional<T>& opt) { - setBit(opt); return *this; - } - - /** Bits are special optional values */ - PackBits& operator()(Bit b) { setBit(b); return *this; } - - private: - uint32_t bit; - uint32_t bits; -}; - -/** Bit mask to encode a packable struct */ -template<class T> uint32_t packBits(const T& t) { - PackBits pack; - const_cast<T&>(t).serialize(pack); - return pack.getBits(); -} - -/** Decode members enabled by Bits */ -template <class Decoder, class Bits> -class PackedDecoder { - public: - PackedDecoder(Decoder& d, Bits b) : decode(d), bits(b) {} - - template <class T> PackedDecoder& operator()(T& t) { - if (bits & 1) - decode(t); - else - t = T(); - // FIXME aconway 2008-04-10: When we have all optionals - // represented by boost::optional the line above should be: - // throw CommandInvalidException("A required value was omitted."); - bits >>= 1; - return *this; - } - - template <class T> PackedDecoder& operator()(boost::optional<T>& opt) { - if (bits & 1) { - opt = T(); - decode(*opt); - } - else - opt = boost::none; - bits >>= 1; - return *this; - } - - private: - Decoder& decode; - Bits bits; -}; - -/** Metafunction to compute type to contain pack bits. */ -template <int Bytes> struct UintOfSize; -template <> struct UintOfSize<1> { typedef uint8_t type; }; -template <> struct UintOfSize<2> { typedef uint16_t type; }; -template <> struct UintOfSize<4> { typedef uint32_t type; }; - -/** - * Helper to serialize packed structs. - */ -template <class T> class Packer -{ - public: - typedef typename UintOfSize<T::PACK>::type Bits; - - Packer(T& t) : data(t) {} - - template <class S> void serialize(S& s) { s.split(*this); } - - template <class S> void encode(S& s) const { - Bits bits = packBits(data); - s.littleEnd(bits); - data.serialize(s); - } - - template <class S> void decode(S& s) { - Bits bits; - s.littleEnd(bits); - PackedDecoder<S, Bits> decode(s, bits); - data.serialize(decode); - } - - - protected: - T& data; -}; - -template <class T, uint8_t=T::SIZE> struct SizedPacker : public Packer<T> { - typedef typename UintOfSize<T::SIZE>::type Size; - - SizedPacker(T& t) : Packer<T>(t) {} - - template <class S> void serialize(S& s) { - s.split(*this); - } - - template <class S> void encode(S& s) const { - Codec::Size sizer; - this->data.serialize(sizer); - Size size=size_t(sizer)+T::PACK; // Size with pack bits. - s(size); - Packer<T>::encode(s); - } - - template <class S> void decode(S& s) { - Size size; - s(size); - typename S::ScopedLimit l(s, size); - Packer<T>::decode(s); - } - -}; - -template <class T> struct SizedPacker<T,0> : public Packer<T> { - SizedPacker(T& t) : Packer<T>(t) {} -}; - -}} // namespace qpid::amqp_0_10 - - - -#endif /*!QPID_PACKER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/SerializableString.h b/cpp/src/qpid/amqp_0_10/SerializableString.h deleted file mode 100644 index 485b7ca6a8..0000000000 --- a/cpp/src/qpid/amqp_0_10/SerializableString.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_AMQP_0_10_SERIALIZABLESTRING_H -#define QPID_AMQP_0_10_SERIALIZABLESTRING_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -namespace qpid { -namespace amqp_0_10 { - -/** Template for length-prefixed strings/arrays. - * Unique parameter allows creation of distinct SerializableString - * types with the smae T/SizeType - */ -template <class T, class SizeType, int Unique=0> -struct SerializableString : public std::basic_string<T> { - SerializableString() {} - template <class U> SerializableString(const U& u) : std::basic_string<T>(u) {} - template <class I> SerializableString(const I& i, const I& j) : std::basic_string<T>(i,j) {} - - using std::basic_string<T>::operator=; - - template <class S> void serialize(S& s) { s.split(*this); } - - template <class S> void encode(S& s) const { - s(SizeType(this->size()))(this->begin(), this->end()); - } - - template <class S> void decode(S& s) { - SizeType newSize; - s(newSize); - this->resize(newSize); - s(this->begin(), this->end()); - } -}; - -// TODO aconway 2008-02-29: separate ostream ops -template <class T, class SizeType> -std::ostream& operator<<(std::ostream& o, const SerializableString<T,SizeType>& s) { - const std::basic_string<T> str(s); - return o << str.c_str(); // TODO aconway 2008-02-29: why doesn't o<<str work? -} - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_SERIALIZABLESTRING_H*/ diff --git a/cpp/src/qpid/amqp_0_10/SessionHandler.cpp b/cpp/src/qpid/amqp_0_10/SessionHandler.cpp deleted file mode 100644 index 97281a8d8c..0000000000 --- a/cpp/src/qpid/amqp_0_10/SessionHandler.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -#include "qpid/amqp_0_10/SessionHandler.h" -#include "qpid/SessionState.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/AllInvoker.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Statement.h" - - -#include <boost/bind.hpp> - -namespace qpid { -namespace amqp_0_10 { -using namespace framing; -using namespace std; - -void SessionHandler::checkAttached() { - if (!getState()) - throw NotAttachedException(QPID_MSG("Channel " << channel.get() << " is not attached")); -} - -SessionHandler::SessionHandler(FrameHandler* out, ChannelId ch) - : channel(ch, out), peer(channel), - awaitingDetached(false), - sendReady(), receiveReady() {} - -SessionHandler::~SessionHandler() {} - -namespace { -bool isSessionControl(AMQMethodBody* m) { - return m && m->amqpClassId() == SESSION_CLASS_ID; -} - -session::DetachCode convert(uint8_t code) { - switch(code) { - case 0: return session::DETACH_CODE_NORMAL; - case 1: return session::DETACH_CODE_SESSION_BUSY; - case 2: return session::DETACH_CODE_TRANSPORT_BUSY; - case 3: return session::DETACH_CODE_NOT_ATTACHED; - case 4: default: return session::DETACH_CODE_UNKNOWN_IDS; - } -} - -} // namespace - -void SessionHandler::invoke(const AMQMethodBody& m) { - framing::invoke(*this, m); -} - -void SessionHandler::handleIn(AMQFrame& f) { - // Note on channel states: a channel is attached if session != 0 - AMQMethodBody* m = f.getBody()->getMethod(); - try { - // Ignore all but detach controls while awaiting detach - if (awaitingDetached) { - if (!isSessionControl(m)) return; - if (m->amqpMethodId() != SESSION_DETACH_METHOD_ID && - m->amqpMethodId() != SESSION_DETACHED_METHOD_ID) - return; - } - if (isSessionControl(m)) { - invoke(*m); - } - else { - // Drop frames if we are detached. - if (!getState()) return; - if (!receiveReady) - throw IllegalStateException(QPID_MSG(getState()->getId() << ": Not ready to receive data")); - if (!getState()->receiverRecord(f)) - return; // Ignore duplicates. - if (getState()->receiverNeedKnownCompleted()) - sendCompletion(); - getInHandler()->handle(f); - } - } - catch(const SessionException& e) { - QPID_LOG(error, "Execution exception: " << e.what()); - executionException(e.code, e.what()); // Let subclass handle this first. - framing::AMQP_AllProxy::Execution execution(channel); - AMQMethodBody* m = f.getMethod(); - SequenceNumber commandId; - if (getState()) commandId = getState()->receiverGetCurrent(); - execution.exception(e.code, commandId, m ? m->amqpClassId() : 0, m ? m->amqpMethodId() : 0, 0, e.what(), FieldTable()); - detaching(); - sendDetach(); - } - catch(const ChannelException& e){ - QPID_LOG(error, "Channel exception: " << e.what()); - channelException(e.code, e.what()); // Let subclass handle this first. - peer.detached(name, e.code); - } - catch(const ConnectionException& e) { - QPID_LOG(error, "Connection exception: " << e.what()); - connectionException(e.code, e.getMessage()); - } - catch(const std::exception& e) { - QPID_LOG(error, "Unexpected exception: " << e.what()); - connectionException(connection::CLOSE_CODE_FRAMING_ERROR, e.what()); - } -} - -void SessionHandler::handleException(const qpid::SessionException& e) -{ - QPID_LOG(error, "Execution exception (during output): " << e.what()); - executionException(e.code, e.what()); // Let subclass handle this first. - framing::AMQP_AllProxy::Execution execution(channel); - execution.exception(e.code, 0, 0, 0, 0, e.what(), FieldTable()); - detaching(); - sendDetach(); -} - -namespace { -bool isCommand(const AMQFrame& f) { - return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_COMMAND; -} -} // namespace - -void SessionHandler::handleOut(AMQFrame& f) { - checkAttached(); - if (!sendReady) - throw IllegalStateException(QPID_MSG(getState()->getId() << ": Not ready to send data")); - getState()->senderRecord(f); - if (isCommand(f) && getState()->senderNeedFlush()) { - peer.flush(false, false, true); - getState()->senderRecordFlush(); - } - channel.handle(f); -} - -void SessionHandler::attach(const std::string& name_, bool force) { - // Save the name for possible session-busy exception. Session-busy - // can be thrown before we have attached the handler to a valid - // SessionState, and in that case we need the name to send peer.detached - name = name_; - if (getState() && name == getState()->getId().getName()) - return; // Idempotent - if (getState()) - throw TransportBusyException( - QPID_MSG("Channel " << channel.get() << " already attached to " << getState()->getId())); - setState(name, force); - QPID_LOG(debug, "Attached channel " << channel.get() << " to " << getState()->getId()); - peer.attached(name); - if (getState()->hasState()) - peer.flush(true, true, true); - else - sendCommandPoint(getState()->senderGetCommandPoint()); -} - -#define CHECK_NAME(NAME, MSG) do { \ - checkAttached(); \ - if (NAME != getState()->getId().getName()) \ - throw InvalidArgumentException( \ - QPID_MSG(MSG << ": incorrect session name: " << NAME \ - << ", expecting: " << getState()->getId().getName())); \ - } while(0) - - -void SessionHandler::attached(const std::string& name) { - CHECK_NAME(name, "session.attached"); -} - -void SessionHandler::detach(const std::string& name) { - CHECK_NAME(name, "session.detach"); - peer.detached(name, session::DETACH_CODE_NORMAL); - handleDetach(); -} - -void SessionHandler::detached(const std::string& name, uint8_t code) { - CHECK_NAME(name, "session.detached"); - awaitingDetached = false; - if (code != session::DETACH_CODE_NORMAL) - channelException(convert(code), "session.detached from peer."); - else { - handleDetach(); - } -} - -void SessionHandler::handleDetach() { - sendReady = receiveReady = false; -} - -void SessionHandler::requestTimeout(uint32_t t) { - checkAttached(); - getState()->setTimeout(t); - peer.timeout(getState()->getTimeout()); -} - -void SessionHandler::timeout(uint32_t t) { - checkAttached(); - getState()->setTimeout(t); -} - -void SessionHandler::commandPoint(const SequenceNumber& id, uint64_t offset) { - checkAttached(); - getState()->receiverSetCommandPoint(SessionPoint(id, offset)); - if (!receiveReady) { - receiveReady = true; - readyToReceive(); - } -} - -void SessionHandler::expected(const SequenceSet& commands, const Array& /*fragments*/) { - checkAttached(); - if (getState()->hasState()) { // Replay - if (commands.empty()) throw IllegalStateException( - QPID_MSG(getState()->getId() << ": has state but client is attaching as new session.")); - // TODO aconway 2008-05-12: support replay of partial commands. - // Here we always round down to the last command boundary. - SessionPoint expectedPoint = commands.empty() ? SequenceNumber(0) : SessionPoint(commands.front(),0); - SessionState::ReplayRange replay = getState()->senderExpected(expectedPoint); - sendCommandPoint(expectedPoint); - std::for_each(replay.begin(), replay.end(), out); // replay - } - else - sendCommandPoint(getState()->senderGetCommandPoint()); -} - -void SessionHandler::confirmed(const SequenceSet& commands, const Array& /*fragments*/) { - checkAttached(); - // Ignore non-contiguous confirmations. - if (!commands.empty() && commands.front() >= getState()->senderGetReplayPoint()) - getState()->senderConfirmed(commands.rangesBegin()->last()); -} - -void SessionHandler::completed(const SequenceSet& commands, bool timelyReply) { - checkAttached(); - getState()->senderCompleted(commands); - if (getState()->senderNeedKnownCompleted() || timelyReply) { - peer.knownCompleted(commands); - getState()->senderRecordKnownCompleted(); - } -} - -void SessionHandler::knownCompleted(const SequenceSet& commands) { - checkAttached(); - getState()->receiverKnownCompleted(commands); -} - -void SessionHandler::flush(bool expected, bool confirmed, bool completed) { - checkAttached(); - if (expected) { - SequenceSet expectSet; - if (getState()->hasState()) - expectSet.add(getState()->receiverGetExpected().command); - peer.expected(expectSet, Array()); - } - if (confirmed) { - SequenceSet confirmSet; - if (!getState()->receiverGetUnknownComplete().empty()) - confirmSet.add(getState()->receiverGetUnknownComplete().front(), - getState()->receiverGetReceived().command); - peer.confirmed(confirmSet, Array()); - } - if (completed) - peer.completed(getState()->receiverGetUnknownComplete(), true); -} - -void SessionHandler::gap(const SequenceSet& /*commands*/) { - throw NotImplementedException("session.gap not supported"); -} - -void SessionHandler::sendDetach() -{ - checkAttached(); - awaitingDetached = true; - peer.detach(getState()->getId().getName()); -} - -void SessionHandler::sendCompletion() { - checkAttached(); - const SequenceSet& c = getState()->receiverGetUnknownComplete(); - peer.completed(c, getState()->receiverNeedKnownCompleted()); -} - -void SessionHandler::sendAttach(bool force) { - QPID_LOG(debug, "SessionHandler::sendAttach attach id=" << getState()->getId()); - peer.attach(getState()->getId().getName(), force); - if (getState()->hasState()) - peer.flush(true, true, true); - else - sendCommandPoint(getState()->senderGetCommandPoint()); -} - -void SessionHandler::sendCommandPoint(const SessionPoint& point) { - peer.commandPoint(point.command, point.offset); - if (!sendReady) { - sendReady = true; - readyToSend(); - } -} - -void SessionHandler::markReadyToSend() { - if (!sendReady) { - sendReady = true; - } -} - -void SessionHandler::sendTimeout(uint32_t t) { - checkAttached(); - peer.requestTimeout(t); -} - -void SessionHandler::sendFlush() { - peer.flush(false, true, true); -} - -bool SessionHandler::ready() const { - return sendReady && receiveReady; -} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/amqp_0_10/SessionHandler.h b/cpp/src/qpid/amqp_0_10/SessionHandler.h deleted file mode 100644 index b5b0fe5ee0..0000000000 --- a/cpp/src/qpid/amqp_0_10/SessionHandler.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef QPID_AMQP_0_10_SESSIONHANDLER_H -#define QPID_AMQP_0_10_SESSIONHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/ChannelHandler.h" -#include "qpid/framing/AMQP_AllProxy.h" -#include "qpid/framing/AMQP_AllOperations.h" -#include "qpid/SessionState.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { - -struct SessionException; - -namespace amqp_0_10 { - -/** - * Base SessionHandler with logic common to both client and broker. - * - * A SessionHandler is associated with a channel and can be attached - * to a session state. - */ - -class QPID_COMMON_CLASS_EXTERN SessionHandler : public framing::AMQP_AllOperations::SessionHandler, - public framing::FrameHandler::InOutHandler -{ - public: - QPID_COMMON_EXTERN SessionHandler(framing::FrameHandler* out=0, uint16_t channel=0); - QPID_COMMON_EXTERN ~SessionHandler(); - - void setChannel(uint16_t ch) { channel = ch; } - uint16_t getChannel() const { return channel.get(); } - - void setOutHandler(framing::FrameHandler& h) { channel.next = &h; } - - virtual SessionState* getState() = 0; - virtual framing::FrameHandler* getInHandler() = 0; - - // Non-protocol methods, called locally to initiate some action. - QPID_COMMON_EXTERN void sendDetach(); - QPID_COMMON_EXTERN void sendCompletion(); - QPID_COMMON_EXTERN void sendAttach(bool force); - QPID_COMMON_EXTERN void sendTimeout(uint32_t t); - QPID_COMMON_EXTERN void sendFlush(); - QPID_COMMON_EXTERN void markReadyToSend();//TODO: only needed for inter-broker bridge; cleanup - QPID_COMMON_EXTERN void handleException(const qpid::SessionException& e); - - /** True if the handler is ready to send and receive */ - bool ready() const; - - // Protocol methods - QPID_COMMON_EXTERN void attach(const std::string& name, bool force); - QPID_COMMON_EXTERN void attached(const std::string& name); - QPID_COMMON_EXTERN void detach(const std::string& name); - QPID_COMMON_EXTERN void detached(const std::string& name, uint8_t code); - - QPID_COMMON_EXTERN void requestTimeout(uint32_t t); - QPID_COMMON_EXTERN void timeout(uint32_t t); - - QPID_COMMON_EXTERN void commandPoint(const framing::SequenceNumber& id, uint64_t offset); - QPID_COMMON_EXTERN void expected(const framing::SequenceSet& commands, const framing::Array& fragments); - QPID_COMMON_EXTERN void confirmed(const framing::SequenceSet& commands,const framing::Array& fragments); - QPID_COMMON_EXTERN void completed(const framing::SequenceSet& commands, bool timelyReply); - QPID_COMMON_EXTERN void knownCompleted(const framing::SequenceSet& commands); - QPID_COMMON_EXTERN void flush(bool expected, bool confirmed, bool completed); - QPID_COMMON_EXTERN void gap(const framing::SequenceSet& commands); - - protected: - QPID_COMMON_EXTERN virtual void invoke(const framing::AMQMethodBody& m); - - virtual void setState(const std::string& sessionName, bool force) = 0; - virtual void connectionException(framing::connection::CloseCode code, const std::string& msg) = 0; - virtual void channelException(framing::session::DetachCode, const std::string& msg) = 0; - virtual void executionException(framing::execution::ErrorCode, const std::string& msg) = 0; - virtual void detaching() = 0; - - // Notification of events - virtual void readyToSend() {} - virtual void readyToReceive() {} - - QPID_COMMON_EXTERN virtual void handleDetach(); - QPID_COMMON_EXTERN virtual void handleIn(framing::AMQFrame&); - QPID_COMMON_EXTERN virtual void handleOut(framing::AMQFrame&); - - framing::ChannelHandler channel; - - private: - void checkAttached(); - void sendCommandPoint(const SessionPoint&); - - framing::AMQP_AllProxy::Session peer; - std::string name; - bool awaitingDetached; - bool sendReady, receiveReady; -}; -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_SESSIONHANDLER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Struct.h b/cpp/src/qpid/amqp_0_10/Struct.h deleted file mode 100644 index 29ece84f6e..0000000000 --- a/cpp/src/qpid/amqp_0_10/Struct.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_AMQP_0_10_STRUCT_H -#define QPID_AMQP_0_10_STRUCT_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/built_in_types.h" -#include <iosfwd> - -namespace qpid { -namespace amqp_0_10 { - -// Base classes for complex types. - -template <class V, class CV, class H> struct Visitable { - typedef V Visitor; - typedef CV ConstVisitor; - typedef H Holder; - - virtual ~Visitable() {} - virtual void accept(Visitor&) = 0; - virtual void accept(ConstVisitor&) const = 0; -}; - - -// Note: only coded structs inherit from Struct. -struct StructVisitor; -struct ConstStructVisitor; -struct StructHolder; -struct Struct - : public Visitable<StructVisitor, ConstStructVisitor, StructHolder> -{ - uint8_t getCode() const; - uint8_t getPack() const; - uint8_t getSize() const; - uint8_t getClassCode() const; -}; -std::ostream& operator<<(std::ostream&, const Struct&); - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_STRUCT_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Struct32.cpp b/cpp/src/qpid/amqp_0_10/Struct32.cpp deleted file mode 100644 index 2d38c09c21..0000000000 --- a/cpp/src/qpid/amqp_0_10/Struct32.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/Struct32.h" - -namespace qpid { -namespace amqp_0_10 { - -Struct32::Struct32() { - // FIXME aconway 2008-04-16: this is only here to force a valid - // default-constructed Struct32 for serialize tests, clean up. - *this = in_place<message::MessageResumeResult>(); -} - -std::ostream& operator<<(std::ostream& o, const Struct32& s) { - return o << static_cast<const StructHolder&>(s); -} - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Struct32.h b/cpp/src/qpid/amqp_0_10/Struct32.h deleted file mode 100644 index 2ed73e0b4c..0000000000 --- a/cpp/src/qpid/amqp_0_10/Struct32.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_AMQP_0_10_STRUCT32_H -#define QPID_AMQP_0_10_STRUCT32_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/StructHolder.h" - -namespace qpid { -namespace amqp_0_10 { - -class Struct32 : public StructHolder -{ - public: - Struct32(); - - template <class T> explicit Struct32(const T& t) : StructHolder(t) {} - - template <class S> void serialize(S& s) { s.split(*this); } - - using StructHolder::operator=; - - template <class S> void encode(S& s) const { - s(contentSize()); - const_cast<Struct32*>(this)->StructHolder::serialize(s); - } - - template <class S> void decode(S& s) { - uint32_t contentSz; - s(contentSz); - typename S::ScopedLimit l(s, contentSz); - StructHolder::serialize(s); - } - - private: - uint32_t contentSize() const { - return Codec::size(static_cast<const StructHolder&>(*this)); - } - -}; - -std::ostream& operator<<(std::ostream&, const Struct32&); - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_STRUCT32_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Unit.cpp b/cpp/src/qpid/amqp_0_10/Unit.cpp deleted file mode 100644 index 381de76dcc..0000000000 --- a/cpp/src/qpid/amqp_0_10/Unit.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/Unit.h" -#include "qpid/amqp_0_10/Codec.h" - -namespace qpid { -namespace amqp_0_10 { - -void Unit::updateVariant() { - switch (header.getType()) { - case CONTROL: variant=ControlHolder(); break; - case COMMAND: variant=CommandHolder(); break; - case HEADER: variant=Header(); break; - case BODY: variant=Body(header.getDataSize()); break; - default: assert(0); // FIXME aconway 2008-04-14: exception? - } -} - -struct GetTypeVisitor : public boost::static_visitor<SegmentType> { - SegmentType operator()(const CommandHolder& ) const { return COMMAND; } - SegmentType operator()(const ControlHolder& ) const { return CONTROL; } - SegmentType operator()(const Header& ) const { return HEADER; } - SegmentType operator()(const Body&) const { return BODY; } -}; - -struct GetFlagsVisitor : public boost::static_visitor<uint8_t> { - uint8_t operator()(const CommandHolder& ) const { return FIRST_FRAME|LAST_FRAME|FIRST_SEGMENT; } - uint8_t operator()(const ControlHolder& ) const { return FIRST_FRAME|LAST_FRAME|FIRST_SEGMENT; } - uint8_t operator()(const Header& ) const { return FIRST_FRAME|LAST_FRAME; } - uint8_t operator()(const Body&) const { return 0; } -}; - -void Unit::updateHeader(uint8_t flags) { - GetFlagsVisitor flagger; - header.setFlags(flags | variant.apply_visitor(flagger)); - GetTypeVisitor getter; - header.setType(variant.apply_visitor(getter)); - header.setDataSize(Codec::size(*this)); - // track automatically set from type. - // no channel specified at this point. -} - -std::ostream& operator<<(std::ostream& o, const Unit& u) { - return o << u.getHeader() << " " << u.variant.type().name() << "[" << u.variant << "]"; -} - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Unit.h b/cpp/src/qpid/amqp_0_10/Unit.h deleted file mode 100644 index 0229e07419..0000000000 --- a/cpp/src/qpid/amqp_0_10/Unit.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef QPID_AMQP_0_10_UNIT_H -#define QPID_AMQP_0_10_UNIT_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/ControlHolder.h" -#include "qpid/amqp_0_10/CommandHolder.h" -#include "qpid/amqp_0_10/Header.h" -#include "qpid/amqp_0_10/Body.h" -#include "qpid/amqp_0_10/FrameHeader.h" - -#include <boost/variant.hpp> -#include <ostream> - -namespace qpid { -namespace amqp_0_10 { - -/** - * A Unit contains a frame header and associated value. - * For all types except BODY the frame header is for a complete segment. - */ -class Unit { - public: - explicit Unit(const FrameHeader& h=FrameHeader()) : header(h) { updateVariant(); } - - /** - *@param flags: is ORed with the required flags for type T. - */ - template <class T> - explicit Unit(const T& t, uint8_t flags=0) : variant(t) { updateHeader(flags); } - - void setHeader(FrameHeader& h) { header = h; updateVariant(); } - const FrameHeader& getHeader() const { return header; } - - template<class T> const T* get() const { return boost::get<T>(&variant); } - template<class T> T* get() { return boost::get<T>(&variant); } - template<class T> Unit& operator=(const T& t) { variant=t; return *this; } - - template <class V> typename V::result_type applyVisitor(V& v) const { - variant.apply_visitor(v); - } - - template <class S> void serialize(S& s) { variant.apply_visitor(s); s.split(*this); } - template <class S> void encode(S&) const {} - template <class S> void decode(S&) { updateHeader(header.getFlags()); } - - private: - typedef boost::variant<ControlHolder, CommandHolder, Header, Body> Variant; - - void updateHeader(uint8_t flags); - void updateVariant(); - - Variant variant; - FrameHeader header; - - friend std::ostream& operator<<(std::ostream& o, const Unit& u); -}; - -std::ostream& operator<<(std::ostream& o, const Unit& u); - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_UNIT_H*/ diff --git a/cpp/src/qpid/amqp_0_10/UnitHandler.h b/cpp/src/qpid/amqp_0_10/UnitHandler.h deleted file mode 100644 index 93a8ce573a..0000000000 --- a/cpp/src/qpid/amqp_0_10/UnitHandler.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef QPID_AMQP_0_10_UNITHANDLER_H -#define QPID_AMQP_0_10_UNITHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/Handler.h" - -namespace qpid { -namespace amqp_0_10 { - -class Unit; -typedef framing::Handler<const Unit&> UnitHandler; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_UNITHANDLER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/UnknownStruct.cpp b/cpp/src/qpid/amqp_0_10/UnknownStruct.cpp deleted file mode 100644 index 35445054c9..0000000000 --- a/cpp/src/qpid/amqp_0_10/UnknownStruct.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/StructVisitor.h" -#include "qpid/amqp_0_10/UnknownStruct.h" - -namespace qpid { -namespace amqp_0_10 { - -void UnknownStruct::accept(Visitor& v) { v.visit(*this); } -void UnknownStruct::accept(ConstVisitor& v) const { v.visit(*this); } -std::ostream& operator<<(std::ostream& o, const UnknownStruct& u) { - return o << "UnknownStruct[class=" << u.getClassCode() << " code=" << u.getCode() << "]"; -} - -}} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/UnknownStruct.h b/cpp/src/qpid/amqp_0_10/UnknownStruct.h deleted file mode 100644 index 1c66d8e6af..0000000000 --- a/cpp/src/qpid/amqp_0_10/UnknownStruct.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef QPID_AMQP_0_10_UNKNOWNSTRUCT_H -#define QPID_AMQP_0_10_UNKNOWNSTRUCT_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/Struct.h" -#include <string> - -namespace qpid { -namespace amqp_0_10 { - -class UnknownStruct : public Struct { - public: - static const uint8_t SIZE=4; - static const uint8_t PACK=2; - - template <class S> void serialize(S& s) { s.split(*this); s(data.begin(), data.end()); } - template <class S> void encode(S&) const { } - template <class S> void decode(S& s) { data.resize(s.bytesRemaining()); } - - UnknownStruct(uint8_t cc=0, uint8_t c=0) : classCode(cc), code(c) {} - void accept(Visitor&); - void accept(ConstVisitor&) const; - - uint8_t getClassCode() const { return classCode; } - uint8_t getCode() const { return code; } - - private: - uint8_t classCode, code; - std::string data; -}; - -std::ostream& operator<<(std::ostream&, const UnknownStruct&); - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_UNKNOWNSTRUCT_H*/ diff --git a/cpp/src/qpid/amqp_0_10/UnknownType.cpp b/cpp/src/qpid/amqp_0_10/UnknownType.cpp deleted file mode 100644 index cd45dd76db..0000000000 --- a/cpp/src/qpid/amqp_0_10/UnknownType.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/UnknownType.h" -#include <boost/range/iterator_range.hpp> -#include <ostream> - -namespace qpid { -namespace amqp_0_10 { - -UnknownType::Width UnknownType::WidthTable[16] = { - { 1, 0 }, - { 2, 0 }, - { 4, 0 }, - { 8, 0 }, - { 16, 0 }, - { 32, 0 }, - { 64, 0 }, - { 128, 0 }, - { 0, 1 }, - { 0, 2 }, - { 0, 4 }, - { -1, -1 }, // Invalid - { 5, 0 }, - { 9, 0 }, - { -1, -1 }, // Invalid - { 0, 0 } -}; - -int UnknownType::fixed() const { return WidthTable[code>>4].fixed; } -int UnknownType::variable() const { return WidthTable[code>>4].variable; } -UnknownType::UnknownType(uint8_t c) : code(c) { data.resize(fixed()); } - -std::ostream& operator<<(std::ostream& o, const UnknownType& u) { - return o << boost::make_iterator_range(u.begin(), u.end()) << std::endl; -} - -}} // namespace qpid::amqp_0_10 - diff --git a/cpp/src/qpid/amqp_0_10/UnknownType.h b/cpp/src/qpid/amqp_0_10/UnknownType.h deleted file mode 100644 index 77498871b3..0000000000 --- a/cpp/src/qpid/amqp_0_10/UnknownType.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef QPID_AMQP_0_10_UNKNOWNTYPE_H -#define QPID_AMQP_0_10_UNKNOWNTYPE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/IntegerTypes.h" -#include <vector> -#include <iosfwd> - -namespace qpid { -namespace amqp_0_10 { - -/** Encode/decode an unknown type based on typecode. */ -class UnknownType { - public: - UnknownType(uint8_t code=0); - uint8_t getCode() const { return code; } - /** Size of fixed type or 0 if not fixed/0-length. -1 invalid */ - int fixed() const; - /** Bytes in size type for variable width. -1 invalid */ - int variable() const; - - typedef std::vector<char>::const_iterator const_iterator; - const_iterator begin() const { return data.begin(); } - const_iterator end() const { return data.end(); } - size_t size() const { return data.size(); } - - template <class S> void serialize(S& s) { s.split(*this); } - template <class S> void encode(S& s) const; - template <class S> void decode(S& s); - - private: - uint8_t code; - struct Width { int fixed; int variable; }; - static Width WidthTable[16]; - - std::vector<char> data; -}; - -template <class S> void UnknownType::encode(S& s) const { - switch (variable()) { - case 0: break; - case 1: s(uint8_t(data.size())); break; - case 2: s(uint16_t(data.size())); break; - case 4: s(uint32_t(data.size())); break; - } - s(data.begin(), data.end()); -} - -template <class S> void UnknownType::decode(S& s) { - uint32_t s8; - uint32_t s16; - uint32_t s32; - switch (variable()) { - case 0: break; - case 1: s(s8); data.resize(s8); break; - case 2: s(s16); data.resize(s16); break; - case 4: s(s32); data.resize(s32); break; - } - s(data.begin(), data.end()); -} - -inline uint8_t codeFor(const UnknownType& u) { return u.getCode(); } - -std::ostream& operator<<(std::ostream&, const UnknownType&); - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_UNKNOWNTYPE_H*/ diff --git a/cpp/src/qpid/amqp_0_10/apply.h b/cpp/src/qpid/amqp_0_10/apply.h deleted file mode 100644 index f32b3482ef..0000000000 --- a/cpp/src/qpid/amqp_0_10/apply.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef QPID_AMQP_0_10_APPLY_H -#define QPID_AMQP_0_10_APPLY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <boost/optional.hpp> - -namespace qpid { -namespace amqp_0_10 { - -template <class F, class R=typename F::result_type> struct FunctionAndResult { - F* functor; - boost::optional<R> result; - - FunctionAndResult() : functor(0) {} - template <class T> void invoke(T& t) { result=(*functor)(t); } - template <class T> void invoke(const T& t) { result=(*functor)(t); } - R getResult() { return *result; } -}; - -// void result is special case. -template <class F> struct FunctionAndResult<F, void> { - F* functor; - - FunctionAndResult() : functor(0) {} - template <class T> void invoke(T& t) { (*functor)(t); } - void getResult() {} -}; - -// Metafunction returning correct abstract visitor for Visitable type. -template <class Visitable> struct VisitorType { - typedef typename Visitable::Visitor type; -}; -template <class Visitable> struct VisitorType<const Visitable> { - typedef typename Visitable::ConstVisitor type; -}; - -template <class Visitor, class F> -struct ApplyVisitorBase : public Visitor, public FunctionAndResult<F> {}; - -// Specialize for each visitor type -template <class Visitable, class F> struct ApplyVisitor; - -/** Apply a functor to a visitable object. - * The functor can have operator() overloads for each visitable type - * and/or templated operator(). - */ -template <class F, class Visitable> -typename F::result_type apply(F& functor, Visitable& visitable) { - ApplyVisitor<typename VisitorType<Visitable>::type, F> visitor; - visitor.functor=&functor; - visitable.accept(visitor); - return visitor.getResult(); -} - -template <class F, class Visitable> -typename F::result_type apply(const F& functor, Visitable& visitable) { - ApplyVisitor<typename VisitorType<Visitable>::type, const F> visitor; - visitor.functor=&functor; - visitable.accept(visitor); - return visitor.getResult(); -} - -template <class R> struct ApplyFunctor { typedef R result_type; }; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_APPLY_H*/ diff --git a/cpp/src/qpid/amqp_0_10/built_in_types.h b/cpp/src/qpid/amqp_0_10/built_in_types.h deleted file mode 100644 index e95d1cf3e9..0000000000 --- a/cpp/src/qpid/amqp_0_10/built_in_types.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef QPID_AMQP_0_10_BUILT_IN_TYPES_H -#define QPID_AMQP_0_10_BUILT_IN_TYPES_H -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Serializer.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/Time.h" -#include "qpid/amqp_0_10/Decimal.h" -#include "qpid/amqp_0_10/SerializableString.h" -#include <boost/array.hpp> -#include <boost/range/iterator_range.hpp> -#include <string> -#include <ostream> -#include <vector> - -/**@file Mapping from built-in AMQP types to C++ types */ - -namespace qpid { - -namespace framing { -class SequenceNumber; -class SequenceSet; -} - -namespace amqp_0_10 { - -/** Wrapper that behaves like type T but is a distinct type for - * overloading purposes. Unique allows multiple distinc wrappers. - */ -template <class T, int Unique=0> struct Wrapper { - T value; - Wrapper() {} - Wrapper(const T& x) : value(x) {} - Wrapper& operator=(const T& x) { value=x; return *this; } - operator T&() { return value; } - operator const T&() const { return value; } - template <class S> void serialize(S& s) { s(value); } -}; - -template<class T> -inline std::ostream& operator<<(std::ostream& o, const Wrapper<T>& w) { - return o << w.value; -} - -/** Void type */ -struct Void { template <class S> void serialize(S&) {} }; -inline std::ostream& operator<<(std::ostream& o, const Void&) { return o; } - -/** Bit is a presence indicator - an optional value with no encoding. */ -struct Bit : public Wrapper<bool> { - Bit(bool b=false) : Wrapper<bool>(b) {} - using Wrapper<bool>::operator=; - template <class S> void serialize(S& s) { s.split(*this); } - template <class S> void encode(S&) const { } - template <class S> void decode(S&) { *this = true; } -}; - -inline std::ostream& operator<<(std::ostream& o, const Bit& b) { - return o << bool(b); -} - -// Fixed size types -typedef bool Boolean; -typedef char Char; -typedef int8_t Int8; -typedef int16_t Int16; -typedef int32_t Int32; -typedef int64_t Int64; -typedef uint8_t Uint8; -typedef uint16_t Uint16; -typedef uint32_t Uint32; -typedef uint64_t Uint64; -typedef Wrapper<uint32_t> CharUtf32; - -template <size_t N> struct Bin : public boost::array<char, N> { - template <class S> void serialize(S& s) { s.raw(this->begin(), this->size()); } -}; - -template <size_t N> std::ostream& operator<<(std::ostream& o, const Bin<N>& b) { - return o << boost::make_iterator_range(b.begin(), b.end()); -} - -template <> struct Bin<1> : public boost::array<char, 1> { - Bin(char c=0) { this->front() = c; } - operator char() { return this->front(); } - template <class S> void serialize(S& s) { s(front()); } -}; - -typedef Bin<1> Bin8; -typedef Bin<128> Bin1024; -typedef Bin<16> Bin128; -typedef Bin<2> Bin16; -typedef Bin<32> Bin256; -typedef Bin<4> Bin32; -typedef Bin<5> Bin40; -typedef Bin<64> Bin512; -typedef Bin<8> Bin64; -typedef Bin<9> Bin72; - -typedef double Double; -typedef float Float; -typedef framing::SequenceNumber SequenceNo; -using framing::Uuid; -typedef sys::AbsTime Datetime; - -typedef Decimal<Uint8, Int32> Dec32; -typedef Decimal<Uint8, Int64> Dec64; - -// Variable width types - -typedef SerializableString<Uint8, Uint8> Vbin8; -typedef SerializableString<char, Uint8, 1> Str8Latin; -typedef SerializableString<char, Uint8> Str8; -typedef SerializableString<Uint16, Uint8> Str8Utf16; - -typedef SerializableString<Uint8, Uint16> Vbin16; -typedef SerializableString<char, Uint16, 1> Str16Latin; -typedef SerializableString<char, Uint16> Str16; -typedef SerializableString<Uint16, Uint16> Str16Utf16; - -typedef SerializableString<Uint8, Uint32> Vbin32; - -typedef framing::SequenceSet SequenceSet; - -// Forward declare class types. -class Map; -class Struct32; -class UnknownType; - -template <class T> struct ArrayDomain; -typedef ArrayDomain<UnknownType> Array; - -// FIXME aconway 2008-04-08: TODO -struct ByteRanges { template <class S> void serialize(S&) {} }; -struct List { template <class S> void serialize(S&) {} }; - -// FIXME aconway 2008-03-10: dummy ostream operators -inline std::ostream& operator<<(std::ostream& o, const ByteRanges&) { return o; } -inline std::ostream& operator<<(std::ostream& o, const SequenceSet&) { return o; } -inline std::ostream& operator<<(std::ostream& o, const List&) { return o; } - -enum SegmentType { CONTROL, COMMAND, HEADER, BODY }; - -inline SerializeAs<SegmentType, uint8_t> serializable(SegmentType& st) { - return SerializeAs<SegmentType, uint8_t>(st); -} - - -}} // namespace qpid::amqp_0_10 - -#endif diff --git a/cpp/src/qpid/amqp_0_10/complex_types.cpp b/cpp/src/qpid/amqp_0_10/complex_types.cpp deleted file mode 100644 index 656d363ba6..0000000000 --- a/cpp/src/qpid/amqp_0_10/complex_types.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/UnknownStruct.h" -#include "qpid/amqp_0_10/ApplyCommand.h" -#include "qpid/amqp_0_10/ApplyControl.h" -#include "qpid/amqp_0_10/ApplyStruct.h" -#include "qpid/amqp_0_10/apply.h" -#include <iostream> - -namespace qpid { -namespace amqp_0_10 { -// Functors for getting static values from a visitable base type. - -#define QPID_STATIC_VALUE_GETTER(NAME, TYPE, VALUE) \ - struct NAME : public ApplyFunctor<TYPE> { \ - template <class T> TYPE operator()(const T&) const { return T::VALUE; }\ - } - -QPID_STATIC_VALUE_GETTER(GetCode, uint8_t, CODE); -QPID_STATIC_VALUE_GETTER(GetSize, uint8_t, SIZE); -QPID_STATIC_VALUE_GETTER(GetPack, uint8_t, PACK); -QPID_STATIC_VALUE_GETTER(GetClassCode, uint8_t, CLASS_CODE); -QPID_STATIC_VALUE_GETTER(GetName, const char*, NAME); -QPID_STATIC_VALUE_GETTER(GetClassName, const char*, CLASS_NAME); - - -uint8_t Command::getCode() const { return apply(GetCode(), *this); } -uint8_t Command::getClassCode() const { return apply(GetClassCode(), *this); } -const char* Command::getName() const { return apply(GetName(), *this); } -const char* Command::getClassName() const { return apply(GetClassName(), *this); } - -uint8_t Control::getCode() const { return apply(GetCode(), *this); } -uint8_t Control::getClassCode() const { return apply(GetClassCode(), *this); } -const char* Control::getName() const { return apply(GetName(), *this); } -const char* Control::getClassName() const { return apply(GetClassName(), *this); } - -// Special cases for UnknownStruct -struct GetStructCode : public GetCode { - using GetCode::operator(); - uint8_t operator()(const UnknownStruct& u) const { return u.getCode(); } -}; - -struct GetStructClassCode : public GetClassCode { - using GetClassCode::operator(); - uint8_t operator()(const UnknownStruct& u) const { return u.getClassCode(); } -}; - -uint8_t Struct::getCode() const { return apply(GetStructCode(), *this); } -uint8_t Struct::getClassCode() const { return apply(GetStructClassCode(), *this); } -uint8_t Struct::getPack() const { return apply(GetPack(), *this); } -uint8_t Struct::getSize() const { return apply(GetSize(), *this); } - -struct PrintVisitor { - typedef std::ostream& result_type; - std::ostream& out; - PrintVisitor(std::ostream& o) : out(o) {} - template <class T> result_type operator()(const T& t) const { return out << t; } -}; - -std::ostream& operator<<(std::ostream& o, const Command& x) { return apply(PrintVisitor(o), x); } -std::ostream& operator<<(std::ostream& o, const Control& x) { return apply(PrintVisitor(o), x); } -std::ostream& operator<<(std::ostream& o, const Struct& x) { return apply(PrintVisitor(o), x); } - -}} // namespace qpid::amqp_0_10 - diff --git a/cpp/src/qpid/assert.cpp b/cpp/src/qpid/assert.cpp deleted file mode 100644 index 801bfa6ae5..0000000000 --- a/cpp/src/qpid/assert.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_ASSERT_CPP -#define QPID_ASSERT_CPP - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <sstream> -#include <iostream> -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include <stdlib.h> - -namespace qpid { - -void assert_fail(char const * expr, char const * function, char const * file, long line) { - std::ostringstream msg; - msg << "Assertion failed: " << expr << " in function " << function - << "(" << file << ":" << line << ")"; - QPID_LOG(critical, msg.str()); -#ifdef NDEBUG - throw framing::InternalErrorException(msg.str()); -#else - std::cerr << msg.str() << std::endl; - abort(); -#endif -} - -} // namespace qpid - -#endif /*!QPID_ASSERT_CPP*/ diff --git a/cpp/src/qpid/assert.h b/cpp/src/qpid/assert.h deleted file mode 100644 index 49e7c5355d..0000000000 --- a/cpp/src/qpid/assert.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef QPID_ASSERT_H -#define QPID_ASSERT_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/current_function.hpp> - -/** - * Abort if !expr in debug mode, throw an exception if NDEBUG is set. - */ -#define QPID_ASSERT(expr) ((expr) ? static_cast<void>(0) : ::qpid::assert_fail(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) - -namespace qpid { - -void assert_fail(char const * expr, char const * function, char const * file, long line); - -} // namespace qpid - -#endif /*!QPID_ASSERT_H*/ diff --git a/cpp/src/qpid/broker/AclModule.h b/cpp/src/qpid/broker/AclModule.h deleted file mode 100644 index 2f4f7eaacc..0000000000 --- a/cpp/src/qpid/broker/AclModule.h +++ /dev/null @@ -1,281 +0,0 @@ -#ifndef QPID_ACLMODULE_ACL_H -#define QPID_ACLMODULE_ACL_H - - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "qpid/RefCounted.h" -#include <boost/shared_ptr.hpp> -#include <map> -#include <set> -#include <string> -#include <sstream> - -namespace qpid { - -namespace acl { - -enum ObjectType {OBJ_QUEUE, OBJ_EXCHANGE, OBJ_BROKER, OBJ_LINK, - OBJ_METHOD, OBJECTSIZE}; // OBJECTSIZE must be last in list -enum Action {ACT_CONSUME, ACT_PUBLISH, ACT_CREATE, ACT_ACCESS, ACT_BIND, - ACT_UNBIND, ACT_DELETE, ACT_PURGE, ACT_UPDATE, - ACTIONSIZE}; // ACTIONSIZE must be last in list -enum Property {PROP_NAME, PROP_DURABLE, PROP_OWNER, PROP_ROUTINGKEY, - PROP_PASSIVE, PROP_AUTODELETE, PROP_EXCLUSIVE, PROP_TYPE, - PROP_ALTERNATE, PROP_QUEUENAME, PROP_SCHEMAPACKAGE, - PROP_SCHEMACLASS, PROP_POLICYTYPE, PROP_MAXQUEUESIZE, - PROP_MAXQUEUECOUNT}; -enum AclResult {ALLOW, ALLOWLOG, DENY, DENYLOG}; - -} // namespace acl - -namespace broker { - - -class AclModule -{ - -public: - - // effienty turn off ACL on message transfer. - virtual bool doTransferAcl()=0; - - virtual bool authorise(const std::string& id, const acl::Action& action, const acl::ObjectType& objType, const std::string& name, - std::map<acl::Property, std::string>* params=0)=0; - virtual bool authorise(const std::string& id, const acl::Action& action, const acl::ObjectType& objType, const std::string& ExchangeName, - const std::string& RoutingKey)=0; - // create specilied authorise methods for cases that need faster matching as needed. - - virtual ~AclModule() {}; -}; - -} // namespace broker - -namespace acl { - -class AclHelper { - private: - AclHelper(){} - public: - static inline ObjectType getObjectType(const std::string& str) { - if (str.compare("queue") == 0) return OBJ_QUEUE; - if (str.compare("exchange") == 0) return OBJ_EXCHANGE; - if (str.compare("broker") == 0) return OBJ_BROKER; - if (str.compare("link") == 0) return OBJ_LINK; - if (str.compare("method") == 0) return OBJ_METHOD; - throw str; - } - static inline std::string getObjectTypeStr(const ObjectType o) { - switch (o) { - case OBJ_QUEUE: return "queue"; - case OBJ_EXCHANGE: return "exchange"; - case OBJ_BROKER: return "broker"; - case OBJ_LINK: return "link"; - case OBJ_METHOD: return "method"; - default: assert(false); // should never get here - } - return ""; - } - static inline Action getAction(const std::string& str) { - if (str.compare("consume") == 0) return ACT_CONSUME; - if (str.compare("publish") == 0) return ACT_PUBLISH; - if (str.compare("create") == 0) return ACT_CREATE; - if (str.compare("access") == 0) return ACT_ACCESS; - if (str.compare("bind") == 0) return ACT_BIND; - if (str.compare("unbind") == 0) return ACT_UNBIND; - if (str.compare("delete") == 0) return ACT_DELETE; - if (str.compare("purge") == 0) return ACT_PURGE; - if (str.compare("update") == 0) return ACT_UPDATE; - throw str; - } - static inline std::string getActionStr(const Action a) { - switch (a) { - case ACT_CONSUME: return "consume"; - case ACT_PUBLISH: return "publish"; - case ACT_CREATE: return "create"; - case ACT_ACCESS: return "access"; - case ACT_BIND: return "bind"; - case ACT_UNBIND: return "unbind"; - case ACT_DELETE: return "delete"; - case ACT_PURGE: return "purge"; - case ACT_UPDATE: return "update"; - default: assert(false); // should never get here - } - return ""; - } - static inline Property getProperty(const std::string& str) { - if (str.compare("name") == 0) return PROP_NAME; - if (str.compare("durable") == 0) return PROP_DURABLE; - if (str.compare("owner") == 0) return PROP_OWNER; - if (str.compare("routingkey") == 0) return PROP_ROUTINGKEY; - if (str.compare("passive") == 0) return PROP_PASSIVE; - if (str.compare("autodelete") == 0) return PROP_AUTODELETE; - if (str.compare("exclusive") == 0) return PROP_EXCLUSIVE; - if (str.compare("type") == 0) return PROP_TYPE; - if (str.compare("alternate") == 0) return PROP_ALTERNATE; - if (str.compare("queuename") == 0) return PROP_QUEUENAME; - if (str.compare("schemapackage") == 0) return PROP_SCHEMAPACKAGE; - if (str.compare("schemaclass") == 0) return PROP_SCHEMACLASS; - if (str.compare("policytype") == 0) return PROP_POLICYTYPE; - if (str.compare("maxqueuesize") == 0) return PROP_MAXQUEUESIZE; - if (str.compare("maxqueuecount") == 0) return PROP_MAXQUEUECOUNT; - throw str; - } - static inline std::string getPropertyStr(const Property p) { - switch (p) { - case PROP_NAME: return "name"; - case PROP_DURABLE: return "durable"; - case PROP_OWNER: return "owner"; - case PROP_ROUTINGKEY: return "routingkey"; - case PROP_PASSIVE: return "passive"; - case PROP_AUTODELETE: return "autodelete"; - case PROP_EXCLUSIVE: return "exclusive"; - case PROP_TYPE: return "type"; - case PROP_ALTERNATE: return "alternate"; - case PROP_QUEUENAME: return "queuename"; - case PROP_SCHEMAPACKAGE: return "schemapackage"; - case PROP_SCHEMACLASS: return "schemaclass"; - case PROP_POLICYTYPE: return "policytype"; - case PROP_MAXQUEUESIZE: return "maxqueuesize"; - case PROP_MAXQUEUECOUNT: return "maxqueuecount"; - default: assert(false); // should never get here - } - return ""; - } - static inline AclResult getAclResult(const std::string& str) { - if (str.compare("allow") == 0) return ALLOW; - if (str.compare("allow-log") == 0) return ALLOWLOG; - if (str.compare("deny") == 0) return DENY; - if (str.compare("deny-log") == 0) return DENYLOG; - throw str; - } - static inline std::string getAclResultStr(const AclResult r) { - switch (r) { - case ALLOW: return "allow"; - case ALLOWLOG: return "allow-log"; - case DENY: return "deny"; - case DENYLOG: return "deny-log"; - default: assert(false); // should never get here - } - return ""; - } - - typedef std::set<Property> propSet; - typedef boost::shared_ptr<propSet> propSetPtr; - typedef std::pair<Action, propSetPtr> actionPair; - typedef std::map<Action, propSetPtr> actionMap; - typedef boost::shared_ptr<actionMap> actionMapPtr; - typedef std::pair<ObjectType, actionMapPtr> objectPair; - typedef std::map<ObjectType, actionMapPtr> objectMap; - typedef objectMap::const_iterator omCitr; - typedef boost::shared_ptr<objectMap> objectMapPtr; - typedef std::map<Property, std::string> propMap; - typedef propMap::const_iterator propMapItr; - - // This map contains the legal combinations of object/action/properties found in an ACL file - static void loadValidationMap(objectMapPtr& map) { - if (!map.get()) return; - map->clear(); - propSetPtr p0; // empty ptr, used for no properties - - // == Exchanges == - - propSetPtr p1(new propSet); - p1->insert(PROP_TYPE); - p1->insert(PROP_ALTERNATE); - p1->insert(PROP_PASSIVE); - p1->insert(PROP_DURABLE); - - propSetPtr p2(new propSet); - p2->insert(PROP_ROUTINGKEY); - - propSetPtr p3(new propSet); - p3->insert(PROP_QUEUENAME); - p3->insert(PROP_ROUTINGKEY); - - actionMapPtr a0(new actionMap); - a0->insert(actionPair(ACT_CREATE, p1)); - a0->insert(actionPair(ACT_DELETE, p0)); - a0->insert(actionPair(ACT_ACCESS, p0)); - a0->insert(actionPair(ACT_BIND, p2)); - a0->insert(actionPair(ACT_UNBIND, p2)); - a0->insert(actionPair(ACT_ACCESS, p3)); - a0->insert(actionPair(ACT_PUBLISH, p0)); - - map->insert(objectPair(OBJ_EXCHANGE, a0)); - - // == Queues == - - propSetPtr p4(new propSet); - p4->insert(PROP_ALTERNATE); - p4->insert(PROP_PASSIVE); - p4->insert(PROP_DURABLE); - p4->insert(PROP_EXCLUSIVE); - p4->insert(PROP_AUTODELETE); - p4->insert(PROP_POLICYTYPE); - p4->insert(PROP_MAXQUEUESIZE); - p4->insert(PROP_MAXQUEUECOUNT); - - actionMapPtr a1(new actionMap); - a1->insert(actionPair(ACT_ACCESS, p0)); - a1->insert(actionPair(ACT_CREATE, p4)); - a1->insert(actionPair(ACT_PURGE, p0)); - a1->insert(actionPair(ACT_DELETE, p0)); - a1->insert(actionPair(ACT_CONSUME, p0)); - - map->insert(objectPair(OBJ_QUEUE, a1)); - - // == Links == - - actionMapPtr a2(new actionMap); - a2->insert(actionPair(ACT_CREATE, p0)); - - map->insert(objectPair(OBJ_LINK, a2)); - - // == Method == - - propSetPtr p5(new propSet); - p5->insert(PROP_SCHEMAPACKAGE); - p5->insert(PROP_SCHEMACLASS); - - actionMapPtr a4(new actionMap); - a4->insert(actionPair(ACT_ACCESS, p5)); - - map->insert(objectPair(OBJ_METHOD, a4)); - } - - static std::string propertyMapToString(const std::map<Property, std::string>* params) { - std::ostringstream ss; - ss << "{"; - if (params) - { - for (propMapItr pMItr = params->begin(); pMItr != params->end(); pMItr++) { - ss << " " << getPropertyStr((Property) pMItr-> first) << "=" << pMItr->second; - } - } - ss << " }"; - return ss.str(); - } -}; - - -}} // namespace qpid::acl - -#endif // QPID_ACLMODULE_ACL_H diff --git a/cpp/src/qpid/broker/AsyncCompletion.h b/cpp/src/qpid/broker/AsyncCompletion.h deleted file mode 100644 index fef994438f..0000000000 --- a/cpp/src/qpid/broker/AsyncCompletion.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef _AsyncCompletion_ -#define _AsyncCompletion_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/intrusive_ptr.hpp> - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Monitor.h" - -namespace qpid { -namespace broker { - -/** - * Class to implement asynchronous notification of completion. - * - * Use-case: An "initiator" needs to wait for a set of "completers" to - * finish a unit of work before an action can occur. This object - * tracks the progress of the set of completers, and allows the action - * to occur once all completers have signalled that they are done. - * - * The initiator and completers may be running in separate threads. - * - * The initiating thread is the thread that initiates the action, - * i.e. the connection read thread. - * - * A completing thread is any thread that contributes to completion, - * e.g. a store thread that does an async write. - * There may be zero or more completers. - * - * When the work is complete, a callback is invoked. The callback - * may be invoked in the Initiator thread, or one of the Completer - * threads. The callback is passed a flag indicating whether or not - * the callback is running under the context of the Initiator thread. - * - * Use model: - * 1) Initiator thread invokes begin() - * 2) After begin() has been invoked, zero or more Completers invoke - * startCompleter(). Completers may be running in the same or - * different thread as the Initiator, as long as they guarantee that - * startCompleter() is invoked at least once before the Initiator invokes end(). - * 3) Completers may invoke finishCompleter() at any time, even after the - * initiator has invoked end(). finishCompleter() may be called from any - * thread. - * 4) startCompleter()/finishCompleter() calls "nest": for each call to - * startCompleter(), a corresponding call to finishCompleter() must be made. - * Once the last finishCompleter() is called, the Completer must no longer - * reference the completion object. - * 5) The Initiator invokes end() at the point where it has finished - * dispatching work to the Completers, and is prepared for the callback - * handler to be invoked. Note: if there are no outstanding Completers - * pending when the Initiator invokes end(), the callback will be invoked - * directly, and the sync parameter will be set true. This indicates to the - * Initiator that the callback is executing in the context of the end() call, - * and the Initiator is free to optimize the handling of the completion, - * assuming no need for synchronization with Completer threads. - */ - -class AsyncCompletion -{ - public: - - /** Supplied by the Initiator to the end() method, allows for a callback - * when all outstanding completers are done. If the callback cannot be - * made during the end() call, the clone() method must supply a copy of - * this callback object that persists after end() returns. The cloned - * callback object will be used by the last completer thread, and - * released when the callback returns. - */ - class Callback : public RefCounted - { - public: - virtual void completed(bool) = 0; - virtual boost::intrusive_ptr<Callback> clone() = 0; - }; - - private: - mutable qpid::sys::AtomicValue<uint32_t> completionsNeeded; - mutable qpid::sys::Monitor callbackLock; - bool inCallback, active; - - void invokeCallback(bool sync) { - qpid::sys::Mutex::ScopedLock l(callbackLock); - if (active) { - if (callback.get()) { - inCallback = true; - { - qpid::sys::Mutex::ScopedUnlock ul(callbackLock); - callback->completed(sync); - } - inCallback = false; - callback = boost::intrusive_ptr<Callback>(); - callbackLock.notifyAll(); - } - active = false; - } - } - - protected: - /** Invoked when all completers have signalled that they have completed - * (via calls to finishCompleter()). bool == true if called via end() - */ - boost::intrusive_ptr<Callback> callback; - - public: - AsyncCompletion() : completionsNeeded(0), inCallback(false), active(true) {}; - virtual ~AsyncCompletion() { cancel(); } - - - /** True when all outstanding operations have compeleted - */ - bool isDone() - { - return !active; - } - - /** Called to signal the start of an asynchronous operation. The operation - * is considered pending until finishCompleter() is called. - * E.g. called when initiating an async store operation. - */ - void startCompleter() { ++completionsNeeded; } - - /** Called by completer to signal that it has finished the operation started - * when startCompleter() was invoked. - * e.g. called when async write complete. - */ - void finishCompleter() - { - if (--completionsNeeded == 0) { - invokeCallback(false); - } - } - - /** called by initiator before any calls to startCompleter can be done. - */ - void begin() - { - ++completionsNeeded; - } - - /** called by initiator after all potential completers have called - * startCompleter(). - */ - void end(Callback& cb) - { - assert(completionsNeeded.get() > 0); // ensure begin() has been called! - // the following only "decrements" the count if it is 1. This means - // there are no more outstanding completers and we are done. - if (completionsNeeded.boolCompareAndSwap(1, 0)) { - // done! Complete immediately - cb.completed(true); - return; - } - - // the compare-and-swap did not succeed. This means there are - // outstanding completers pending (count > 1). Get a persistent - // Callback object to use when the last completer is done. - // Decrement after setting up the callback ensures that pending - // completers cannot touch the callback until it is ready. - callback = cb.clone(); - if (--completionsNeeded == 0) { - // note that a completer may have completed during the - // callback setup or decrement: - invokeCallback(true); - } - } - - /** may be called by Initiator to cancel the callback. Will wait for - * callback to complete if in progress. - */ - virtual void cancel() { - qpid::sys::Mutex::ScopedLock l(callbackLock); - while (inCallback) callbackLock.wait(); - callback = boost::intrusive_ptr<Callback>(); - active = false; - } -}; - -}} // qpid::broker:: -#endif /*!_AsyncCompletion_*/ diff --git a/cpp/src/qpid/broker/Bridge.cpp b/cpp/src/qpid/broker/Bridge.cpp deleted file mode 100644 index 7fbbf4e2c4..0000000000 --- a/cpp/src/qpid/broker/Bridge.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Bridge.h" -#include "qpid/broker/FedOps.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/SessionState.h" - -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/Uuid.h" -#include "qpid/log/Statement.h" -#include <iostream> - -using qpid::framing::FieldTable; -using qpid::framing::Uuid; -using qpid::framing::Buffer; -using qpid::management::ManagementAgent; -using std::string; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -void Bridge::PushHandler::handle(framing::AMQFrame& frame) -{ - conn->received(frame); -} - -Bridge::Bridge(Link* _link, framing::ChannelId _id, CancellationListener l, - const _qmf::ArgsLinkBridge& _args) : - link(_link), id(_id), args(_args), mgmtObject(0), - listener(l), name(Uuid(true).str()), queueName("bridge_queue_"), persistenceId(0) -{ - std::stringstream title; - title << id << "_" << link->getBroker()->getFederationTag(); - queueName += title.str(); - ManagementAgent* agent = link->getBroker()->getManagementAgent(); - if (agent != 0) { - mgmtObject = new _qmf::Bridge - (agent, this, link, id, args.i_durable, args.i_src, args.i_dest, - args.i_key, args.i_srcIsQueue, args.i_srcIsLocal, - args.i_tag, args.i_excludes, args.i_dynamic, args.i_sync); - agent->addObject(mgmtObject); - } - QPID_LOG(debug, "Bridge created from " << args.i_src << " to " << args.i_dest); -} - -Bridge::~Bridge() -{ - mgmtObject->resourceDestroy(); -} - -void Bridge::create(Connection& c) -{ - connState = &c; - conn = &c; - FieldTable options; - if (args.i_sync) options.setInt("qpid.sync_frequency", args.i_sync); - SessionHandler& sessionHandler = c.getChannel(id); - if (args.i_srcIsLocal) { - if (args.i_dynamic) - throw Exception("Dynamic routing not supported for push routes"); - // Point the bridging commands at the local connection handler - pushHandler.reset(new PushHandler(&c)); - channelHandler.reset(new framing::ChannelHandler(id, pushHandler.get())); - - session.reset(new framing::AMQP_ServerProxy::Session(*channelHandler)); - peer.reset(new framing::AMQP_ServerProxy(*channelHandler)); - - session->attach(name, false); - session->commandPoint(0,0); - } else { - sessionHandler.attachAs(name); - // Point the bridging commands at the remote peer broker - peer.reset(new framing::AMQP_ServerProxy(sessionHandler.out)); - } - - if (args.i_srcIsLocal) sessionHandler.getSession()->disableReceiverTracking(); - if (args.i_srcIsQueue) { - peer->getMessage().subscribe(args.i_src, args.i_dest, args.i_sync ? 0 : 1, 0, false, "", 0, options); - peer->getMessage().flow(args.i_dest, 0, 0xFFFFFFFF); - peer->getMessage().flow(args.i_dest, 1, 0xFFFFFFFF); - QPID_LOG(debug, "Activated route from queue " << args.i_src << " to " << args.i_dest); - } else { - FieldTable queueSettings; - - if (args.i_tag.size()) { - queueSettings.setString("qpid.trace.id", args.i_tag); - } else { - const string& peerTag = c.getFederationPeerTag(); - if (peerTag.size()) - queueSettings.setString("qpid.trace.id", peerTag); - } - - if (args.i_excludes.size()) { - queueSettings.setString("qpid.trace.exclude", args.i_excludes); - } else { - const string& localTag = link->getBroker()->getFederationTag(); - if (localTag.size()) - queueSettings.setString("qpid.trace.exclude", localTag); - } - - bool durable = false;//should this be an arg, or would we use srcIsQueue for durable queues? - bool autoDelete = !durable;//auto delete transient queues? - peer->getQueue().declare(queueName, "", false, durable, true, autoDelete, queueSettings); - if (!args.i_dynamic) - peer->getExchange().bind(queueName, args.i_src, args.i_key, FieldTable()); - peer->getMessage().subscribe(queueName, args.i_dest, 1, 0, false, "", 0, FieldTable()); - peer->getMessage().flow(args.i_dest, 0, 0xFFFFFFFF); - peer->getMessage().flow(args.i_dest, 1, 0xFFFFFFFF); - - if (args.i_dynamic) { - Exchange::shared_ptr exchange = link->getBroker()->getExchanges().get(args.i_src); - if (exchange.get() == 0) - throw Exception("Exchange not found for dynamic route"); - exchange->registerDynamicBridge(this); - QPID_LOG(debug, "Activated dynamic route for exchange " << args.i_src); - } else { - QPID_LOG(debug, "Activated static route from exchange " << args.i_src << " to " << args.i_dest); - } - } - if (args.i_srcIsLocal) sessionHandler.getSession()->enableReceiverTracking(); -} - -void Bridge::cancel(Connection&) -{ - if (resetProxy()) { - peer->getMessage().cancel(args.i_dest); - peer->getSession().detach(name); - } -} - -void Bridge::closed() -{ - if (args.i_dynamic) { - Exchange::shared_ptr exchange = link->getBroker()->getExchanges().get(args.i_src); - if (exchange.get() != 0) - exchange->removeDynamicBridge(this); - } -} - -void Bridge::destroy() -{ - listener(this); -} - -void Bridge::setPersistenceId(uint64_t pId) const -{ - persistenceId = pId; -} - -const string& Bridge::getName() const -{ - return name; -} - -Bridge::shared_ptr Bridge::decode(LinkRegistry& links, Buffer& buffer) -{ - string host; - uint16_t port; - string src; - string dest; - string key; - string id; - string excludes; - - buffer.getShortString(host); - port = buffer.getShort(); - bool durable(buffer.getOctet()); - buffer.getShortString(src); - buffer.getShortString(dest); - buffer.getShortString(key); - bool is_queue(buffer.getOctet()); - bool is_local(buffer.getOctet()); - buffer.getShortString(id); - buffer.getShortString(excludes); - bool dynamic(buffer.getOctet()); - uint16_t sync = buffer.getShort(); - - return links.declare(host, port, durable, src, dest, key, - is_queue, is_local, id, excludes, dynamic, sync).first; -} - -void Bridge::encode(Buffer& buffer) const -{ - buffer.putShortString(string("bridge")); - buffer.putShortString(link->getHost()); - buffer.putShort(link->getPort()); - buffer.putOctet(args.i_durable ? 1 : 0); - buffer.putShortString(args.i_src); - buffer.putShortString(args.i_dest); - buffer.putShortString(args.i_key); - buffer.putOctet(args.i_srcIsQueue ? 1 : 0); - buffer.putOctet(args.i_srcIsLocal ? 1 : 0); - buffer.putShortString(args.i_tag); - buffer.putShortString(args.i_excludes); - buffer.putOctet(args.i_dynamic ? 1 : 0); - buffer.putShort(args.i_sync); -} - -uint32_t Bridge::encodedSize() const -{ - return link->getHost().size() + 1 // short-string (host) - + 7 // short-string ("bridge") - + 2 // port - + 1 // durable - + args.i_src.size() + 1 - + args.i_dest.size() + 1 - + args.i_key.size() + 1 - + 1 // srcIsQueue - + 1 // srcIsLocal - + args.i_tag.size() + 1 - + args.i_excludes.size() + 1 - + 1 // dynamic - + 2; // sync -} - -management::ManagementObject* Bridge::GetManagementObject (void) const -{ - return (management::ManagementObject*) mgmtObject; -} - -management::Manageable::status_t Bridge::ManagementMethod(uint32_t methodId, - management::Args& /*args*/, - string&) -{ - if (methodId == _qmf::Bridge::METHOD_CLOSE) { - //notify that we are closed - destroy(); - return management::Manageable::STATUS_OK; - } else { - return management::Manageable::STATUS_UNKNOWN_METHOD; - } -} - -void Bridge::propagateBinding(const string& key, const string& tagList, - const string& op, const string& origin, - qpid::framing::FieldTable* extra_args) -{ - const string& localTag = link->getBroker()->getFederationTag(); - const string& peerTag = connState->getFederationPeerTag(); - - if (tagList.find(peerTag) == tagList.npos) { - FieldTable bindArgs; - if (extra_args) { - for (qpid::framing::FieldTable::ValueMap::iterator i=extra_args->begin(); i != extra_args->end(); ++i) { - bindArgs.insert((*i)); - } - } - string newTagList(tagList + string(tagList.empty() ? "" : ",") + localTag); - - bindArgs.setString(qpidFedOp, op); - bindArgs.setString(qpidFedTags, newTagList); - if (origin.empty()) - bindArgs.setString(qpidFedOrigin, localTag); - else - bindArgs.setString(qpidFedOrigin, origin); - - conn->requestIOProcessing(boost::bind(&Bridge::ioThreadPropagateBinding, this, - queueName, args.i_src, key, bindArgs)); - } -} - -void Bridge::sendReorigin() -{ - FieldTable bindArgs; - - bindArgs.setString(qpidFedOp, fedOpReorigin); - bindArgs.setString(qpidFedTags, link->getBroker()->getFederationTag()); - - conn->requestIOProcessing(boost::bind(&Bridge::ioThreadPropagateBinding, this, - queueName, args.i_src, args.i_key, bindArgs)); -} -bool Bridge::resetProxy() -{ - SessionHandler& sessionHandler = conn->getChannel(id); - if (!sessionHandler.getSession()) peer.reset(); - else peer.reset(new framing::AMQP_ServerProxy(sessionHandler.out)); - return peer.get(); -} - -void Bridge::ioThreadPropagateBinding(const string& queue, const string& exchange, const string& key, FieldTable args) -{ - if (resetProxy()) { - peer->getExchange().bind(queue, exchange, key, args); - } else { - QPID_LOG(error, "Cannot propagate binding for dynamic bridge as session has been detached, deleting dynamic bridge"); - destroy(); - } -} - -bool Bridge::containsLocalTag(const string& tagList) const -{ - const string& localTag = link->getBroker()->getFederationTag(); - return (tagList.find(localTag) != tagList.npos); -} - -const string& Bridge::getLocalTag() const -{ - return link->getBroker()->getFederationTag(); -} - -}} diff --git a/cpp/src/qpid/broker/Bridge.h b/cpp/src/qpid/broker/Bridge.h deleted file mode 100644 index a846254c57..0000000000 --- a/cpp/src/qpid/broker/Bridge.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Bridge_ -#define _Bridge_ - -#include "qpid/broker/PersistableConfig.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/framing/ChannelHandler.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/management/Manageable.h" -#include "qpid/broker/Exchange.h" -#include "qmf/org/apache/qpid/broker/ArgsLinkBridge.h" -#include "qmf/org/apache/qpid/broker/Bridge.h" - -#include <boost/function.hpp> -#include <memory> - -namespace qpid { -namespace broker { - -class Connection; -class ConnectionState; -class Link; -class LinkRegistry; - -class Bridge : public PersistableConfig, public management::Manageable, public Exchange::DynamicBridge -{ -public: - typedef boost::shared_ptr<Bridge> shared_ptr; - typedef boost::function<void(Bridge*)> CancellationListener; - - Bridge(Link* link, framing::ChannelId id, CancellationListener l, - const qmf::org::apache::qpid::broker::ArgsLinkBridge& args); - ~Bridge(); - - void create(Connection& c); - void cancel(Connection& c); - void closed(); - void destroy(); - bool isDurable() { return args.i_durable; } - - management::ManagementObject* GetManagementObject() const; - management::Manageable::status_t ManagementMethod(uint32_t methodId, - management::Args& args, - std::string& text); - - // PersistableConfig: - void setPersistenceId(uint64_t id) const; - uint64_t getPersistenceId() const { return persistenceId; } - uint32_t encodedSize() const; - void encode(framing::Buffer& buffer) const; - const std::string& getName() const; - static Bridge::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer); - - // Exchange::DynamicBridge methods - void propagateBinding(const std::string& key, const std::string& tagList, const std::string& op, const std::string& origin, qpid::framing::FieldTable* extra_args=0); - void sendReorigin(); - void ioThreadPropagateBinding(const std::string& queue, const std::string& exchange, const std::string& key, framing::FieldTable args); - bool containsLocalTag(const std::string& tagList) const; - const std::string& getLocalTag() const; - -private: - struct PushHandler : framing::FrameHandler { - PushHandler(Connection* c) { conn = c; } - void handle(framing::AMQFrame& frame); - Connection* conn; - }; - - std::auto_ptr<PushHandler> pushHandler; - std::auto_ptr<framing::ChannelHandler> channelHandler; - std::auto_ptr<framing::AMQP_ServerProxy::Session> session; - std::auto_ptr<framing::AMQP_ServerProxy> peer; - - Link* link; - framing::ChannelId id; - qmf::org::apache::qpid::broker::ArgsLinkBridge args; - qmf::org::apache::qpid::broker::Bridge* mgmtObject; - CancellationListener listener; - std::string name; - std::string queueName; - mutable uint64_t persistenceId; - ConnectionState* connState; - Connection* conn; - - bool resetProxy(); -}; - - -}} - -#endif diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp deleted file mode 100644 index 240766c443..0000000000 --- a/cpp/src/qpid/broker/Broker.cpp +++ /dev/null @@ -1,967 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/MessageStoreModule.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/RecoveryManagerImpl.h" -#include "qpid/broker/SaslAuthenticator.h" -#include "qpid/broker/SecureConnectionFactory.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/broker/QueueFlowLimit.h" - -#include "qmf/org/apache/qpid/broker/Package.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerCreate.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerDelete.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerEcho.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerGetLogLevel.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerQueueMoveMessages.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerSetLogLevel.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h" -#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h" -#include "qmf/org/apache/qpid/broker/EventQueueDelete.h" -#include "qmf/org/apache/qpid/broker/EventBind.h" -#include "qmf/org/apache/qpid/broker/EventUnbind.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/management/ManagementDirectExchange.h" -#include "qpid/management/ManagementTopicExchange.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/log/posix/SinkOptions.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/ProtocolFactory.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/ConnectionInputHandler.h" -#include "qpid/sys/ConnectionInputHandlerFactory.h" -#include "qpid/sys/TimeoutHandler.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/Address.h" -#include "qpid/StringUtils.h" -#include "qpid/Url.h" -#include "qpid/Version.h" - -#include <boost/bind.hpp> -#include <boost/format.hpp> - -#include <iostream> -#include <memory> - -using qpid::sys::ProtocolFactory; -using qpid::sys::Poller; -using qpid::sys::Dispatcher; -using qpid::sys::Thread; -using qpid::framing::FrameHandler; -using qpid::framing::ChannelId; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::management::getManagementExecutionContext; -using qpid::types::Variant; -using std::string; -using std::make_pair; - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -Broker::Options::Options(const std::string& name) : - qpid::Options(name), - noDataDir(0), - port(DEFAULT_PORT), - workerThreads(5), - maxConnections(500), - connectionBacklog(10), - enableMgmt(1), - mgmtPubInterval(10), - queueCleanInterval(60*10),//10 minutes - auth(SaslAuthenticator::available()), - realm("QPID"), - replayFlushLimit(0), - replayHardLimit(0), - queueLimit(100*1048576/*100M default limit*/), - tcpNoDelay(false), - requireEncrypted(false), - maxSessionRate(0), - asyncQueueEvents(false), // Must be false in a cluster. - qmf2Support(true), - qmf1Support(true), - queueFlowStopRatio(80), - queueFlowResumeRatio(70), - queueThresholdEventRatio(80) -{ - int c = sys::SystemInfo::concurrency(); - workerThreads=c+1; - std::string home = getHome(); - - if (home.length() == 0) - dataDir += DEFAULT_DATA_DIR_LOCATION; - else - dataDir += home; - dataDir += DEFAULT_DATA_DIR_NAME; - - addOptions() - ("data-dir", optValue(dataDir,"DIR"), "Directory to contain persistent data generated by the broker") - ("no-data-dir", optValue(noDataDir), "Don't use a data directory. No persistent configuration will be loaded or stored") - ("port,p", optValue(port,"PORT"), "Tells the broker to listen on PORT") - ("worker-threads", optValue(workerThreads, "N"), "Sets the broker thread pool size") - ("max-connections", optValue(maxConnections, "N"), "Sets the maximum allowed connections") - ("connection-backlog", optValue(connectionBacklog, "N"), "Sets the connection backlog limit for the server socket") - ("mgmt-enable,m", optValue(enableMgmt,"yes|no"), "Enable Management") - ("mgmt-qmf2", optValue(qmf2Support,"yes|no"), "Enable broadcast of management information over QMF v2") - ("mgmt-qmf1", optValue(qmf1Support,"yes|no"), "Enable broadcast of management information over QMF v1") - ("mgmt-pub-interval", optValue(mgmtPubInterval, "SECONDS"), "Management Publish Interval") - ("queue-purge-interval", optValue(queueCleanInterval, "SECONDS"), - "Interval between attempts to purge any expired messages from queues") - ("auth", optValue(auth, "yes|no"), "Enable authentication, if disabled all incoming connections will be trusted") - ("realm", optValue(realm, "REALM"), "Use the given realm when performing authentication") - ("default-queue-limit", optValue(queueLimit, "BYTES"), "Default maximum size for queues (in bytes)") - ("tcp-nodelay", optValue(tcpNoDelay), "Set TCP_NODELAY on TCP connections") - ("require-encryption", optValue(requireEncrypted), "Only accept connections that are encrypted") - ("known-hosts-url", optValue(knownHosts, "URL or 'none'"), "URL to send as 'known-hosts' to clients ('none' implies empty list)") - ("sasl-config", optValue(saslConfigPath, "DIR"), "gets sasl config info from nonstandard location") - ("max-session-rate", optValue(maxSessionRate, "MESSAGES/S"), "Sets the maximum message rate per session (0=unlimited)") - ("async-queue-events", optValue(asyncQueueEvents, "yes|no"), "Set Queue Events async, used for services like replication") - ("default-flow-stop-threshold", optValue(queueFlowStopRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is activated.") - ("default-flow-resume-threshold", optValue(queueFlowResumeRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is de-activated.") - ("default-event-threshold-ratio", optValue(queueThresholdEventRatio, "%age of limit"), "The ratio of any specified queue limit at which an event will be raised"); -} - -const std::string empty; -const std::string amq_direct("amq.direct"); -const std::string amq_topic("amq.topic"); -const std::string amq_fanout("amq.fanout"); -const std::string amq_match("amq.match"); -const std::string qpid_management("qpid.management"); -const std::string knownHostsNone("none"); - -Broker::Broker(const Broker::Options& conf) : - poller(new Poller), - config(conf), - managementAgent(conf.enableMgmt ? new ManagementAgent(conf.qmf1Support, - conf.qmf2Support) - : 0), - store(new NullMessageStore), - acl(0), - dataDir(conf.noDataDir ? std::string() : conf.dataDir), - queues(this), - exchanges(this), - links(this), - factory(new SecureConnectionFactory(*this)), - dtxManager(timer), - sessionManager( - qpid::SessionState::Configuration( - conf.replayFlushLimit*1024, // convert kb to bytes. - conf.replayHardLimit*1024), - *this), - queueCleaner(queues, timer), - queueEvents(poller,!conf.asyncQueueEvents), - recovery(true), - inCluster(false), - clusterUpdatee(false), - expiryPolicy(new ExpiryPolicy), - connectionCounter(conf.maxConnections), - getKnownBrokers(boost::bind(&Broker::getKnownBrokersImpl, this)), - deferDelivery(boost::bind(&Broker::deferDeliveryImpl, this, _1, _2)) -{ - try { - if (conf.enableMgmt) { - QPID_LOG(info, "Management enabled"); - managementAgent->configure(dataDir.isEnabled() ? dataDir.getPath() : string(), - conf.mgmtPubInterval, this, conf.workerThreads + 3); - managementAgent->setName("apache.org", "qpidd"); - _qmf::Package packageInitializer(managementAgent.get()); - - System* system = new System (dataDir.isEnabled() ? dataDir.getPath() : string(), this); - systemObject = System::shared_ptr(system); - - mgmtObject = new _qmf::Broker(managementAgent.get(), this, system, "amqp-broker"); - mgmtObject->set_systemRef(system->GetManagementObject()->getObjectId()); - mgmtObject->set_port(conf.port); - mgmtObject->set_workerThreads(conf.workerThreads); - mgmtObject->set_maxConns(conf.maxConnections); - mgmtObject->set_connBacklog(conf.connectionBacklog); - mgmtObject->set_mgmtPubInterval(conf.mgmtPubInterval); - mgmtObject->set_version(qpid::version); - if (dataDir.isEnabled()) - mgmtObject->set_dataDir(dataDir.getPath()); - else - mgmtObject->clr_dataDir(); - - managementAgent->addObject(mgmtObject, 0, true); - - // Since there is currently no support for virtual hosts, a placeholder object - // representing the implied single virtual host is added here to keep the - // management schema correct. - Vhost* vhost = new Vhost(this, this); - vhostObject = Vhost::shared_ptr(vhost); - framing::Uuid uuid(managementAgent->getUuid()); - federationTag = uuid.str(); - vhostObject->setFederationTag(federationTag); - - queues.setParent(vhost); - exchanges.setParent(vhost); - links.setParent(vhost); - } else { - // Management is disabled so there is no broker management ID. - // Create a unique uuid to use as the federation tag. - framing::Uuid uuid(true); - federationTag = uuid.str(); - } - - QueuePolicy::setDefaultMaxSize(conf.queueLimit); - - // Early-Initialize plugins - Plugin::earlyInitAll(*this); - - QueueFlowLimit::setDefaults(conf.queueLimit, conf.queueFlowStopRatio, conf.queueFlowResumeRatio); - - // If no plugin store module registered itself, set up the null store. - if (NullMessageStore::isNullStore(store.get())) - setStore(); - - exchanges.declare(empty, DirectExchange::typeName); // Default exchange. - - if (store.get() != 0) { - // The cluster plug-in will setRecovery(false) on all but the first - // broker to join a cluster. - if (getRecovery()) { - RecoveryManagerImpl recoverer(queues, exchanges, links, dtxManager); - store->recover(recoverer); - } - else { - QPID_LOG(notice, "Cluster recovery: recovered journal data discarded and journal files pushed down"); - store->truncateInit(true); // save old files in subdir - } - } - - //ensure standard exchanges exist (done after recovery from store) - declareStandardExchange(amq_direct, DirectExchange::typeName); - declareStandardExchange(amq_topic, TopicExchange::typeName); - declareStandardExchange(amq_fanout, FanOutExchange::typeName); - declareStandardExchange(amq_match, HeadersExchange::typeName); - - if(conf.enableMgmt) { - exchanges.declare(qpid_management, ManagementTopicExchange::typeName); - Exchange::shared_ptr mExchange = exchanges.get(qpid_management); - Exchange::shared_ptr dExchange = exchanges.get(amq_direct); - managementAgent->setExchange(mExchange, dExchange); - boost::dynamic_pointer_cast<ManagementTopicExchange>(mExchange)->setManagmentAgent(managementAgent.get(), 1); - - std::string qmfTopic("qmf.default.topic"); - std::string qmfDirect("qmf.default.direct"); - - std::pair<Exchange::shared_ptr, bool> topicPair(exchanges.declare(qmfTopic, ManagementTopicExchange::typeName)); - std::pair<Exchange::shared_ptr, bool> directPair(exchanges.declare(qmfDirect, ManagementDirectExchange::typeName)); - - boost::dynamic_pointer_cast<ManagementDirectExchange>(directPair.first)->setManagmentAgent(managementAgent.get(), 2); - boost::dynamic_pointer_cast<ManagementTopicExchange>(topicPair.first)->setManagmentAgent(managementAgent.get(), 2); - - managementAgent->setExchangeV2(topicPair.first, directPair.first); - } - else - QPID_LOG(info, "Management not enabled"); - - /** - * SASL setup, can fail and terminate startup - */ - if (conf.auth) { - SaslAuthenticator::init(qpid::saslName, conf.saslConfigPath); - QPID_LOG(info, "SASL enabled"); - } else { - QPID_LOG(notice, "SASL disabled: No Authentication Performed"); - } - - // Initialize plugins - Plugin::initializeAll(*this); - - if (managementAgent.get()) managementAgent->pluginsInitialized(); - - if (conf.queueCleanInterval) { - queueCleaner.start(conf.queueCleanInterval * qpid::sys::TIME_SEC); - } - - //initialize known broker urls (TODO: add support for urls for other transports (SSL, RDMA)): - if (conf.knownHosts.empty()) { - boost::shared_ptr<ProtocolFactory> factory = getProtocolFactory(TCP_TRANSPORT); - if (factory) { - knownBrokers.push_back ( qpid::Url::getIpAddressesUrl ( factory->getPort() ) ); - } - } else if (conf.knownHosts != knownHostsNone) { - knownBrokers.push_back(Url(conf.knownHosts)); - } - } catch (const std::exception& /*e*/) { - finalize(); - throw; - } -} - -void Broker::declareStandardExchange(const std::string& name, const std::string& type) -{ - bool storeEnabled = store.get() != NULL; - std::pair<Exchange::shared_ptr, bool> status = exchanges.declare(name, type, storeEnabled); - if (status.second && storeEnabled) { - store->create(*status.first, framing::FieldTable ()); - } -} - - -boost::intrusive_ptr<Broker> Broker::create(int16_t port) -{ - Options config; - config.port=port; - return create(config); -} - -boost::intrusive_ptr<Broker> Broker::create(const Options& opts) -{ - return boost::intrusive_ptr<Broker>(new Broker(opts)); -} - -void Broker::setStore (boost::shared_ptr<MessageStore>& _store) -{ - store.reset(new MessageStoreModule (_store)); - setStore(); -} - -void Broker::setStore () { - queues.setStore (store.get()); - dtxManager.setStore (store.get()); - links.setStore (store.get()); -} - -void Broker::run() { - if (config.workerThreads > 0) { - QPID_LOG(notice, "Broker running"); - Dispatcher d(poller); - int numIOThreads = config.workerThreads; - std::vector<Thread> t(numIOThreads-1); - - // Run n-1 io threads - for (int i=0; i<numIOThreads-1; ++i) - t[i] = Thread(d); - - // Run final thread - d.run(); - - // Now wait for n-1 io threads to exit - for (int i=0; i<numIOThreads-1; ++i) { - t[i].join(); - } - } else { - throw Exception((boost::format("Invalid value for worker-threads: %1%") % config.workerThreads).str()); - } -} - -void Broker::shutdown() { - // NB: this function must be async-signal safe, it must not - // call any function that is not async-signal safe. - // Any unsafe shutdown actions should be done in the destructor. - poller->shutdown(); -} - -Broker::~Broker() { - shutdown(); - queueEvents.shutdown(); - finalize(); // Finalize any plugins. - if (config.auth) - SaslAuthenticator::fini(); - timer.stop(); - QPID_LOG(notice, "Shut down"); -} - -ManagementObject* Broker::GetManagementObject(void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable* Broker::GetVhostObject(void) const -{ - return vhostObject.get(); -} - -Manageable::status_t Broker::ManagementMethod (uint32_t methodId, - Args& args, - string&) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - switch (methodId) - { - case _qmf::Broker::METHOD_ECHO : - QPID_LOG (debug, "Broker::echo(" - << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_sequence - << ", " - << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_body - << ")"); - status = Manageable::STATUS_OK; - break; - case _qmf::Broker::METHOD_CONNECT : { - _qmf::ArgsBrokerConnect& hp= - dynamic_cast<_qmf::ArgsBrokerConnect&>(args); - - QPID_LOG (debug, "Broker::connect()"); - string transport = hp.i_transport.empty() ? TCP_TRANSPORT : hp.i_transport; - if (!getProtocolFactory(transport)) { - QPID_LOG(error, "Transport '" << transport << "' not supported"); - return Manageable::STATUS_NOT_IMPLEMENTED; - } - std::pair<Link::shared_ptr, bool> response = - links.declare (hp.i_host, hp.i_port, transport, hp.i_durable, - hp.i_authMechanism, hp.i_username, hp.i_password); - if (hp.i_durable && response.second) - store->create(*response.first); - status = Manageable::STATUS_OK; - break; - } - case _qmf::Broker::METHOD_QUEUEMOVEMESSAGES : { - _qmf::ArgsBrokerQueueMoveMessages& moveArgs= - dynamic_cast<_qmf::ArgsBrokerQueueMoveMessages&>(args); - QPID_LOG (debug, "Broker::queueMoveMessages()"); - if (queueMoveMessages(moveArgs.i_srcQueue, moveArgs.i_destQueue, moveArgs.i_qty)) - status = Manageable::STATUS_OK; - else - return Manageable::STATUS_PARAMETER_INVALID; - break; - } - case _qmf::Broker::METHOD_SETLOGLEVEL : - setLogLevel(dynamic_cast<_qmf::ArgsBrokerSetLogLevel&>(args).i_level); - QPID_LOG (debug, "Broker::setLogLevel()"); - status = Manageable::STATUS_OK; - break; - case _qmf::Broker::METHOD_GETLOGLEVEL : - dynamic_cast<_qmf::ArgsBrokerGetLogLevel&>(args).o_level = getLogLevel(); - QPID_LOG (debug, "Broker::getLogLevel()"); - status = Manageable::STATUS_OK; - break; - case _qmf::Broker::METHOD_CREATE : - { - _qmf::ArgsBrokerCreate& a = dynamic_cast<_qmf::ArgsBrokerCreate&>(args); - createObject(a.i_type, a.i_name, a.i_properties, a.i_strict, getManagementExecutionContext()); - status = Manageable::STATUS_OK; - break; - } - case _qmf::Broker::METHOD_DELETE : - { - _qmf::ArgsBrokerDelete& a = dynamic_cast<_qmf::ArgsBrokerDelete&>(args); - deleteObject(a.i_type, a.i_name, a.i_options, getManagementExecutionContext()); - status = Manageable::STATUS_OK; - break; - } - default: - QPID_LOG (debug, "Broker ManagementMethod not implemented: id=" << methodId << "]"); - status = Manageable::STATUS_NOT_IMPLEMENTED; - break; - } - - return status; -} - -namespace -{ -const std::string TYPE_QUEUE("queue"); -const std::string TYPE_EXCHANGE("exchange"); -const std::string TYPE_TOPIC("topic"); -const std::string TYPE_BINDING("binding"); -const std::string DURABLE("durable"); -const std::string AUTO_DELETE("auto-delete"); -const std::string ALTERNATE_EXCHANGE("alternate-exchange"); -const std::string EXCHANGE_TYPE("exchange-type"); -const std::string QUEUE_NAME("queue"); -const std::string EXCHANGE_NAME("exchange"); - -const std::string _TRUE("true"); -const std::string _FALSE("false"); -} - -struct InvalidBindingIdentifier : public qpid::Exception -{ - InvalidBindingIdentifier(const std::string& name) : qpid::Exception(name) {} - std::string getPrefix() const { return "invalid binding"; } -}; - -struct BindingIdentifier -{ - std::string exchange; - std::string queue; - std::string key; - - BindingIdentifier(const std::string& name) - { - std::vector<std::string> path; - split(path, name, "/"); - switch (path.size()) { - case 1: - queue = path[0]; - break; - case 2: - exchange = path[0]; - queue = path[1]; - break; - case 3: - exchange = path[0]; - queue = path[1]; - key = path[2]; - break; - default: - throw InvalidBindingIdentifier(name); - } - } -}; - -struct ObjectAlreadyExists : public qpid::Exception -{ - ObjectAlreadyExists(const std::string& name) : qpid::Exception(name) {} - std::string getPrefix() const { return "object already exists"; } -}; - -struct UnknownObjectType : public qpid::Exception -{ - UnknownObjectType(const std::string& type) : qpid::Exception(type) {} - std::string getPrefix() const { return "unknown object type"; } -}; - -void Broker::createObject(const std::string& type, const std::string& name, - const Variant::Map& properties, bool /*strict*/, const ConnectionState* context) -{ - std::string userId; - std::string connectionId; - if (context) { - userId = context->getUserId(); - connectionId = context->getUrl(); - } - //TODO: implement 'strict' option (check there are no unrecognised properties) - QPID_LOG (debug, "Broker::create(" << type << ", " << name << "," << properties << ")"); - if (type == TYPE_QUEUE) { - bool durable(false); - bool autodelete(false); - std::string alternateExchange; - Variant::Map extensions; - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - // extract durable, auto-delete and alternate-exchange properties - if (i->first == DURABLE) durable = i->second; - else if (i->first == AUTO_DELETE) autodelete = i->second; - else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString(); - //treat everything else as extension properties - else extensions[i->first] = i->second; - } - framing::FieldTable arguments; - amqp_0_10::translate(extensions, arguments); - - std::pair<boost::shared_ptr<Queue>, bool> result = - createQueue(name, durable, autodelete, 0, alternateExchange, arguments, userId, connectionId); - if (!result.second) { - throw ObjectAlreadyExists(name); - } - } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) { - bool durable(false); - std::string exchangeType("topic"); - std::string alternateExchange; - Variant::Map extensions; - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - // extract durable, auto-delete and alternate-exchange properties - if (i->first == DURABLE) durable = i->second; - else if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString(); - else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString(); - //treat everything else as extension properties - else extensions[i->first] = i->second; - } - framing::FieldTable arguments; - amqp_0_10::translate(extensions, arguments); - - try { - std::pair<boost::shared_ptr<Exchange>, bool> result = - createExchange(name, exchangeType, durable, alternateExchange, arguments, userId, connectionId); - if (!result.second) { - throw ObjectAlreadyExists(name); - } - } catch (const UnknownExchangeTypeException&) { - throw Exception(QPID_MSG("Invalid exchange type: " << exchangeType)); - } - } else if (type == TYPE_BINDING) { - BindingIdentifier binding(name); - std::string exchangeType("topic"); - Variant::Map extensions; - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - // extract durable, auto-delete and alternate-exchange properties - if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString(); - //treat everything else as extension properties - else extensions[i->first] = i->second; - } - framing::FieldTable arguments; - amqp_0_10::translate(extensions, arguments); - - bind(binding.queue, binding.exchange, binding.key, arguments, userId, connectionId); - } else { - throw UnknownObjectType(type); - } -} - -void Broker::deleteObject(const std::string& type, const std::string& name, - const Variant::Map& options, const ConnectionState* context) -{ - std::string userId; - std::string connectionId; - if (context) { - userId = context->getUserId(); - connectionId = context->getUrl(); - } - QPID_LOG (debug, "Broker::delete(" << type << ", " << name << "," << options << ")"); - if (type == TYPE_QUEUE) { - deleteQueue(name, userId, connectionId); - } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) { - deleteExchange(name, userId, connectionId); - } else if (type == TYPE_BINDING) { - BindingIdentifier binding(name); - unbind(binding.queue, binding.exchange, binding.key, userId, connectionId); - } else { - throw UnknownObjectType(type); - } - -} - -void Broker::setLogLevel(const std::string& level) -{ - QPID_LOG(notice, "Changing log level to " << level); - std::vector<std::string> selectors; - split(selectors, level, ", "); - qpid::log::Logger::instance().reconfigure(selectors); -} - -std::string Broker::getLogLevel() -{ - std::string level; - const std::vector<std::string>& selectors = qpid::log::Logger::instance().getOptions().selectors; - for (std::vector<std::string>::const_iterator i = selectors.begin(); i != selectors.end(); ++i) { - if (i != selectors.begin()) level += std::string(","); - level += *i; - } - return level; -} - -boost::shared_ptr<ProtocolFactory> Broker::getProtocolFactory(const std::string& name) const { - ProtocolFactoryMap::const_iterator i - = name.empty() ? protocolFactories.begin() : protocolFactories.find(name); - if (i == protocolFactories.end()) return boost::shared_ptr<ProtocolFactory>(); - else return i->second; -} - -uint16_t Broker::getPort(const std::string& name) const { - boost::shared_ptr<ProtocolFactory> factory = getProtocolFactory(name); - if (factory) { - return factory->getPort(); - } else { - throw NoSuchTransportException(QPID_MSG("No such transport: '" << name << "'")); - } -} - -void Broker::registerProtocolFactory(const std::string& name, ProtocolFactory::shared_ptr protocolFactory) { - protocolFactories[name] = protocolFactory; - Url::addProtocol(name); -} - -void Broker::accept() { - for (ProtocolFactoryMap::const_iterator i = protocolFactories.begin(); i != protocolFactories.end(); i++) { - i->second->accept(poller, factory.get()); - } -} - -void Broker::connect( - const std::string& host, uint16_t port, const std::string& transport, - boost::function2<void, int, std::string> failed, - sys::ConnectionCodec::Factory* f) -{ - boost::shared_ptr<ProtocolFactory> pf = getProtocolFactory(transport); - if (pf) pf->connect(poller, host, port, f ? f : factory.get(), failed); - else throw NoSuchTransportException(QPID_MSG("Unsupported transport type: " << transport)); -} - -void Broker::connect( - const Url& url, - boost::function2<void, int, std::string> failed, - sys::ConnectionCodec::Factory* f) -{ - url.throwIfEmpty(); - const Address& addr=url[0]; - connect(addr.host, addr.port, addr.protocol, failed, f); -} - -uint32_t Broker::queueMoveMessages( - const std::string& srcQueue, - const std::string& destQueue, - uint32_t qty) -{ - Queue::shared_ptr src_queue = queues.find(srcQueue); - if (!src_queue) - return 0; - Queue::shared_ptr dest_queue = queues.find(destQueue); - if (!dest_queue) - return 0; - - return src_queue->move(dest_queue, qty); -} - - -boost::shared_ptr<sys::Poller> Broker::getPoller() { return poller; } - -std::vector<Url> -Broker::getKnownBrokersImpl() -{ - return knownBrokers; -} - -bool Broker::deferDeliveryImpl(const std::string& , - const boost::intrusive_ptr<Message>& ) -{ return false; } - -void Broker::setClusterTimer(std::auto_ptr<sys::Timer> t) { - clusterTimer = t; -} - -const std::string Broker::TCP_TRANSPORT("tcp"); - - -std::pair<boost::shared_ptr<Queue>, bool> Broker::createQueue( - const std::string& name, - bool durable, - bool autodelete, - const OwnershipToken* owner, - const std::string& alternateExchange, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_PASSIVE, _FALSE)); - params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_EXCLUSIVE, owner ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_AUTODELETE, autodelete ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_POLICYTYPE, arguments.getAsString("qpid.policy_type"))); - params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast<string>(arguments.getAsInt("qpid.max_count")))); - params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast<string>(arguments.getAsInt64("qpid.max_size")))); - - if (!acl->authorise(userId,acl::ACT_CREATE,acl::OBJ_QUEUE,name,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << userId)); - } - - Exchange::shared_ptr alternate; - if (!alternateExchange.empty()) { - alternate = exchanges.get(alternateExchange); - if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); - } - - std::pair<Queue::shared_ptr, bool> result = queues.declare(name, durable, autodelete, owner, alternate, arguments); - if (result.second) { - //add default binding: - result.first->bind(exchanges.getDefault(), name); - - if (managementAgent.get()) { - //TODO: debatable whether we should raise an event here for - //create when this is a 'declare' event; ideally add a create - //event instead? - managementAgent->raiseEvent( - _qmf::EventQueueDeclare(connectionId, userId, name, - durable, owner, autodelete, - ManagementAgent::toMap(arguments), - "created")); - } - } - return result; -} - -void Broker::deleteQueue(const std::string& name, const std::string& userId, - const std::string& connectionId, QueueFunctor check) -{ - if (acl && !acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_QUEUE,name,NULL)) { - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue delete request from " << userId)); - } - - Queue::shared_ptr queue = queues.find(name); - if (queue) { - if (check) check(queue); - queues.destroy(name); - queue->destroyed(); - } else { - throw framing::NotFoundException(QPID_MSG("Delete failed. No such queue: " << name)); - } - - if (managementAgent.get()) - managementAgent->raiseEvent(_qmf::EventQueueDelete(connectionId, userId, name)); - -} - -std::pair<Exchange::shared_ptr, bool> Broker::createExchange( - const std::string& name, - const std::string& type, - bool durable, - const std::string& alternateExchange, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_TYPE, type)); - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_PASSIVE, _FALSE)); - params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE)); - if (!acl->authorise(userId,acl::ACT_CREATE,acl::OBJ_EXCHANGE,name,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange create request from " << userId)); - } - - Exchange::shared_ptr alternate; - if (!alternateExchange.empty()) { - alternate = exchanges.get(alternateExchange); - if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); - } - - std::pair<Exchange::shared_ptr, bool> result; - result = exchanges.declare(name, type, durable, arguments); - if (result.second) { - if (alternate) { - result.first->setAlternate(alternate); - alternate->incAlternateUsers(); - } - if (durable) { - store->create(*result.first, arguments); - } - if (managementAgent.get()) { - //TODO: debatable whether we should raise an event here for - //create when this is a 'declare' event; ideally add a create - //event instead? - managementAgent->raiseEvent(_qmf::EventExchangeDeclare(connectionId, - userId, - name, - type, - alternateExchange, - durable, - false, - ManagementAgent::toMap(arguments), - "created")); - } - } - return result; -} - -void Broker::deleteExchange(const std::string& name, const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - if (!acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_EXCHANGE,name,NULL) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange delete request from " << userId)); - } - - Exchange::shared_ptr exchange(exchanges.get(name)); - if (!exchange) throw framing::NotFoundException(QPID_MSG("Delete failed. No such exchange: " << name)); - if (exchange->inUseAsAlternate()) throw framing::NotAllowedException(QPID_MSG("Exchange in use as alternate-exchange.")); - if (exchange->isDurable()) store->destroy(*exchange); - if (exchange->getAlternate()) exchange->getAlternate()->decAlternateUsers(); - exchanges.destroy(name); - - if (managementAgent.get()) - managementAgent->raiseEvent(_qmf::EventExchangeDelete(connectionId, userId, name)); - -} - -void Broker::bind(const std::string& queueName, - const std::string& exchangeName, - const std::string& key, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_QUEUENAME, queueName)); - params.insert(make_pair(acl::PROP_ROUTINGKEY, key)); - - if (!acl->authorise(userId,acl::ACT_BIND,acl::OBJ_EXCHANGE,exchangeName,¶ms)) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange bind request from " << userId)); - } - - Queue::shared_ptr queue = queues.find(queueName); - Exchange::shared_ptr exchange = exchanges.get(exchangeName); - if (!queue) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such queue: " << queueName)); - } else if (!exchange) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such exchange: " << exchangeName)); - } else { - if (queue->bind(exchange, key, arguments)) { - if (managementAgent.get()) { - managementAgent->raiseEvent(_qmf::EventBind(connectionId, userId, exchangeName, - queueName, key, ManagementAgent::toMap(arguments))); - } - } - } -} - -void Broker::unbind(const std::string& queueName, - const std::string& exchangeName, - const std::string& key, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_QUEUENAME, queueName)); - params.insert(make_pair(acl::PROP_ROUTINGKEY, key)); - if (!acl->authorise(userId,acl::ACT_UNBIND,acl::OBJ_EXCHANGE,exchangeName,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange unbind request from " << userId)); - } - - Queue::shared_ptr queue = queues.find(queueName); - Exchange::shared_ptr exchange = exchanges.get(exchangeName); - if (!queue) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such queue: " << queueName)); - } else if (!exchange) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such exchange: " << exchangeName)); - } else { - if (exchange->unbind(queue, key, 0)) { - if (exchange->isDurable() && queue->isDurable()) { - store->unbind(*exchange, *queue, key, qpid::framing::FieldTable()); - } - if (managementAgent.get()) { - managementAgent->raiseEvent(_qmf::EventUnbind(connectionId, userId, exchangeName, queueName, key)); - } - } - } -} - -}} // namespace qpid::broker - diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h deleted file mode 100644 index 6d585bf614..0000000000 --- a/cpp/src/qpid/broker/Broker.h +++ /dev/null @@ -1,351 +0,0 @@ -#ifndef _Broker_ -#define _Broker_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/ConnectionFactory.h" -#include "qpid/broker/ConnectionToken.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/SessionManager.h" -#include "qpid/broker/QueueCleaner.h" -#include "qpid/broker/QueueEvents.h" -#include "qpid/broker/Vhost.h" -#include "qpid/broker/System.h" -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/management/Manageable.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/broker/Broker.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerConnect.h" -#include "qpid/Options.h" -#include "qpid/Plugin.h" -#include "qpid/DataDir.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/OutputHandler.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Timer.h" -#include "qpid/types/Variant.h" -#include "qpid/RefCounted.h" -#include "qpid/broker/AclModule.h" -#include "qpid/sys/Mutex.h" - -#include <boost/intrusive_ptr.hpp> -#include <string> -#include <vector> - -namespace qpid { - -namespace sys { - class ProtocolFactory; - class Poller; -} - -struct Url; - -namespace broker { - -class ConnectionState; -class ExpiryPolicy; -class Message; - -static const uint16_t DEFAULT_PORT=5672; - -struct NoSuchTransportException : qpid::Exception -{ - NoSuchTransportException(const std::string& s) : Exception(s) {} - virtual ~NoSuchTransportException() throw() {} -}; - -/** - * A broker instance. - */ -class Broker : public sys::Runnable, public Plugin::Target, - public management::Manageable, - public RefCounted -{ -public: - - struct Options : public qpid::Options { - static const std::string DEFAULT_DATA_DIR_LOCATION; - static const std::string DEFAULT_DATA_DIR_NAME; - - QPID_BROKER_EXTERN Options(const std::string& name="Broker Options"); - - bool noDataDir; - std::string dataDir; - uint16_t port; - int workerThreads; - int maxConnections; - int connectionBacklog; - bool enableMgmt; - uint16_t mgmtPubInterval; - uint16_t queueCleanInterval; - bool auth; - std::string realm; - size_t replayFlushLimit; - size_t replayHardLimit; - uint queueLimit; - bool tcpNoDelay; - bool requireEncrypted; - std::string knownHosts; - std::string saslConfigPath; - uint32_t maxSessionRate; - bool asyncQueueEvents; - bool qmf2Support; - bool qmf1Support; - uint queueFlowStopRatio; // producer flow control: on - uint queueFlowResumeRatio; // producer flow control: off - uint16_t queueThresholdEventRatio; - - private: - std::string getHome(); - }; - - class ConnectionCounter { - int maxConnections; - int connectionCount; - sys::Mutex connectionCountLock; - public: - ConnectionCounter(int mc): maxConnections(mc),connectionCount(0) {}; - void inc_connectionCount() { - sys::ScopedLock<sys::Mutex> l(connectionCountLock); - connectionCount++; - } - void dec_connectionCount() { - sys::ScopedLock<sys::Mutex> l(connectionCountLock); - connectionCount--; - } - bool allowConnection() { - sys::ScopedLock<sys::Mutex> l(connectionCountLock); - return (maxConnections <= connectionCount); - } - }; - - private: - typedef std::map<std::string, boost::shared_ptr<sys::ProtocolFactory> > ProtocolFactoryMap; - - void declareStandardExchange(const std::string& name, const std::string& type); - void setStore (); - void setLogLevel(const std::string& level); - std::string getLogLevel(); - void createObject(const std::string& type, const std::string& name, - const qpid::types::Variant::Map& properties, bool strict, const ConnectionState* context); - void deleteObject(const std::string& type, const std::string& name, - const qpid::types::Variant::Map& options, const ConnectionState* context); - - boost::shared_ptr<sys::Poller> poller; - sys::Timer timer; - std::auto_ptr<sys::Timer> clusterTimer; - Options config; - std::auto_ptr<management::ManagementAgent> managementAgent; - ProtocolFactoryMap protocolFactories; - std::auto_ptr<MessageStore> store; - AclModule* acl; - DataDir dataDir; - - QueueRegistry queues; - ExchangeRegistry exchanges; - LinkRegistry links; - boost::shared_ptr<sys::ConnectionCodec::Factory> factory; - DtxManager dtxManager; - SessionManager sessionManager; - qmf::org::apache::qpid::broker::Broker* mgmtObject; - Vhost::shared_ptr vhostObject; - System::shared_ptr systemObject; - QueueCleaner queueCleaner; - QueueEvents queueEvents; - std::vector<Url> knownBrokers; - std::vector<Url> getKnownBrokersImpl(); - bool deferDeliveryImpl(const std::string& queue, - const boost::intrusive_ptr<Message>& msg); - std::string federationTag; - bool recovery; - bool inCluster, clusterUpdatee; - boost::intrusive_ptr<ExpiryPolicy> expiryPolicy; - ConnectionCounter connectionCounter; - - public: - virtual ~Broker(); - - QPID_BROKER_EXTERN Broker(const Options& configuration); - static QPID_BROKER_EXTERN boost::intrusive_ptr<Broker> create(const Options& configuration); - static QPID_BROKER_EXTERN boost::intrusive_ptr<Broker> create(int16_t port = DEFAULT_PORT); - - /** - * Return listening port. If called before bind this is - * the configured port. If called after it is the actual - * port, which will be different if the configured port is - * 0. - */ - virtual uint16_t getPort(const std::string& name) const; - - /** - * Run the broker. Implements Runnable::run() so the broker - * can be run in a separate thread. - */ - virtual void run(); - - /** Shut down the broker */ - virtual void shutdown(); - - QPID_BROKER_EXTERN void setStore (boost::shared_ptr<MessageStore>& store); - MessageStore& getStore() { return *store; } - void setAcl (AclModule* _acl) {acl = _acl;} - AclModule* getAcl() { return acl; } - QueueRegistry& getQueues() { return queues; } - ExchangeRegistry& getExchanges() { return exchanges; } - LinkRegistry& getLinks() { return links; } - DtxManager& getDtxManager() { return dtxManager; } - DataDir& getDataDir() { return dataDir; } - Options& getOptions() { return config; } - QueueEvents& getQueueEvents() { return queueEvents; } - - void setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e) { expiryPolicy = e; } - boost::intrusive_ptr<ExpiryPolicy> getExpiryPolicy() { return expiryPolicy; } - - SessionManager& getSessionManager() { return sessionManager; } - const std::string& getFederationTag() const { return federationTag; } - - management::ManagementObject* GetManagementObject (void) const; - management::Manageable* GetVhostObject (void) const; - management::Manageable::status_t ManagementMethod (uint32_t methodId, - management::Args& args, - std::string& text); - - /** Add to the broker's protocolFactorys */ - void registerProtocolFactory(const std::string& name, boost::shared_ptr<sys::ProtocolFactory>); - - /** Accept connections */ - QPID_BROKER_EXTERN void accept(); - - /** Create a connection to another broker. */ - void connect(const std::string& host, uint16_t port, - const std::string& transport, - boost::function2<void, int, std::string> failed, - sys::ConnectionCodec::Factory* =0); - /** Create a connection to another broker. */ - void connect(const Url& url, - boost::function2<void, int, std::string> failed, - sys::ConnectionCodec::Factory* =0); - - /** Move messages from one queue to another. - A zero quantity means to move all messages - */ - uint32_t queueMoveMessages( const std::string& srcQueue, - const std::string& destQueue, - uint32_t qty); - - boost::shared_ptr<sys::ProtocolFactory> getProtocolFactory(const std::string& name = TCP_TRANSPORT) const; - - /** Expose poller so plugins can register their descriptors. */ - boost::shared_ptr<sys::Poller> getPoller(); - - boost::shared_ptr<sys::ConnectionCodec::Factory> getConnectionFactory() { return factory; } - void setConnectionFactory(boost::shared_ptr<sys::ConnectionCodec::Factory> f) { factory = f; } - - /** Timer for local tasks affecting only this broker */ - sys::Timer& getTimer() { return timer; } - - /** Timer for tasks that must be synchronized if we are in a cluster */ - sys::Timer& getClusterTimer() { return clusterTimer.get() ? *clusterTimer : timer; } - void setClusterTimer(std::auto_ptr<sys::Timer>); - - boost::function<std::vector<Url> ()> getKnownBrokers; - - static QPID_BROKER_EXTERN const std::string TCP_TRANSPORT; - - void setRecovery(bool set) { recovery = set; } - bool getRecovery() const { return recovery; } - - /** True of this broker is part of a cluster. - * Only valid after early initialization of plugins is complete. - */ - bool isInCluster() const { return inCluster; } - void setInCluster(bool set) { inCluster = set; } - - /** True if this broker is joining a cluster and in the process of - * receiving a state update. - */ - bool isClusterUpdatee() const { return clusterUpdatee; } - void setClusterUpdatee(bool set) { clusterUpdatee = set; } - - management::ManagementAgent* getManagementAgent() { return managementAgent.get(); } - - ConnectionCounter& getConnectionCounter() {return connectionCounter;} - - /** - * Never true in a stand-alone broker. In a cluster, return true - * to defer delivery of messages deliveredg in a cluster-unsafe - * context. - *@return true if delivery of a message should be deferred. - */ - boost::function<bool (const std::string& queue, - const boost::intrusive_ptr<Message>& msg)> deferDelivery; - - bool isAuthenticating ( ) { return config.auth; } - - typedef boost::function1<void, boost::shared_ptr<Queue> > QueueFunctor; - - std::pair<boost::shared_ptr<Queue>, bool> createQueue( - const std::string& name, - bool durable, - bool autodelete, - const OwnershipToken* owner, - const std::string& alternateExchange, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId); - void deleteQueue(const std::string& name, - const std::string& userId, - const std::string& connectionId, - QueueFunctor check = QueueFunctor()); - std::pair<Exchange::shared_ptr, bool> createExchange( - const std::string& name, - const std::string& type, - bool durable, - const std::string& alternateExchange, - const qpid::framing::FieldTable& args, - const std::string& userId, const std::string& connectionId); - void deleteExchange(const std::string& name, const std::string& userId, - const std::string& connectionId); - void bind(const std::string& queue, - const std::string& exchange, - const std::string& key, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId); - void unbind(const std::string& queue, - const std::string& exchange, - const std::string& key, - const std::string& userId, - const std::string& connectionId); -}; - -}} - -#endif /*!_Broker_*/ diff --git a/cpp/src/qpid/broker/BrokerImportExport.h b/cpp/src/qpid/broker/BrokerImportExport.h deleted file mode 100644 index ee05788063..0000000000 --- a/cpp/src/qpid/broker/BrokerImportExport.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_BROKER_IMPORT_EXPORT_H -#define QPID_BROKER_IMPORT_EXPORT_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#if defined(WIN32) && !defined(QPID_DECLARE_STATIC) -# if defined(BROKER_EXPORT) || defined (qpidbroker_EXPORTS) -# define QPID_BROKER_EXTERN __declspec(dllexport) -# else -# define QPID_BROKER_EXTERN __declspec(dllimport) -# endif -# ifdef _MSC_VER -# define QPID_BROKER_CLASS_EXTERN -# define QPID_BROKER_INLINE_EXTERN QPID_BROKER_EXTERN -# else -# define QPID_BROKER_CLASS_EXTERN QPID_BROKER_EXTERN -# define QPID_BROKER_INLINE_EXTERN -# endif -#else -# define QPID_BROKER_EXTERN -# define QPID_BROKER_CLASS_EXTERN -# define QPID_BROKER_INLINE_EXTERN -#endif - -#endif diff --git a/cpp/src/qpid/broker/Connection.cpp b/cpp/src/qpid/broker/Connection.cpp deleted file mode 100644 index c07e63e68c..0000000000 --- a/cpp/src/qpid/broker/Connection.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Connection.h" -#include "qpid/broker/SessionOutputException.h" -#include "qpid/broker/SessionState.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/ClusterSafe.h" - -#include "qpid/log/Statement.h" -#include "qpid/ptr_map.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qmf/org/apache/qpid/broker/EventClientConnect.h" -#include "qmf/org/apache/qpid/broker/EventClientDisconnect.h" - -#include <boost/bind.hpp> -#include <boost/ptr_container/ptr_vector.hpp> - -#include <algorithm> -#include <iostream> -#include <assert.h> - - - -using namespace qpid::sys; -using namespace qpid::framing; -using qpid::ptr_map_ptr; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -struct ConnectionTimeoutTask : public sys::TimerTask { - sys::Timer& timer; - Connection& connection; - - ConnectionTimeoutTask(uint16_t hb, sys::Timer& t, Connection& c) : - TimerTask(Duration(hb*2*TIME_SEC),"ConnectionTimeout"), - timer(t), - connection(c) - {} - - void touch() { - restart(); - } - - void fire() { - // If we get here then we've not received any traffic in the timeout period - // Schedule closing the connection for the io thread - QPID_LOG(error, "Connection " << connection.getMgmtId() - << " timed out: closing"); - connection.abort(); - } -}; - -Connection::Connection(ConnectionOutputHandler* out_, - Broker& broker_, const - std::string& mgmtId_, - const qpid::sys::SecuritySettings& external, - bool isLink_, - uint64_t objectId_, - bool shadow_, - bool delayManagement) : - ConnectionState(out_, broker_), - securitySettings(external), - adapter(*this, isLink_, shadow_), - isLink(isLink_), - mgmtClosing(false), - mgmtId(mgmtId_), - mgmtObject(0), - links(broker_.getLinks()), - agent(0), - timer(broker_.getTimer()), - errorListener(0), - objectId(objectId_), - shadow(shadow_), - outboundTracker(*this) -{ - outboundTracker.wrap(out); - if (isLink) - links.notifyConnection(mgmtId, this); - // In a cluster, allow adding the management object to be delayed. - if (!delayManagement) addManagementObject(); - if (!isShadow()) broker.getConnectionCounter().inc_connectionCount(); -} - -void Connection::addManagementObject() { - assert(agent == 0); - assert(mgmtObject == 0); - Manageable* parent = broker.GetVhostObject(); - if (parent != 0) { - agent = broker.getManagementAgent(); - if (agent != 0) { - // TODO set last bool true if system connection - mgmtObject = new _qmf::Connection(agent, this, parent, mgmtId, !isLink, false); - mgmtObject->set_shadow(shadow); - agent->addObject(mgmtObject, objectId); - } - ConnectionState::setUrl(mgmtId); - } -} - -void Connection::requestIOProcessing(boost::function0<void> callback) -{ - ScopedLock<Mutex> l(ioCallbackLock); - ioCallbacks.push(callback); - out.activateOutput(); -} - -Connection::~Connection() -{ - if (mgmtObject != 0) { - mgmtObject->resourceDestroy(); - // In a cluster, Connections destroyed during shutdown are in - // a cluster-unsafe context. Don't raise an event in that case. - if (!isLink && isClusterSafe()) - agent->raiseEvent(_qmf::EventClientDisconnect(mgmtId, ConnectionState::getUserId())); - } - if (isLink) - links.notifyClosed(mgmtId); - - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - - if (!isShadow()) broker.getConnectionCounter().dec_connectionCount(); -} - -void Connection::received(framing::AMQFrame& frame) { - // Received frame on connection so delay timeout - restartTimeout(); - - if (frame.getChannel() == 0 && frame.getMethod()) { - adapter.handle(frame); - } else { - if (adapter.isOpen()) - getChannel(frame.getChannel()).in(frame); - else - close(connection::CLOSE_CODE_FRAMING_ERROR, "Connection not yet open, invalid frame received."); - } - - if (isLink) //i.e. we are acting as the client to another broker - recordFromServer(frame); - else - recordFromClient(frame); -} - -void Connection::sent(const framing::AMQFrame& frame) -{ - if (isLink) //i.e. we are acting as the client to another broker - recordFromClient(frame); - else - recordFromServer(frame); -} - -bool isMessage(const AMQMethodBody* method) -{ - return method && method->isA<qpid::framing::MessageTransferBody>(); -} - -void Connection::recordFromServer(const framing::AMQFrame& frame) -{ - // Don't record management stats in cluster-unsafe contexts - if (mgmtObject != 0 && isClusterSafe()) - { - mgmtObject->inc_framesToClient(); - mgmtObject->inc_bytesToClient(frame.encodedSize()); - if (isMessage(frame.getMethod())) { - mgmtObject->inc_msgsToClient(); - } - } -} - -void Connection::recordFromClient(const framing::AMQFrame& frame) -{ - // Don't record management stats in cluster-unsafe contexts - if (mgmtObject != 0 && isClusterSafe()) - { - mgmtObject->inc_framesFromClient(); - mgmtObject->inc_bytesFromClient(frame.encodedSize()); - if (isMessage(frame.getMethod())) { - mgmtObject->inc_msgsFromClient(); - } - } -} - -string Connection::getAuthMechanism() -{ - if (!isLink) - return string("ANONYMOUS"); - - return links.getAuthMechanism(mgmtId); -} - -string Connection::getUsername ( ) -{ - if (!isLink) - return string("anonymous"); - - return links.getUsername(mgmtId); -} - -string Connection::getPassword ( ) -{ - if (!isLink) - return string(""); - - return links.getPassword(mgmtId); -} - -string Connection::getHost ( ) -{ - if (!isLink) - return string(""); - - return links.getHost(mgmtId); -} - -uint16_t Connection::getPort ( ) -{ - if (!isLink) - return 0; - - return links.getPort(mgmtId); -} - -string Connection::getAuthCredentials() -{ - if (!isLink) - return string(); - - if (mgmtObject != 0) - { - if (links.getAuthMechanism(mgmtId) == "ANONYMOUS") - mgmtObject->set_authIdentity("anonymous"); - else - mgmtObject->set_authIdentity(links.getAuthIdentity(mgmtId)); - } - - return links.getAuthCredentials(mgmtId); -} - -void Connection::notifyConnectionForced(const string& text) -{ - if (isLink) - links.notifyConnectionForced(mgmtId, text); -} - -void Connection::setUserId(const string& userId) -{ - ConnectionState::setUserId(userId); - // In a cluster, the cluster code will raise the connect event - // when the connection is replicated to the cluster. - if (!broker.isInCluster()) raiseConnectEvent(); -} - -void Connection::raiseConnectEvent() { - if (mgmtObject != 0) { - mgmtObject->set_authIdentity(userId); - agent->raiseEvent(_qmf::EventClientConnect(mgmtId, userId)); - } -} - -void Connection::setFederationLink(bool b) -{ - ConnectionState::setFederationLink(b); - if (mgmtObject != 0) - mgmtObject->set_federationLink(b); -} - -void Connection::close(connection::CloseCode code, const string& text) -{ - QPID_LOG_IF(error, code != connection::CLOSE_CODE_NORMAL, "Connection " << mgmtId << " closed by error: " << text << "(" << code << ")"); - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - adapter.close(code, text); - //make sure we delete dangling pointers from outputTasks before deleting sessions - outputTasks.removeAll(); - channels.clear(); - getOutput().close(); -} - -// Send a close to the client but keep the channels. Used by cluster. -void Connection::sendClose() { - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - adapter.close(connection::CLOSE_CODE_NORMAL, "OK"); - getOutput().close(); -} - -void Connection::idleOut(){} - -void Connection::idleIn(){} - -void Connection::closed(){ // Physically closed, suspend open sessions. - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - try { - while (!channels.empty()) - ptr_map_ptr(channels.begin())->handleDetach(); - } catch(std::exception& e) { - QPID_LOG(error, QPID_MSG("While closing connection: " << e.what())); - assert(0); - } -} - -void Connection::doIoCallbacks() { - { - ScopedLock<Mutex> l(ioCallbackLock); - // Although IO callbacks execute in the connection thread context, they are - // not cluster safe because they are queued for execution in non-IO threads. - ClusterUnsafeScope cus; - while (!ioCallbacks.empty()) { - boost::function0<void> cb = ioCallbacks.front(); - ioCallbacks.pop(); - ScopedUnlock<Mutex> ul(ioCallbackLock); - cb(); // Lend the IO thread for management processing - } - } -} - -bool Connection::doOutput() { - try { - doIoCallbacks(); - if (mgmtClosing) { - closed(); - close(connection::CLOSE_CODE_CONNECTION_FORCED, "Closed by Management Request"); - } else { - //then do other output as needed: - return outputTasks.doOutput(); - } - }catch(const SessionOutputException& e){ - getChannel(e.channel).handleException(e); - return true; - }catch(ConnectionException& e){ - close(e.code, e.getMessage()); - }catch(std::exception& e){ - close(connection::CLOSE_CODE_CONNECTION_FORCED, e.what()); - } - return false; -} - -void Connection::sendHeartbeat() { - adapter.heartbeat(); -} - -void Connection::closeChannel(uint16_t id) { - ChannelMap::iterator i = channels.find(id); - if (i != channels.end()) channels.erase(i); -} - -SessionHandler& Connection::getChannel(ChannelId id) { - ChannelMap::iterator i=channels.find(id); - if (i == channels.end()) { - i = channels.insert(id, new SessionHandler(*this, id)).first; - } - return *ptr_map_ptr(i); -} - -ManagementObject* Connection::GetManagementObject(void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t Connection::ManagementMethod(uint32_t methodId, Args&, string&) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - QPID_LOG(debug, "Connection::ManagementMethod [id=" << methodId << "]"); - - switch (methodId) - { - case _qmf::Connection::METHOD_CLOSE : - mgmtClosing = true; - if (mgmtObject != 0) mgmtObject->set_closing(1); - out.activateOutput(); - status = Manageable::STATUS_OK; - break; - } - - return status; -} - -void Connection::setSecureConnection(SecureConnection* s) -{ - adapter.setSecureConnection(s); -} - -struct ConnectionHeartbeatTask : public sys::TimerTask { - sys::Timer& timer; - Connection& connection; - ConnectionHeartbeatTask(uint16_t hb, sys::Timer& t, Connection& c) : - TimerTask(Duration(hb*TIME_SEC), "ConnectionHeartbeat"), - timer(t), - connection(c) - {} - - void fire() { - // Setup next firing - setupNextFire(); - timer.add(this); - - // Send Heartbeat - connection.sendHeartbeat(); - } -}; - -void Connection::abort() -{ - // Make sure that we don't try to send a heartbeat as we're - // aborting the connection - if (heartbeatTimer) - heartbeatTimer->cancel(); - - out.abort(); -} - -void Connection::setHeartbeatInterval(uint16_t heartbeat) -{ - setHeartbeat(heartbeat); - if (heartbeat > 0 && !isShadow()) { - heartbeatTimer = new ConnectionHeartbeatTask(heartbeat, timer, *this); - timer.add(heartbeatTimer); - timeoutTimer = new ConnectionTimeoutTask(heartbeat, timer, *this); - timer.add(timeoutTimer); - } -} - -void Connection::restartTimeout() -{ - if (timeoutTimer) - timeoutTimer->touch(); -} - -bool Connection::isOpen() { return adapter.isOpen(); } - -Connection::OutboundFrameTracker::OutboundFrameTracker(Connection& _con) : con(_con), next(0) {} -void Connection::OutboundFrameTracker::close() { next->close(); } -size_t Connection::OutboundFrameTracker::getBuffered() const { return next->getBuffered(); } -void Connection::OutboundFrameTracker::abort() { next->abort(); } -void Connection::OutboundFrameTracker::activateOutput() { next->activateOutput(); } -void Connection::OutboundFrameTracker::giveReadCredit(int32_t credit) { next->giveReadCredit(credit); } -void Connection::OutboundFrameTracker::send(framing::AMQFrame& f) -{ - next->send(f); - con.sent(f); -} -void Connection::OutboundFrameTracker::wrap(sys::ConnectionOutputHandlerPtr& p) -{ - next = p.get(); - p.set(this); -} - -}} diff --git a/cpp/src/qpid/broker/Connection.h b/cpp/src/qpid/broker/Connection.h deleted file mode 100644 index 8f1aa701ef..0000000000 --- a/cpp/src/qpid/broker/Connection.h +++ /dev/null @@ -1,216 +0,0 @@ -#ifndef QPID_BROKER_CONNECTION_H -#define QPID_BROKER_CONNECTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <memory> -#include <sstream> -#include <vector> -#include <queue> - -#include <boost/ptr_container/ptr_map.hpp> - -#include "qpid/broker/ConnectionHandler.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/SessionHandler.h" -#include "qmf/org/apache/qpid/broker/Connection.h" -#include "qpid/Exception.h" -#include "qpid/RefCounted.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/framing/AMQP_ServerOperations.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/management/Manageable.h" -#include "qpid/ptr_map.h" -#include "qpid/sys/AggregateOutput.h" -#include "qpid/sys/ConnectionInputHandler.h" -#include "qpid/sys/ConnectionOutputHandler.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/TimeoutHandler.h" -#include "qpid/sys/Mutex.h" - -#include <boost/ptr_container/ptr_map.hpp> -#include <boost/bind.hpp> - -#include <algorithm> - -namespace qpid { -namespace broker { - -class Broker; -class LinkRegistry; -class SecureConnection; -struct ConnectionTimeoutTask; - -class Connection : public sys::ConnectionInputHandler, - public ConnectionState, - public RefCounted -{ - public: - /** - * Listener that can be registered with a Connection to be informed of errors. - */ - class ErrorListener - { - public: - virtual ~ErrorListener() {} - virtual void sessionError(uint16_t channel, const std::string&) = 0; - virtual void connectionError(const std::string&) = 0; - }; - - Connection(sys::ConnectionOutputHandler* out, - Broker& broker, - const std::string& mgmtId, - const qpid::sys::SecuritySettings&, - bool isLink = false, - uint64_t objectId = 0, - bool shadow=false, - bool delayManagement = false); - - ~Connection (); - - /** Get the SessionHandler for channel. Create if it does not already exist */ - SessionHandler& getChannel(framing::ChannelId channel); - - /** Close the connection */ - void close(framing::connection::CloseCode code, const std::string& text); - - // ConnectionInputHandler methods - void received(framing::AMQFrame& frame); - void idleOut(); - void idleIn(); - bool doOutput(); - void closed(); - - void closeChannel(framing::ChannelId channel); - - // Manageable entry points - management::ManagementObject* GetManagementObject (void) const; - management::Manageable::status_t - ManagementMethod (uint32_t methodId, management::Args& args, std::string&); - - void requestIOProcessing (boost::function0<void>); - void recordFromServer (const framing::AMQFrame& frame); - void recordFromClient (const framing::AMQFrame& frame); - std::string getAuthMechanism(); - std::string getAuthCredentials(); - std::string getUsername(); - std::string getPassword(); - std::string getHost(); - uint16_t getPort(); - void notifyConnectionForced(const std::string& text); - void setUserId(const std::string& uid); - void raiseConnectEvent(); - const std::string& getUserId() const { return ConnectionState::getUserId(); } - const std::string& getMgmtId() const { return mgmtId; } - management::ManagementAgent* getAgent() const { return agent; } - void setFederationLink(bool b); - /** Connection does not delete the listener. 0 resets. */ - void setErrorListener(ErrorListener* l) { errorListener=l; } - ErrorListener* getErrorListener() { return errorListener; } - - void setHeartbeatInterval(uint16_t heartbeat); - void sendHeartbeat(); - void restartTimeout(); - void abort(); - - template <class F> void eachSessionHandler(F f) { - for (ChannelMap::iterator i = channels.begin(); i != channels.end(); ++i) - f(*ptr_map_ptr(i)); - } - - void sendClose(); - void setSecureConnection(SecureConnection* secured); - - /** True if this is a shadow connection in a cluster. */ - bool isShadow() { return shadow; } - - // Used by cluster to update connection status - sys::AggregateOutput& getOutputTasks() { return outputTasks; } - - /** Cluster delays adding management object in the constructor then calls this. */ - void addManagementObject(); - - const qpid::sys::SecuritySettings& getExternalSecuritySettings() const - { - return securitySettings; - } - - /** @return true if the initial connection negotiation is complete. */ - bool isOpen(); - - // Used by cluster during catch-up, see cluster::OutputInterceptor - void doIoCallbacks(); - - private: - typedef boost::ptr_map<framing::ChannelId, SessionHandler> ChannelMap; - typedef std::vector<boost::shared_ptr<Queue> >::iterator queue_iterator; - - ChannelMap channels; - qpid::sys::SecuritySettings securitySettings; - ConnectionHandler adapter; - const bool isLink; - bool mgmtClosing; - const std::string mgmtId; - sys::Mutex ioCallbackLock; - std::queue<boost::function0<void> > ioCallbacks; - qmf::org::apache::qpid::broker::Connection* mgmtObject; - LinkRegistry& links; - management::ManagementAgent* agent; - sys::Timer& timer; - boost::intrusive_ptr<sys::TimerTask> heartbeatTimer; - boost::intrusive_ptr<ConnectionTimeoutTask> timeoutTimer; - ErrorListener* errorListener; - uint64_t objectId; - bool shadow; - /** - * Chained ConnectionOutputHandler that allows outgoing frames to be - * tracked (for updating mgmt stats). - */ - class OutboundFrameTracker : public sys::ConnectionOutputHandler - { - public: - OutboundFrameTracker(Connection&); - void close(); - size_t getBuffered() const; - void abort(); - void activateOutput(); - void giveReadCredit(int32_t credit); - void send(framing::AMQFrame&); - void wrap(sys::ConnectionOutputHandlerPtr&); - private: - Connection& con; - sys::ConnectionOutputHandler* next; - }; - OutboundFrameTracker outboundTracker; - - - void sent(const framing::AMQFrame& f); - public: - qmf::org::apache::qpid::broker::Connection* getMgmtObject() { return mgmtObject; } -}; - -}} - -#endif /*!QPID_BROKER_CONNECTION_H*/ diff --git a/cpp/src/qpid/broker/ConnectionFactory.cpp b/cpp/src/qpid/broker/ConnectionFactory.cpp deleted file mode 100644 index 9e0020812b..0000000000 --- a/cpp/src/qpid/broker/ConnectionFactory.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/ConnectionFactory.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/amqp_0_10/Connection.h" -#include "qpid/broker/Connection.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -using framing::ProtocolVersion; -using qpid::sys::SecuritySettings; -typedef std::auto_ptr<amqp_0_10::Connection> ConnectionPtr; -typedef std::auto_ptr<sys::ConnectionInputHandler> InputPtr; - -ConnectionFactory::ConnectionFactory(Broker& b) : broker(b) {} - -ConnectionFactory::~ConnectionFactory() {} - -sys::ConnectionCodec* -ConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - if (broker.getConnectionCounter().allowConnection()) - { - QPID_LOG(error, "Client max connection count limit exceeded: " << broker.getOptions().maxConnections << " connection refused"); - return 0; - } - if (v == ProtocolVersion(0, 10)) { - ConnectionPtr c(new amqp_0_10::Connection(out, id, false)); - c->setInputHandler(InputPtr(new broker::Connection(c.get(), broker, id, external, false))); - return c.release(); - } - return 0; -} - -sys::ConnectionCodec* -ConnectionFactory::create(sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - // used to create connections from one broker to another - ConnectionPtr c(new amqp_0_10::Connection(out, id, true)); - c->setInputHandler(InputPtr(new broker::Connection(c.get(), broker, id, external, true))); - return c.release(); -} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/ConnectionFactory.h b/cpp/src/qpid/broker/ConnectionFactory.h deleted file mode 100644 index 7c1a9a08e1..0000000000 --- a/cpp/src/qpid/broker/ConnectionFactory.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionFactory_ -#define _ConnectionFactory_ - -#include "qpid/sys/ConnectionCodec.h" - -namespace qpid { -namespace broker { -class Broker; - -class ConnectionFactory : public sys::ConnectionCodec::Factory -{ - public: - ConnectionFactory(Broker& b); - - virtual ~ConnectionFactory(); - - sys::ConnectionCodec* - create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id, - const qpid::sys::SecuritySettings&); - - sys::ConnectionCodec* - create(sys::OutputControl&, const std::string& id, const qpid::sys::SecuritySettings&); - - private: - Broker& broker; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/ConnectionHandler.cpp b/cpp/src/qpid/broker/ConnectionHandler.cpp deleted file mode 100644 index 3f97e5b9de..0000000000 --- a/cpp/src/qpid/broker/ConnectionHandler.cpp +++ /dev/null @@ -1,364 +0,0 @@ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/SaslFactory.h" -#include "qpid/broker/ConnectionHandler.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/SecureConnection.h" -#include "qpid/Url.h" -#include "qpid/framing/AllInvoker.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/broker/AclModule.h" -#include "qmf/org/apache/qpid/broker/EventClientConnectFail.h" - -using namespace qpid; -using namespace qpid::broker; -using namespace qpid::framing; -using qpid::sys::SecurityLayer; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace -{ -const std::string ANONYMOUS = "ANONYMOUS"; -const std::string PLAIN = "PLAIN"; -const std::string en_US = "en_US"; -const std::string QPID_FED_LINK = "qpid.fed_link"; -const std::string QPID_FED_TAG = "qpid.federation_tag"; -const std::string SESSION_FLOW_CONTROL("qpid.session_flow"); -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -const std::string CLIENT_PPID("qpid.client_ppid"); -const int SESSION_FLOW_CONTROL_VER = 1; -const std::string SPACE(" "); -} - -void ConnectionHandler::close(connection::CloseCode code, const string& text) -{ - handler->proxy.close(code, text); -} - -void ConnectionHandler::heartbeat() -{ - handler->proxy.heartbeat(); -} - -void ConnectionHandler::handle(framing::AMQFrame& frame) -{ - AMQMethodBody* method=frame.getBody()->getMethod(); - Connection::ErrorListener* errorListener = handler->connection.getErrorListener(); - try{ - if (!invoke(static_cast<AMQP_AllOperations::ConnectionHandler&>(*handler.get()), *method)) { - handler->connection.getChannel(frame.getChannel()).in(frame); - } - }catch(ConnectionException& e){ - if (errorListener) errorListener->connectionError(e.what()); - handler->proxy.close(e.code, e.what()); - }catch(std::exception& e){ - if (errorListener) errorListener->connectionError(e.what()); - handler->proxy.close(541/*internal error*/, e.what()); - } -} - -void ConnectionHandler::setSecureConnection(SecureConnection* secured) -{ - handler->secured = secured; -} - -ConnectionHandler::ConnectionHandler(Connection& connection, bool isClient, bool isShadow) : handler(new Handler(connection, isClient, isShadow)) {} - -ConnectionHandler::Handler::Handler(Connection& c, bool isClient, bool isShadow) : - proxy(c.getOutput()), - connection(c), serverMode(!isClient), acl(0), secured(0), - isOpen(false) -{ - if (serverMode) { - - acl = connection.getBroker().getAcl(); - - FieldTable properties; - Array mechanisms(0x95); - - properties.setString(QPID_FED_TAG, connection.getBroker().getFederationTag()); - - authenticator = SaslAuthenticator::createAuthenticator(c, isShadow); - authenticator->getMechanisms(mechanisms); - - Array locales(0x95); - boost::shared_ptr<FieldValue> l(new Str16Value(en_US)); - locales.add(l); - proxy.start(properties, mechanisms, locales); - - } - - maxFrameSize = (64 * 1024) - 1; -} - - -ConnectionHandler::Handler::~Handler() {} - - -void ConnectionHandler::Handler::startOk(const framing::FieldTable& clientProperties, - const string& mechanism, - const string& response, - const string& /*locale*/) -{ - try { - authenticator->start(mechanism, response); - } catch (std::exception& /*e*/) { - management::ManagementAgent* agent = connection.getAgent(); - if (agent) { - string error; - string uid; - authenticator->getError(error); - authenticator->getUid(uid); - agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error)); - } - throw; - } - connection.setFederationLink(clientProperties.get(QPID_FED_LINK)); - connection.setFederationPeerTag(clientProperties.getAsString(QPID_FED_TAG)); - if (connection.isFederationLink()) { - if (acl && !acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){ - proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,"ACL denied creating a federation link"); - return; - } - QPID_LOG(info, "Connection is a federation link"); - } - if (clientProperties.getAsInt(SESSION_FLOW_CONTROL) == SESSION_FLOW_CONTROL_VER) { - connection.setClientThrottling(); - } - - if (connection.getMgmtObject() != 0) { - string procName = clientProperties.getAsString(CLIENT_PROCESS_NAME); - uint32_t pid = clientProperties.getAsInt(CLIENT_PID); - uint32_t ppid = clientProperties.getAsInt(CLIENT_PPID); - - if (!procName.empty()) - connection.getMgmtObject()->set_remoteProcessName(procName); - if (pid != 0) - connection.getMgmtObject()->set_remotePid(pid); - if (ppid != 0) - connection.getMgmtObject()->set_remoteParentPid(ppid); - } -} - -void ConnectionHandler::Handler::secureOk(const string& response) -{ - try { - authenticator->step(response); - } catch (std::exception& /*e*/) { - management::ManagementAgent* agent = connection.getAgent(); - if (agent) { - string error; - string uid; - authenticator->getError(error); - authenticator->getUid(uid); - agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error)); - } - throw; - } -} - -void ConnectionHandler::Handler::tuneOk(uint16_t /*channelmax*/, - uint16_t framemax, uint16_t heartbeat) -{ - connection.setFrameMax(framemax); - connection.setHeartbeatInterval(heartbeat); -} - -void ConnectionHandler::Handler::open(const string& /*virtualHost*/, - const framing::Array& /*capabilities*/, bool /*insist*/) -{ - std::vector<Url> urls = connection.broker.getKnownBrokers(); - framing::Array array(0x95); // str16 array - for (std::vector<Url>::iterator i = urls.begin(); i < urls.end(); ++i) - array.add(boost::shared_ptr<Str16Value>(new Str16Value(i->str()))); - - //install security layer if one has been negotiated: - if (secured) { - std::auto_ptr<SecurityLayer> sl = authenticator->getSecurityLayer(connection.getFrameMax()); - if (sl.get()) secured->activateSecurityLayer(sl); - } - - isOpen = true; - proxy.openOk(array); -} - - -void ConnectionHandler::Handler::close(uint16_t replyCode, const string& replyText) -{ - if (replyCode != 200) { - QPID_LOG(warning, "Client closed connection with " << replyCode << ": " << replyText); - } - - if (replyCode == framing::connection::CLOSE_CODE_CONNECTION_FORCED) - connection.notifyConnectionForced(replyText); - - proxy.closeOk(); - connection.getOutput().close(); -} - -void ConnectionHandler::Handler::closeOk(){ - connection.getOutput().close(); -} - -void ConnectionHandler::Handler::heartbeat(){ - // For general case, do nothing - the purpose of heartbeats is - // just to make sure that there is some traffic on the connection - // within the heart beat interval, we check for the traffic and - // don't need to do anything in response to heartbeats. The - // exception is when we are in fact the client to another broker - // (i.e. an inter-broker link), in which case we echo the - // heartbeat back to the peer - if (!serverMode) proxy.heartbeat(); -} - -void ConnectionHandler::Handler::start(const FieldTable& serverProperties, - const framing::Array& supportedMechanisms, - const framing::Array& /*locales*/) -{ - string requestedMechanism = connection.getAuthMechanism(); - - std::string username = connection.getUsername(); - - std::string password = connection.getPassword(); - std::string host = connection.getHost(); - std::string service("qpidd"); - - if ( connection.getBroker().isAuthenticating() ) { - sasl = SaslFactory::getInstance().create( username, - password, - service, - host, - 0, // TODO -- mgoulish Fri Sep 24 2010 - 256, - false ); // disallow interaction - } - std::string supportedMechanismsList; - bool requestedMechanismIsSupported = false; - Array::const_iterator i; - - /* - If no specific mechanism has been requested, just make - a list of all of them, and assert that the one the caller - requested is there. ( If *any* are supported! ) - */ - if ( requestedMechanism.empty() ) { - for ( i = supportedMechanisms.begin(); i != supportedMechanisms.end(); ++i) { - if (i != supportedMechanisms.begin()) - supportedMechanismsList += SPACE; - supportedMechanismsList += (*i)->get<std::string>(); - requestedMechanismIsSupported = true; - } - } - else { - requestedMechanismIsSupported = false; - /* - The caller has requested a mechanism. If it's available, - make sure it ends up at the head of the list. - */ - for ( i = supportedMechanisms.begin(); i != supportedMechanisms.end(); ++i) { - string currentMechanism = (*i)->get<std::string>(); - - if ( requestedMechanism == currentMechanism ) { - requestedMechanismIsSupported = true; - supportedMechanismsList = currentMechanism + SPACE + supportedMechanismsList; - } else { - if (i != supportedMechanisms.begin()) - supportedMechanismsList += SPACE; - supportedMechanismsList += currentMechanism; - } - } - } - - connection.setFederationPeerTag(serverProperties.getAsString(QPID_FED_TAG)); - - FieldTable ft; - ft.setInt(QPID_FED_LINK,1); - ft.setString(QPID_FED_TAG, connection.getBroker().getFederationTag()); - - string response; - if (sasl.get()) { - const qpid::sys::SecuritySettings& ss = connection.getExternalSecuritySettings(); - response = sasl->start ( requestedMechanism.empty() - ? supportedMechanismsList - : requestedMechanism, - & ss ); - proxy.startOk ( ft, sasl->getMechanism(), response, en_US ); - } - else { - response = ((char)0) + username + ((char)0) + password; - proxy.startOk ( ft, requestedMechanism, response, en_US ); - } - -} - -void ConnectionHandler::Handler::secure(const string& challenge ) -{ - if (sasl.get()) { - string response = sasl->step(challenge); - proxy.secureOk(response); - } - else { - proxy.secureOk(""); - } -} - -void ConnectionHandler::Handler::tune(uint16_t channelMax, - uint16_t maxFrameSizeProposed, - uint16_t /*heartbeatMin*/, - uint16_t heartbeatMax) -{ - maxFrameSize = std::min(maxFrameSize, maxFrameSizeProposed); - connection.setFrameMax(maxFrameSize); - - connection.setHeartbeat(heartbeatMax); - proxy.tuneOk(channelMax, maxFrameSize, heartbeatMax); - proxy.open("/", Array(), true); -} - -void ConnectionHandler::Handler::openOk(const framing::Array& knownHosts) -{ - for (Array::ValueVector::const_iterator i = knownHosts.begin(); i != knownHosts.end(); ++i) { - Url url((*i)->get<std::string>()); - connection.getKnownHosts().push_back(url); - } - - if (sasl.get()) { - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer = sasl->getSecurityLayer(maxFrameSize); - - if ( securityLayer.get() ) { - secured->activateSecurityLayer(securityLayer, true); - } - - saslUserId = sasl->getUserId(); - } - - isOpen = true; -} - -void ConnectionHandler::Handler::redirect(const string& /*host*/, const framing::Array& /*knownHosts*/) -{ - -} diff --git a/cpp/src/qpid/broker/ConnectionHandler.h b/cpp/src/qpid/broker/ConnectionHandler.h deleted file mode 100644 index b32167669e..0000000000 --- a/cpp/src/qpid/broker/ConnectionHandler.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionAdapter_ -#define _ConnectionAdapter_ - -#include <memory> -#include "qpid/Sasl.h" -#include "qpid/broker/SaslAuthenticator.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQP_AllOperations.h" -#include "qpid/framing/AMQP_AllProxy.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/Exception.h" -#include "qpid/broker/AclModule.h" -#include "qpid/sys/SecurityLayer.h" - - -namespace qpid { - -namespace sys { -struct SecuritySettings; -} - - -namespace broker { - -class Connection; -class SecureConnection; - -class ConnectionHandler : public framing::FrameHandler -{ - struct Handler : public framing::AMQP_AllOperations::ConnectionHandler - { - framing::AMQP_AllProxy::Connection proxy; - Connection& connection; - bool serverMode; - std::auto_ptr<SaslAuthenticator> authenticator; - AclModule* acl; - SecureConnection* secured; - bool isOpen; - - Handler(Connection& connection, bool isClient, bool isShadow=false); - ~Handler(); - void startOk(const qpid::framing::FieldTable& clientProperties, - const std::string& mechanism, const std::string& response, - const std::string& locale); - void secureOk(const std::string& response); - void tuneOk(uint16_t channelMax, uint16_t frameMax, uint16_t heartbeat); - void heartbeat(); - void open(const std::string& virtualHost, - const framing::Array& capabilities, bool insist); - void close(uint16_t replyCode, const std::string& replyText); - void closeOk(); - - void start(const qpid::framing::FieldTable& serverProperties, - const framing::Array& mechanisms, - const framing::Array& locales); - - void secure(const std::string& challenge); - - void tune(uint16_t channelMax, - uint16_t frameMax, - uint16_t heartbeatMin, - uint16_t heartbeatMax); - - void openOk(const framing::Array& knownHosts); - - void redirect(const std::string& host, const framing::Array& knownHosts); - - std::auto_ptr<Sasl> sasl; - typedef boost::function<const qpid::sys::SecuritySettings*()> GetSecuritySettings; - std::string saslUserId; - uint16_t maxFrameSize; - }; - std::auto_ptr<Handler> handler; - - - public: - ConnectionHandler(Connection& connection, bool isClient, bool isShadow=false ); - void close(framing::connection::CloseCode code, const std::string& text); - void heartbeat(); - void handle(framing::AMQFrame& frame); - void setSecureConnection(SecureConnection* secured); - bool isOpen() { return handler->isOpen; } -}; - - -}} - -#endif diff --git a/cpp/src/qpid/broker/ConnectionState.h b/cpp/src/qpid/broker/ConnectionState.h deleted file mode 100644 index 9c31a931d8..0000000000 --- a/cpp/src/qpid/broker/ConnectionState.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionState_ -#define _ConnectionState_ - -#include <vector> - -#include "qpid/sys/AggregateOutput.h" -#include "qpid/sys/ConnectionOutputHandlerPtr.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/management/Manageable.h" -#include "qpid/Url.h" -#include "qpid/broker/Broker.h" - -namespace qpid { -namespace broker { - -class ConnectionState : public ConnectionToken, public management::Manageable -{ - protected: - sys::ConnectionOutputHandlerPtr out; - - public: - ConnectionState(qpid::sys::ConnectionOutputHandler* o, Broker& b) : - out(o), - broker(b), - outputTasks(out), - framemax(65535), - heartbeat(0), - heartbeatmax(120), - federationLink(true), - clientSupportsThrottling(false), - clusterOrderOut(0) - {} - - virtual ~ConnectionState () {} - - uint32_t getFrameMax() const { return framemax; } - uint16_t getHeartbeat() const { return heartbeat; } - uint16_t getHeartbeatMax() const { return heartbeatmax; } - - void setFrameMax(uint32_t fm) { framemax = std::max(fm, (uint32_t) 4096); } - void setHeartbeat(uint16_t hb) { heartbeat = hb; } - void setHeartbeatMax(uint16_t hbm) { heartbeatmax = hbm; } - - virtual void setUserId(const std::string& uid) { userId = uid; } - const std::string& getUserId() const { return userId; } - - void setUrl(const std::string& _url) { url = _url; } - const std::string& getUrl() const { return url; } - - void setFederationLink(bool b) { federationLink = b; } - bool isFederationLink() const { return federationLink; } - void setFederationPeerTag(const std::string& tag) { federationPeerTag = std::string(tag); } - const std::string& getFederationPeerTag() const { return federationPeerTag; } - std::vector<Url>& getKnownHosts() { return knownHosts; } - - void setClientThrottling(bool set=true) { clientSupportsThrottling = set; } - bool getClientThrottling() const { return clientSupportsThrottling; } - - Broker& getBroker() { return broker; } - - Broker& broker; - - //contained output tasks - sys::AggregateOutput outputTasks; - - sys::ConnectionOutputHandler& getOutput() { return out; } - framing::ProtocolVersion getVersion() const { return version; } - void setOutputHandler(qpid::sys::ConnectionOutputHandler* o) { out.set(o); } - - /** - * If the broker is part of a cluster, this is a handler provided - * by cluster code. It ensures consistent ordering of commands - * that are sent based on criteria that are not predictably - * ordered cluster-wide, e.g. a timer firing. - */ - framing::FrameHandler* getClusterOrderOutput() { return clusterOrderOut; } - void setClusterOrderOutput(framing::FrameHandler& fh) { clusterOrderOut = &fh; } - - virtual void requestIOProcessing (boost::function0<void>) = 0; - - protected: - framing::ProtocolVersion version; - uint32_t framemax; - uint16_t heartbeat; - uint16_t heartbeatmax; - std::string userId; - std::string url; - bool federationLink; - std::string federationPeerTag; - std::vector<Url> knownHosts; - bool clientSupportsThrottling; - framing::FrameHandler* clusterOrderOut; -}; - -}} - -#endif diff --git a/cpp/src/qpid/broker/ConnectionToken.h b/cpp/src/qpid/broker/ConnectionToken.h deleted file mode 100644 index 9b40383c80..0000000000 --- a/cpp/src/qpid/broker/ConnectionToken.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionToken_ -#define _ConnectionToken_ - -#include "qpid/broker/OwnershipToken.h" -namespace qpid { - namespace broker { - /** - * An empty interface allowing opaque implementations of some - * form of token to identify a connection. - */ - class ConnectionToken : public OwnershipToken { - public: - virtual bool isLocal(const ConnectionToken* t) const { return this == t; } - virtual ~ConnectionToken(){} - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/Consumer.h b/cpp/src/qpid/broker/Consumer.h deleted file mode 100644 index 317338a8ad..0000000000 --- a/cpp/src/qpid/broker/Consumer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Consumer_ -#define _Consumer_ - -#include "qpid/broker/Message.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/broker/OwnershipToken.h" - -namespace qpid { -namespace broker { - -class Queue; -class QueueListeners; - -class Consumer { - const bool acquires; - // inListeners allows QueueListeners to efficiently track if this instance is registered - // for notifications without having to search its containers - bool inListeners; - public: - typedef boost::shared_ptr<Consumer> shared_ptr; - - framing::SequenceNumber position; - - Consumer(bool preAcquires = true) : acquires(preAcquires), inListeners(false) {} - bool preAcquires() const { return acquires; } - virtual bool deliver(QueuedMessage& msg) = 0; - virtual void notify() = 0; - virtual bool filter(boost::intrusive_ptr<Message>) { return true; } - virtual bool accept(boost::intrusive_ptr<Message>) { return true; } - virtual OwnershipToken* getSession() = 0; - virtual ~Consumer(){} - friend class QueueListeners; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/Daemon.cpp b/cpp/src/qpid/broker/Daemon.cpp deleted file mode 100644 index b30e5f18cb..0000000000 --- a/cpp/src/qpid/broker/Daemon.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * TODO: Note this is really a Posix specific implementation and so should be - * refactored together with windows/QpiddBroker into a more coherent daemon driver/ - * platform specific split - */ -#include "qpid/broker/Daemon.h" -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" -#include "qpid/sys/posix/PidFile.h" - -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -namespace qpid { -namespace broker { - -using namespace std; -using qpid::sys::PidFile; - -Daemon::Daemon(std::string _pidDir) : pidDir(_pidDir) { - struct stat s; - pid = -1; - pipeFds[0] = pipeFds[1] = -1; - - if (::stat(pidDir.c_str(), &s)) { - if (errno == ENOENT) { - if (::mkdir(pidDir.c_str(), 0755)) - throw Exception ("Can't create PID directory: " + pidDir); - } - else - throw Exception ("PID directory not found: " + pidDir); - } -} - -string Daemon::pidFile(string pidDir, uint16_t port) { - ostringstream path; - path << pidDir << "/qpidd." << port << ".pid"; - return path.str(); -} - -/* - * Rewritten using low-level IO, for compatibility - * with earlier Boost versions, i.e. 103200. - */ -void Daemon::fork() -{ - if(::pipe(pipeFds) < 0) throw ErrnoException("Can't create pipe"); - if ((pid = ::fork()) < 0) throw ErrnoException("Daemon fork failed"); - if (pid == 0) { // Child - try { - QPID_LOG(debug, "Forked daemon child process"); - - // File descriptors - if(::close(pipeFds[0])<0) throw ErrnoException("Cannot close read pipe"); - if(::close(0)<0) throw ErrnoException("Cannot close stdin"); - if(::close(1)<0) throw ErrnoException("Cannot close stdout"); - if(::close(2)<0) throw ErrnoException("Cannot close stderr"); - int fd=::open("/dev/null",O_RDWR); // stdin - if(fd != 0) throw ErrnoException("Cannot re-open stdin"); - if(::dup(fd)<0) throw ErrnoException("Cannot re-open stdout"); - if(::dup(fd)<0) throw ErrnoException("Cannot re-open stderror"); - - // Misc - if(setsid()<0) throw ErrnoException("Cannot set session ID"); - if(chdir(pidDir.c_str()) < 0) throw ErrnoException("Cannot change directory to "+pidDir); - umask(027); - - // Child behavior - child(); - } - catch (const exception& e) { - QPID_LOG(critical, "Unexpected error: " << e.what()); - uint16_t port = 0; - int unused_ret; //Supress warning about ignoring return value. - unused_ret = write(pipeFds[1], &port, sizeof(uint16_t)); - - std::string pipeFailureMessage = e.what(); - unused_ret = write ( pipeFds[1], - pipeFailureMessage.c_str(), - strlen(pipeFailureMessage.c_str()) - ); - } - } - else { // Parent - close(pipeFds[1]); // Write side. - parent(); - } -} - -Daemon::~Daemon() { - if (!lockFile.empty()) - unlink(lockFile.c_str()); -} - -uint16_t Daemon::wait(int timeout) { // parent waits for child. - try { - errno = 0; - struct timeval tv; - tv.tv_sec = timeout; - tv.tv_usec = 0; - - /* - * Rewritten using low-level IO, for compatibility - * with earlier Boost versions, i.e. 103200. - */ - fd_set fds; - FD_ZERO(&fds); - FD_SET(pipeFds[0], &fds); - int n=select(FD_SETSIZE, &fds, 0, 0, &tv); - if(n==0) throw Exception("Timed out waiting for daemon (If store recovery is in progress, use longer wait time)"); - if(n<0) throw ErrnoException("Error waiting for daemon"); - uint16_t port = 0; - /* - * Read the child's port number from the pipe. - */ - int desired_read = sizeof(uint16_t); - if ( desired_read > ::read(pipeFds[0], & port, desired_read) ) - throw Exception("Cannot read from child process."); - - /* - * If the port number is 0, the child has put an error message - * on the pipe. Get it and throw it. - */ - if ( 0 == port ) { - // Skip whitespace - char c = ' '; - while ( isspace(c) ) { - if ( 1 > ::read(pipeFds[0], &c, 1) ) - throw Exception("Child port == 0, and no error message on pipe."); - } - - // Get Message - string errmsg; - do { - errmsg += c; - } while (::read(pipeFds[0], &c, 1)); - throw Exception("Daemon startup failed"+ - (errmsg.empty() ? string(".") : ": " + errmsg)); - } - return port; - } - catch (const std::exception& e) { - // Print directly to cerr. The caller will catch and log the - // exception, but in the case of a daemon parent process we - // also need to be sure the error goes to stderr. A - // dameon's logging configuration normally does not log to - // stderr. - std::cerr << e.what() << endl; - throw; - } -} - - -/* - * When the child is ready, it writes its pid to the - * lockfile and its port number on the pipe back to - * its parent process. This indicates that the - * child has successfully daemonized. When the parent - * hears the good news, it ill exit. - */ -void Daemon::ready(uint16_t port) { // child - lockFile = pidFile(pidDir, port); - PidFile lf(lockFile, true); - - /* - * Write the PID to the lockfile. - */ - lf.writePid(); - - /* - * Write the port number to the parent. - */ - int desired_write = sizeof(uint16_t); - if ( desired_write > ::write(pipeFds[1], & port, desired_write) ) { - throw Exception("Error writing to parent." ); - } - - QPID_LOG(debug, "Daemon ready on port: " << port); -} - -/* - * The parent process reads the child's pid - * from the lockfile. - */ -pid_t Daemon::getPid(string _pidDir, uint16_t port) { - string name = pidFile(_pidDir, port); - PidFile lf(name, false); - pid_t pid = lf.readPid(); - if (kill(pid, 0) < 0 && errno != EPERM) { - unlink(name.c_str()); - throw Exception("Removing stale lock file "+name); - } - return pid; -} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/Daemon.h b/cpp/src/qpid/broker/Daemon.h deleted file mode 100644 index a9cd98bce2..0000000000 --- a/cpp/src/qpid/broker/Daemon.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _broker_Daemon_h -#define _broker_Daemon_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" -#include <boost/scoped_ptr.hpp> -#include <boost/function.hpp> -#include <boost/noncopyable.hpp> -#include <string> - - -namespace qpid { -namespace broker { - -/** - * Tools for forking and managing a daemon process. - * NB: Only one Daemon instance is allowed in a process. - */ -class Daemon : private boost::noncopyable -{ - public: - /** Check daemon is running on port, throw exception if not */ - static pid_t getPid(std::string pidDir, uint16_t port); - - Daemon(std::string pidDir); - - virtual ~Daemon(); - - /** - * Fork a daemon process. - * Call parent() in the parent process, child() in the child. - */ - void fork(); - - protected: - - /** Called in parent process */ - virtual void parent() = 0; - - /** Called in child process */ - virtual void child() = 0; - - /** Call from parent(): wait for child to indicate it is ready. - * @timeout in seconds to wait for response. - * @return port passed by child to ready(). - */ - uint16_t wait(int timeout); - - /** Call from child(): Notify the parent we are ready and write the - * PID file. - *@param port returned by parent call to wait(). - */ - void ready(uint16_t port); - - private: - static std::string pidFile(std::string pidDir, uint16_t port); - - pid_t pid; - int pipeFds[2]; - int lockFileFd; - std::string lockFile; - std::string pidDir; -}; - -}} // namespace qpid::broker - -#endif /*!_broker_Daemon_h*/ diff --git a/cpp/src/qpid/broker/Deliverable.h b/cpp/src/qpid/broker/Deliverable.h deleted file mode 100644 index ffb5a77bca..0000000000 --- a/cpp/src/qpid/broker/Deliverable.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Deliverable_ -#define _Deliverable_ - -#include "qpid/broker/Message.h" - -namespace qpid { - namespace broker { - class Deliverable{ - public: - bool delivered; - Deliverable() : delivered(false) {} - - virtual Message& getMessage() = 0; - - virtual void deliverTo(const boost::shared_ptr<Queue>& queue) = 0; - virtual uint64_t contentSize() { return 0; } - virtual ~Deliverable(){} - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/DeliverableMessage.cpp b/cpp/src/qpid/broker/DeliverableMessage.cpp deleted file mode 100644 index 3ebb12461c..0000000000 --- a/cpp/src/qpid/broker/DeliverableMessage.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/Queue.h" - -using namespace qpid::broker; - -DeliverableMessage::DeliverableMessage(const boost::intrusive_ptr<Message>& _msg) : msg(_msg) -{ -} - -void DeliverableMessage::deliverTo(const boost::shared_ptr<Queue>& queue) -{ - queue->deliver(msg); - delivered = true; -} - -Message& DeliverableMessage::getMessage() -{ - return *msg; -} - -uint64_t DeliverableMessage::contentSize () -{ - return msg->contentSize (); -} diff --git a/cpp/src/qpid/broker/DeliverableMessage.h b/cpp/src/qpid/broker/DeliverableMessage.h deleted file mode 100644 index c8d21001eb..0000000000 --- a/cpp/src/qpid/broker/DeliverableMessage.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DeliverableMessage_ -#define _DeliverableMessage_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - namespace broker { - class QPID_BROKER_CLASS_EXTERN DeliverableMessage : public Deliverable{ - boost::intrusive_ptr<Message> msg; - public: - QPID_BROKER_EXTERN DeliverableMessage(const boost::intrusive_ptr<Message>& msg); - QPID_BROKER_EXTERN virtual void deliverTo(const boost::shared_ptr<Queue>& queue); - QPID_BROKER_EXTERN Message& getMessage(); - QPID_BROKER_EXTERN uint64_t contentSize(); - virtual ~DeliverableMessage(){} - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/DeliveryAdapter.h b/cpp/src/qpid/broker/DeliveryAdapter.h deleted file mode 100644 index b0bec60890..0000000000 --- a/cpp/src/qpid/broker/DeliveryAdapter.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DeliveryAdapter_ -#define _DeliveryAdapter_ - -#include "qpid/broker/DeliveryId.h" -#include "qpid/broker/Message.h" -#include "qpid/framing/amqp_types.h" - -namespace qpid { -namespace broker { - -class DeliveryRecord; - -/** - * The intention behind this interface is to separate the generic - * handling of some form of message delivery to clients that is - * contained in the version independent Channel class from the - * details required for a particular situation or - * version. i.e. where the existing adapters allow (through - * supporting the generated interface for a version of the - * protocol) inputs of a channel to be adapted to the version - * independent part, this does the same for the outputs. - */ -class DeliveryAdapter -{ - public: - virtual void deliver(DeliveryRecord&, bool sync) = 0; - virtual ~DeliveryAdapter(){} -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/DeliveryId.h b/cpp/src/qpid/broker/DeliveryId.h deleted file mode 100644 index 05b19f032e..0000000000 --- a/cpp/src/qpid/broker/DeliveryId.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DeliveryId_ -#define _DeliveryId_ - -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceNumberSet.h" - -namespace qpid { -namespace broker { - - typedef framing::SequenceNumber DeliveryId; - typedef framing::SequenceNumberSet DeliveryIds; -}} - - -#endif diff --git a/cpp/src/qpid/broker/DeliveryRecord.cpp b/cpp/src/qpid/broker/DeliveryRecord.cpp deleted file mode 100644 index 58dcc6d7c7..0000000000 --- a/cpp/src/qpid/broker/DeliveryRecord.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Queue.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/MessageTransferBody.h" - -using namespace qpid; -using namespace qpid::broker; -using std::string; - -DeliveryRecord::DeliveryRecord(const QueuedMessage& _msg, - const Queue::shared_ptr& _queue, - const std::string& _tag, - bool _acquired, - bool accepted, - bool _windowing, - uint32_t _credit) : msg(_msg), - queue(_queue), - tag(_tag), - acquired(_acquired), - acceptExpected(!accepted), - cancelled(false), - completed(false), - ended(accepted && acquired), - windowing(_windowing), - credit(msg.payload ? msg.payload->getRequiredCredit() : _credit) -{} - -bool DeliveryRecord::setEnded() -{ - ended = true; - //reset msg pointer, don't need to hold on to it anymore - msg.payload = boost::intrusive_ptr<Message>(); - QPID_LOG(debug, "DeliveryRecord::setEnded() id=" << id); - return isRedundant(); -} - -void DeliveryRecord::redeliver(SemanticState* const session) { - if (!ended) { - if(cancelled){ - //if subscription was cancelled, requeue it (waiting for - //final confirmation for AMQP WG on this case) - requeue(); - }else{ - msg.payload->redeliver();//mark as redelivered - session->deliver(*this, false); - } - } -} - -void DeliveryRecord::deliver(framing::FrameHandler& h, DeliveryId deliveryId, uint16_t framesize) -{ - id = deliveryId; - if (msg.payload->getRedelivered()){ - msg.payload->getProperties<framing::DeliveryProperties>()->setRedelivered(true); - } - msg.payload->adjustTtl(); - - framing::AMQFrame method((framing::MessageTransferBody(framing::ProtocolVersion(), tag, acceptExpected ? 0 : 1, acquired ? 0 : 1))); - method.setEof(false); - h.handle(method); - msg.payload->sendHeader(h, framesize); - msg.payload->sendContent(*queue, h, framesize); -} - -void DeliveryRecord::requeue() const -{ - if (acquired && !ended) { - msg.payload->redeliver(); - queue->requeue(msg); - } -} - -void DeliveryRecord::release(bool setRedelivered) -{ - if (acquired && !ended) { - if (setRedelivered) msg.payload->redeliver(); - queue->requeue(msg); - acquired = false; - setEnded(); - } else { - QPID_LOG(debug, "Ignoring release for " << id << " acquired=" << acquired << ", ended =" << ended); - } -} - -void DeliveryRecord::complete() { - completed = true; -} - -bool DeliveryRecord::accept(TransactionContext* ctxt) { - if (acquired && !ended) { - queue->dequeue(ctxt, msg); - setEnded(); - QPID_LOG(debug, "Accepted " << id); - } - return isRedundant(); -} - -void DeliveryRecord::dequeue(TransactionContext* ctxt) const{ - if (acquired && !ended) { - queue->dequeue(ctxt, msg); - } -} - -void DeliveryRecord::committed() const{ - queue->dequeueCommitted(msg); -} - -void DeliveryRecord::reject() -{ - if (acquired && !ended) { - Exchange::shared_ptr alternate = queue->getAlternateExchange(); - if (alternate) { - DeliverableMessage delivery(msg.payload); - alternate->routeWithAlternate(delivery); - QPID_LOG(info, "Routed rejected message from " << queue->getName() << " to " - << alternate->getName()); - } else { - //just drop it - QPID_LOG(info, "Dropping rejected message from " << queue->getName()); - } - dequeue(); - setEnded(); - } -} - -uint32_t DeliveryRecord::getCredit() const -{ - return credit; -} - -void DeliveryRecord::acquire(DeliveryIds& results) { - if (queue->acquire(msg)) { - acquired = true; - results.push_back(id); - if (!acceptExpected) { - if (ended) { QPID_LOG(error, "Can't dequeue ended message"); } - else { queue->dequeue(0, msg); setEnded(); } - } - } else { - QPID_LOG(info, "Message already acquired " << id.getValue()); - } -} - -void DeliveryRecord::cancel(const std::string& cancelledTag) -{ - if (tag == cancelledTag) - cancelled = true; -} - -AckRange DeliveryRecord::findRange(DeliveryRecords& records, DeliveryId first, DeliveryId last) -{ - DeliveryRecords::iterator start = lower_bound(records.begin(), records.end(), first); - // Find end - position it just after the last record in range - DeliveryRecords::iterator end = lower_bound(records.begin(), records.end(), last); - if (end != records.end() && end->getId() == last) ++end; - return AckRange(start, end); -} - - -namespace qpid { -namespace broker { - -std::ostream& operator<<(std::ostream& out, const DeliveryRecord& r) -{ - out << "{" << "id=" << r.id.getValue(); - out << ", tag=" << r.tag << "}"; - out << ", queue=" << r.queue->getName() << "}"; - return out; -} - - -}} diff --git a/cpp/src/qpid/broker/DeliveryRecord.h b/cpp/src/qpid/broker/DeliveryRecord.h deleted file mode 100644 index d388ba94be..0000000000 --- a/cpp/src/qpid/broker/DeliveryRecord.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef QPID_BROKER_DELIVERYRECORD_H -#define QPID_BROKER_DELIVERYRECORD_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <algorithm> -#include <deque> -#include <vector> -#include <ostream> -#include "qpid/framing/SequenceSet.h" -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/broker/DeliveryId.h" -#include "qpid/broker/Message.h" - -namespace qpid { -namespace broker { - -class TransactionContext; -class SemanticState; -struct AckRange; - -/** - * Record of a delivery for which an ack is outstanding. - */ -class DeliveryRecord -{ - QueuedMessage msg; - mutable boost::shared_ptr<Queue> queue; - std::string tag; - DeliveryId id; - bool acquired : 1; - bool acceptExpected : 1; - bool cancelled : 1; - bool completed : 1; - bool ended : 1; - bool windowing : 1; - - /** - * Record required credit on construction as the pointer to the - * message may be reset once we no longer need to deliver it - * (e.g. when it is accepted), but we will still need to be able - * to reallocate credit when it is completed (which could happen - * after that). - */ - uint32_t credit; - - public: - QPID_BROKER_EXTERN DeliveryRecord(const QueuedMessage& msg, - const boost::shared_ptr<Queue>& queue, - const std::string& tag, - bool acquired, - bool accepted, - bool windowing, - uint32_t credit=0 // Only used if msg is empty. - ); - - bool coveredBy(const framing::SequenceSet* const range) const { return range->contains(id); } - - void dequeue(TransactionContext* ctxt = 0) const; - void requeue() const; - void release(bool setRedelivered); - void reject(); - void cancel(const std::string& tag); - void redeliver(SemanticState* const); - void acquire(DeliveryIds& results); - void complete(); - bool accept(TransactionContext* ctxt); // Returns isRedundant() - bool setEnded(); // Returns isRedundant() - void committed() const; - - bool isAcquired() const { return acquired; } - bool isComplete() const { return completed; } - bool isRedundant() const { return ended && (!windowing || completed); } - bool isCancelled() const { return cancelled; } - bool isAccepted() const { return !acceptExpected; } - bool isEnded() const { return ended; } - bool isWindowing() const { return windowing; } - - uint32_t getCredit() const; - const std::string& getTag() const { return tag; } - - void deliver(framing::FrameHandler& h, DeliveryId deliveryId, uint16_t framesize); - void setId(DeliveryId _id) { id = _id; } - - typedef std::deque<DeliveryRecord> DeliveryRecords; - static AckRange findRange(DeliveryRecords& records, DeliveryId first, DeliveryId last); - const QueuedMessage& getMessage() const { return msg; } - framing::SequenceNumber getId() const { return id; } - boost::shared_ptr<Queue> getQueue() const { return queue; } - - friend std::ostream& operator<<(std::ostream&, const DeliveryRecord&); -}; - -inline bool operator<(const DeliveryRecord& a, const DeliveryRecord& b) { return a.getId() < b.getId(); } -inline bool operator<(const framing::SequenceNumber& a, const DeliveryRecord& b) { return a < b.getId(); } -inline bool operator<(const DeliveryRecord& a, const framing::SequenceNumber& b) { return a.getId() < b; } - -struct AcquireFunctor -{ - DeliveryIds& results; - - AcquireFunctor(DeliveryIds& _results) : results(_results) {} - - void operator()(DeliveryRecord& record) - { - record.acquire(results); - } -}; - -typedef DeliveryRecord::DeliveryRecords DeliveryRecords; - -struct AckRange -{ - DeliveryRecords::iterator start; - DeliveryRecords::iterator end; - AckRange(DeliveryRecords::iterator _start, DeliveryRecords::iterator _end) : start(_start), end(_end) {} -}; - -} -} - - -#endif /*!QPID_BROKER_DELIVERYRECORD_H*/ diff --git a/cpp/src/qpid/broker/DirectExchange.cpp b/cpp/src/qpid/broker/DirectExchange.cpp deleted file mode 100644 index 060f80f60d..0000000000 --- a/cpp/src/qpid/broker/DirectExchange.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/log/Statement.h" -#include "qpid/broker/FedOps.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/DirectExchange.h" -#include <iostream> - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -using qpid::management::Manageable; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace -{ - const std::string qpidExclusiveBinding("qpid.exclusive-binding"); -} - -DirectExchange::DirectExchange(const string& _name, Manageable* _parent, Broker* b) : Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type(typeName); -} - -DirectExchange::DirectExchange(const string& _name, bool _durable, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type(typeName); -} - -bool DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args) -{ - string fedOp(fedOpBind); - string fedTags; - string fedOrigin; - bool exclusiveBinding = false; - if (args) { - fedOp = args->getAsString(qpidFedOp); - fedTags = args->getAsString(qpidFedTags); - fedOrigin = args->getAsString(qpidFedOrigin); - exclusiveBinding = args->get(qpidExclusiveBinding); // only direct exchanges take exclusive bindings - } - - bool propagate = false; - - if (args == 0 || fedOp.empty() || fedOp == fedOpBind) { - Mutex::ScopedLock l(lock); - Binding::shared_ptr b(new Binding(routingKey, queue, this, FieldTable(), fedOrigin)); - BoundKey& bk = bindings[routingKey]; - if (exclusiveBinding) bk.queues.clear(); - - QPID_LOG(debug, "Bind key [" << routingKey << "] to queue " << queue->getName() - << " (origin=" << fedOrigin << ")"); - - if (bk.queues.add_unless(b, MatchQueue(queue))) { - b->startManagement(); - propagate = bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - // queue already present - still need to track fedOrigin - bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } else if (fedOp == fedOpUnbind) { - Mutex::ScopedLock l(lock); - BoundKey& bk = bindings[routingKey]; - - QPID_LOG(debug, "Bind - fedOpUnbind key [" << routingKey << "] queue " << queue->getName() - << " (origin=" << fedOrigin << ")" << " (count=" << bk.fedBinding.count() << ")"); - - propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin); - if (bk.fedBinding.countFedBindings(queue->getName()) == 0) - unbind(queue, routingKey, args); - - } else if (fedOp == fedOpReorigin) { - /** gather up all the keys that need rebinding in a local vector - * while holding the lock. Then propagate once the lock is - * released - */ - std::vector<std::string> keys2prop; - { - Mutex::ScopedLock l(lock); - for (Bindings::iterator iter = bindings.begin(); - iter != bindings.end(); iter++) { - const BoundKey& bk = iter->second; - if (bk.fedBinding.hasLocal()) { - keys2prop.push_back(iter->first); - } - } - } /* lock dropped */ - for (std::vector<std::string>::const_iterator key = keys2prop.begin(); - key != keys2prop.end(); key++) { - propagateFedOp( *key, string(), fedOpBind, string()); - } - } - - routeIVE(); - if (propagate) - propagateFedOp(routingKey, fedTags, fedOp, fedOrigin); - return true; -} - -bool DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args) -{ - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - - QPID_LOG(debug, "Unbinding key [" << routingKey << "] from queue " << queue->getName() - << " on exchange " << getName() << " origin=" << fedOrigin << ")" ); - { - Mutex::ScopedLock l(lock); - BoundKey& bk = bindings[routingKey]; - if (bk.queues.remove_if(MatchQueue(queue))) { - propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - } else { - return false; - } - } - - // If I delete my local binding, propagate this unbind to any upstream brokers - if (propagate) - propagateFedOp(routingKey, string(), fedOpUnbind, string()); - return true; -} - -void DirectExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/) -{ - PreRoute pr(msg, this); - ConstBindingList b; - { - Mutex::ScopedLock l(lock); - b = bindings[routingKey].queues.snapshot(); - } - doRoute(msg, b); -} - - -bool DirectExchange::isBound(Queue::shared_ptr queue, const string* const routingKey, const FieldTable* const) -{ - Mutex::ScopedLock l(lock); - if (routingKey) { - Bindings::iterator i = bindings.find(*routingKey); - - if (i == bindings.end()) - return false; - if (!queue) - return true; - - Queues::ConstPtr p = i->second.queues.snapshot(); - return p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end(); - } else if (!queue) { - //if no queue or routing key is specified, just report whether any bindings exist - return bindings.size() > 0; - } else { - for (Bindings::iterator i = bindings.begin(); i != bindings.end(); i++) { - Queues::ConstPtr p = i->second.queues.snapshot(); - if (p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end()) return true; - } - return false; - } - - return false; -} - -DirectExchange::~DirectExchange() {} - -const std::string DirectExchange::typeName("direct"); diff --git a/cpp/src/qpid/broker/DirectExchange.h b/cpp/src/qpid/broker/DirectExchange.h deleted file mode 100644 index a6f9cf91af..0000000000 --- a/cpp/src/qpid/broker/DirectExchange.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DirectExchange_ -#define _DirectExchange_ - -#include <map> -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace broker { -class DirectExchange : public virtual Exchange { - typedef qpid::sys::CopyOnWriteArray<Binding::shared_ptr> Queues; - struct BoundKey { - Queues queues; - FedBinding fedBinding; - }; - typedef std::map<std::string, BoundKey> Bindings; - Bindings bindings; - qpid::sys::Mutex lock; - -public: - static const std::string typeName; - - QPID_BROKER_EXTERN DirectExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN DirectExchange(const std::string& _name, - bool _durable, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(boost::shared_ptr<Queue> queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - virtual bool unbind(boost::shared_ptr<Queue> queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - QPID_BROKER_EXTERN virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - QPID_BROKER_EXTERN virtual bool isBound(boost::shared_ptr<Queue> queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~DirectExchange(); - - virtual bool supportsDynamicBinding() { return true; } -}; - -}} - -#endif diff --git a/cpp/src/qpid/broker/DtxAck.cpp b/cpp/src/qpid/broker/DtxAck.cpp deleted file mode 100644 index bca3f90bbe..0000000000 --- a/cpp/src/qpid/broker/DtxAck.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxAck.h" -#include "qpid/log/Statement.h" - -using std::bind1st; -using std::bind2nd; -using std::mem_fun_ref; -using namespace qpid::broker; - -DtxAck::DtxAck(const qpid::framing::SequenceSet& acked, DeliveryRecords& unacked) -{ - remove_copy_if(unacked.begin(), unacked.end(), inserter(pending, pending.end()), - not1(bind2nd(mem_fun_ref(&DeliveryRecord::coveredBy), &acked))); -} - -bool DtxAck::prepare(TransactionContext* ctxt) throw() -{ - try{ - //record dequeue in the store - for (DeliveryRecords::iterator i = pending.begin(); i != pending.end(); i++) { - i->dequeue(ctxt); - } - return true; - }catch(...){ - QPID_LOG(error, "Failed to prepare"); - return false; - } -} - -void DtxAck::commit() throw() -{ - try { - for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::committed)); - pending.clear(); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to commit (unknown error)"); - } - -} - -void DtxAck::rollback() throw() -{ - try { - for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::requeue)); - pending.clear(); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to complete rollback: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to complete rollback (unknown error)"); - } - -} diff --git a/cpp/src/qpid/broker/DtxAck.h b/cpp/src/qpid/broker/DtxAck.h deleted file mode 100644 index 166147e58d..0000000000 --- a/cpp/src/qpid/broker/DtxAck.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxAck_ -#define _DtxAck_ - -#include <algorithm> -#include <functional> -#include <list> -#include "qpid/framing/SequenceSet.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/TxOp.h" - -namespace qpid { - namespace broker { - class DtxAck : public TxOp{ - DeliveryRecords pending; - - public: - DtxAck(const framing::SequenceSet& acked, DeliveryRecords& unacked); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~DtxAck(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/DtxBuffer.cpp b/cpp/src/qpid/broker/DtxBuffer.cpp deleted file mode 100644 index f1b8169cf7..0000000000 --- a/cpp/src/qpid/broker/DtxBuffer.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxBuffer.h" - -using namespace qpid::broker; -using qpid::sys::Mutex; - -DtxBuffer::DtxBuffer(const std::string& _xid) - : xid(_xid), ended(false), suspended(false), failed(false), expired(false) {} - -DtxBuffer::~DtxBuffer() {} - -void DtxBuffer::markEnded() -{ - Mutex::ScopedLock locker(lock); - ended = true; -} - -bool DtxBuffer::isEnded() -{ - Mutex::ScopedLock locker(lock); - return ended; -} - -void DtxBuffer::setSuspended(bool isSuspended) -{ - suspended = isSuspended; -} - -bool DtxBuffer::isSuspended() -{ - return suspended; -} - -void DtxBuffer::fail() -{ - Mutex::ScopedLock locker(lock); - rollback(); - failed = true; - ended = true; -} - -bool DtxBuffer::isRollbackOnly() -{ - Mutex::ScopedLock locker(lock); - return failed; -} - -const std::string& DtxBuffer::getXid() -{ - return xid; -} - -void DtxBuffer::timedout() -{ - Mutex::ScopedLock locker(lock); - expired = true; - fail(); -} - -bool DtxBuffer::isExpired() -{ - Mutex::ScopedLock locker(lock); - return expired; -} diff --git a/cpp/src/qpid/broker/DtxBuffer.h b/cpp/src/qpid/broker/DtxBuffer.h deleted file mode 100644 index 1511cb032f..0000000000 --- a/cpp/src/qpid/broker/DtxBuffer.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxBuffer_ -#define _DtxBuffer_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/TxBuffer.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { - namespace broker { - class DtxBuffer : public TxBuffer{ - sys::Mutex lock; - const std::string xid; - bool ended; - bool suspended; - bool failed; - bool expired; - - public: - typedef boost::shared_ptr<DtxBuffer> shared_ptr; - - QPID_BROKER_EXTERN DtxBuffer(const std::string& xid = ""); - QPID_BROKER_EXTERN ~DtxBuffer(); - QPID_BROKER_EXTERN void markEnded(); - bool isEnded(); - void setSuspended(bool suspended); - bool isSuspended(); - void fail(); - bool isRollbackOnly(); - void timedout(); - bool isExpired(); - const std::string& getXid(); - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/DtxManager.cpp b/cpp/src/qpid/broker/DtxManager.cpp deleted file mode 100644 index 3caa41c3f4..0000000000 --- a/cpp/src/qpid/broker/DtxManager.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Timer.h" -#include "qpid/ptr_map.h" - -#include <boost/format.hpp> -#include <iostream> - -using boost::intrusive_ptr; -using qpid::sys::Mutex; -using qpid::ptr_map_ptr; -using namespace qpid::broker; -using namespace qpid::framing; - -DtxManager::DtxManager(qpid::sys::Timer& t) : store(0), timer(t) {} - -DtxManager::~DtxManager() {} - -void DtxManager::start(const std::string& xid, DtxBuffer::shared_ptr ops) -{ - createWork(xid)->add(ops); -} - -void DtxManager::join(const std::string& xid, DtxBuffer::shared_ptr ops) -{ - getWork(xid)->add(ops); -} - -void DtxManager::recover(const std::string& xid, std::auto_ptr<TPCTransactionContext> txn, DtxBuffer::shared_ptr ops) -{ - createWork(xid)->recover(txn, ops); -} - -bool DtxManager::prepare(const std::string& xid) -{ - QPID_LOG(debug, "preparing: " << xid); - try { - return getWork(xid)->prepare(); - } catch (DtxTimeoutException& e) { - remove(xid); - throw e; - } -} - -bool DtxManager::commit(const std::string& xid, bool onePhase) -{ - QPID_LOG(debug, "committing: " << xid); - try { - bool result = getWork(xid)->commit(onePhase); - remove(xid); - return result; - } catch (DtxTimeoutException& e) { - remove(xid); - throw e; - } -} - -void DtxManager::rollback(const std::string& xid) -{ - QPID_LOG(debug, "rolling back: " << xid); - try { - getWork(xid)->rollback(); - remove(xid); - } catch (DtxTimeoutException& e) { - remove(xid); - throw e; - } -} - -DtxWorkRecord* DtxManager::getWork(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i == work.end()) { - throw NotFoundException(QPID_MSG("Unrecognised xid " << xid)); - } - return ptr_map_ptr(i); -} - -void DtxManager::remove(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i == work.end()) { - throw NotFoundException(QPID_MSG("Unrecognised xid " << xid)); - } else { - work.erase(i); - } -} - -DtxWorkRecord* DtxManager::createWork(std::string xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i != work.end()) { - throw NotAllowedException(QPID_MSG("Xid " << xid << " is already known (use 'join' to add work to an existing xid)")); - } else { - return ptr_map_ptr(work.insert(xid, new DtxWorkRecord(xid, store)).first); - } -} - -void DtxManager::setTimeout(const std::string& xid, uint32_t secs) -{ - DtxWorkRecord* record = getWork(xid); - intrusive_ptr<DtxTimeout> timeout = record->getTimeout(); - if (timeout.get()) { - if (timeout->timeout == secs) return;//no need to do anything further if timeout hasn't changed - timeout->cancel(); - } - timeout = intrusive_ptr<DtxTimeout>(new DtxTimeout(secs, *this, xid)); - record->setTimeout(timeout); - timer.add(timeout); -} - -uint32_t DtxManager::getTimeout(const std::string& xid) -{ - intrusive_ptr<DtxTimeout> timeout = getWork(xid)->getTimeout(); - return !timeout ? 0 : timeout->timeout; -} - -void DtxManager::timedout(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i == work.end()) { - QPID_LOG(warning, "Transaction timeout failed: no record for xid"); - } else { - ptr_map_ptr(i)->timedout(); - //TODO: do we want to have a timed task to cleanup, or can we rely on an explicit completion? - //timer.add(intrusive_ptr<TimerTask>(new DtxCleanup(60*30/*30 mins*/, *this, xid))); - } -} - -DtxManager::DtxCleanup::DtxCleanup(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid) - : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxCleanup"), mgr(_mgr), xid(_xid) {} - -void DtxManager::DtxCleanup::fire() -{ - try { - mgr.remove(xid); - } catch (ConnectionException& /*e*/) { - //assume it was explicitly cleaned up after a call to prepare, commit or rollback - } -} - -void DtxManager::setStore (TransactionalStore* _store) -{ - store = _store; -} diff --git a/cpp/src/qpid/broker/DtxManager.h b/cpp/src/qpid/broker/DtxManager.h deleted file mode 100644 index 680b62eeb2..0000000000 --- a/cpp/src/qpid/broker/DtxManager.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxManager_ -#define _DtxManager_ - -#include <boost/ptr_container/ptr_map.hpp> -#include "qpid/broker/DtxBuffer.h" -#include "qpid/broker/DtxWorkRecord.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Timer.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace broker { - -class DtxManager{ - typedef boost::ptr_map<std::string, DtxWorkRecord> WorkMap; - - struct DtxCleanup : public sys::TimerTask - { - DtxManager& mgr; - const std::string& xid; - - DtxCleanup(uint32_t timeout, DtxManager& mgr, const std::string& xid); - void fire(); - }; - - WorkMap work; - TransactionalStore* store; - qpid::sys::Mutex lock; - qpid::sys::Timer& timer; - - void remove(const std::string& xid); - DtxWorkRecord* getWork(const std::string& xid); - DtxWorkRecord* createWork(std::string xid); - -public: - DtxManager(qpid::sys::Timer&); - ~DtxManager(); - void start(const std::string& xid, DtxBuffer::shared_ptr work); - void join(const std::string& xid, DtxBuffer::shared_ptr work); - void recover(const std::string& xid, std::auto_ptr<TPCTransactionContext> txn, DtxBuffer::shared_ptr work); - bool prepare(const std::string& xid); - bool commit(const std::string& xid, bool onePhase); - void rollback(const std::string& xid); - void setTimeout(const std::string& xid, uint32_t secs); - uint32_t getTimeout(const std::string& xid); - void timedout(const std::string& xid); - void setStore(TransactionalStore* store); -}; - -} -} - -#endif diff --git a/cpp/src/qpid/broker/DtxTimeout.cpp b/cpp/src/qpid/broker/DtxTimeout.cpp deleted file mode 100644 index c4c52ec40a..0000000000 --- a/cpp/src/qpid/broker/DtxTimeout.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxTimeout.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/sys/Time.h" - -using namespace qpid::broker; - -DtxTimeout::DtxTimeout(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid) - : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxTimeout"), timeout(_timeout), mgr(_mgr), xid(_xid) -{ -} - -void DtxTimeout::fire() -{ - mgr.timedout(xid); -} diff --git a/cpp/src/qpid/broker/DtxTimeout.h b/cpp/src/qpid/broker/DtxTimeout.h deleted file mode 100644 index 680a210e4f..0000000000 --- a/cpp/src/qpid/broker/DtxTimeout.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxTimeout_ -#define _DtxTimeout_ - -#include "qpid/Exception.h" -#include "qpid/sys/Timer.h" - -namespace qpid { -namespace broker { - -class DtxManager; - -struct DtxTimeoutException : public Exception {}; - -struct DtxTimeout : public sys::TimerTask -{ - const uint32_t timeout; - DtxManager& mgr; - const std::string xid; - - DtxTimeout(uint32_t timeout, DtxManager& mgr, const std::string& xid); - void fire(); -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/DtxWorkRecord.cpp b/cpp/src/qpid/broker/DtxWorkRecord.cpp deleted file mode 100644 index 9f33e698db..0000000000 --- a/cpp/src/qpid/broker/DtxWorkRecord.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxWorkRecord.h" -#include "qpid/framing/reply_exceptions.h" -#include <boost/format.hpp> -#include <boost/mem_fn.hpp> -using boost::mem_fn; -using qpid::sys::Mutex; - -using namespace qpid::broker; -using namespace qpid::framing; - -DtxWorkRecord::DtxWorkRecord(const std::string& _xid, TransactionalStore* const _store) : - xid(_xid), store(_store), completed(false), rolledback(false), prepared(false), expired(false) {} - -DtxWorkRecord::~DtxWorkRecord() -{ - if (timeout.get()) { - timeout->cancel(); - } -} - -bool DtxWorkRecord::prepare() -{ - Mutex::ScopedLock locker(lock); - if (check()) { - txn = store->begin(xid); - if (prepare(txn.get())) { - store->prepare(*txn); - prepared = true; - } else { - abort(); - //TODO: this should probably be flagged as internal error - } - } else { - //some part of the work has been marked rollback only - abort(); - } - return prepared; -} - -bool DtxWorkRecord::prepare(TransactionContext* _txn) -{ - bool succeeded(true); - for (Work::iterator i = work.begin(); succeeded && i != work.end(); i++) { - succeeded = (*i)->prepare(_txn); - } - return succeeded; -} - -bool DtxWorkRecord::commit(bool onePhase) -{ - Mutex::ScopedLock locker(lock); - if (check()) { - if (prepared) { - //already prepared i.e. 2pc - if (onePhase) { - throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " has been prepared, one-phase option not valid!")); - } - - store->commit(*txn); - txn.reset(); - - std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::commit)); - return true; - } else { - //1pc commit optimisation, don't need a 2pc transaction context: - if (!onePhase) { - throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " has not been prepared, one-phase option required!")); - } - std::auto_ptr<TransactionContext> localtxn = store->begin(); - if (prepare(localtxn.get())) { - store->commit(*localtxn); - std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::commit)); - return true; - } else { - store->abort(*localtxn); - abort(); - //TODO: this should probably be flagged as internal error - return false; - } - } - } else { - //some part of the work has been marked rollback only - abort(); - return false; - } -} - -void DtxWorkRecord::rollback() -{ - Mutex::ScopedLock locker(lock); - check(); - abort(); -} - -void DtxWorkRecord::add(DtxBuffer::shared_ptr ops) -{ - Mutex::ScopedLock locker(lock); - if (expired) { - throw DtxTimeoutException(); - } - if (completed) { - throw CommandInvalidException(QPID_MSG("Branch with xid " << xid << " has been completed!")); - } - work.push_back(ops); -} - -bool DtxWorkRecord::check() -{ - if (expired) { - throw DtxTimeoutException(); - } - if (!completed) { - //iterate through all DtxBuffers and ensure they are all ended - for (Work::iterator i = work.begin(); i != work.end(); i++) { - if (!(*i)->isEnded()) { - throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " not completed!")); - } else if ((*i)->isRollbackOnly()) { - rolledback = true; - } - } - completed = true; - } - return !rolledback; -} - -void DtxWorkRecord::abort() -{ - if (txn.get()) { - store->abort(*txn); - txn.reset(); - } - std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::rollback)); -} - -void DtxWorkRecord::recover(std::auto_ptr<TPCTransactionContext> _txn, DtxBuffer::shared_ptr ops) -{ - add(ops); - txn = _txn; - ops->markEnded(); - completed = true; - prepared = true; -} - -void DtxWorkRecord::timedout() -{ - Mutex::ScopedLock locker(lock); - expired = true; - rolledback = true; - if (!completed) { - for (Work::iterator i = work.begin(); i != work.end(); i++) { - if (!(*i)->isEnded()) { - (*i)->timedout(); - } - } - } - abort(); -} diff --git a/cpp/src/qpid/broker/DtxWorkRecord.h b/cpp/src/qpid/broker/DtxWorkRecord.h deleted file mode 100644 index aec2d2aed4..0000000000 --- a/cpp/src/qpid/broker/DtxWorkRecord.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxWorkRecord_ -#define _DtxWorkRecord_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/DtxBuffer.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/broker/TransactionalStore.h" - -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Mutex.h" - -#include <algorithm> -#include <functional> -#include <vector> - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * Represents the work done under a particular distributed transaction - * across potentially multiple channels. Identified by a xid. Allows - * that work to be prepared, committed and rolled-back. - */ -class DtxWorkRecord -{ - typedef std::vector<DtxBuffer::shared_ptr> Work; - - const std::string xid; - TransactionalStore* const store; - bool completed; - bool rolledback; - bool prepared; - bool expired; - boost::intrusive_ptr<DtxTimeout> timeout; - Work work; - std::auto_ptr<TPCTransactionContext> txn; - qpid::sys::Mutex lock; - - bool check(); - void abort(); - bool prepare(TransactionContext* txn); -public: - QPID_BROKER_EXTERN DtxWorkRecord(const std::string& xid, - TransactionalStore* const store); - QPID_BROKER_EXTERN ~DtxWorkRecord(); - QPID_BROKER_EXTERN bool prepare(); - QPID_BROKER_EXTERN bool commit(bool onePhase); - QPID_BROKER_EXTERN void rollback(); - QPID_BROKER_EXTERN void add(DtxBuffer::shared_ptr ops); - void recover(std::auto_ptr<TPCTransactionContext> txn, DtxBuffer::shared_ptr ops); - void timedout(); - void setTimeout(boost::intrusive_ptr<DtxTimeout> t) { timeout = t; } - boost::intrusive_ptr<DtxTimeout> getTimeout() { return timeout; } -}; - -} -} - -#endif diff --git a/cpp/src/qpid/broker/Exchange.cpp b/cpp/src/qpid/broker/Exchange.cpp deleted file mode 100644 index 622cc81002..0000000000 --- a/cpp/src/qpid/broker/Exchange.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/FedOps.h" -#include "qpid/broker/Queue.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/sys/ExceptionHolder.h" -#include <stdexcept> - -using namespace qpid::broker; -using namespace qpid::framing; -using qpid::framing::Buffer; -using qpid::framing::FieldTable; -using qpid::sys::Mutex; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace -{ - const std::string qpidMsgSequence("qpid.msg_sequence"); - const std::string qpidSequenceCounter("qpid.sequence_counter"); - const std::string qpidIVE("qpid.ive"); - const std::string QPID_MANAGEMENT("qpid.management"); -} - - -Exchange::PreRoute::PreRoute(Deliverable& msg, Exchange* _p):parent(_p) { - if (parent){ - if (parent->sequence || parent->ive) parent->sequenceLock.lock(); - - if (parent->sequence){ - parent->sequenceNo++; - msg.getMessage().getProperties<MessageProperties>()->getApplicationHeaders().setInt64(qpidMsgSequence,parent->sequenceNo); - } - if (parent->ive) { - parent->lastMsg = &( msg.getMessage()); - } - } -} - -Exchange::PreRoute::~PreRoute(){ - if (parent && (parent->sequence || parent->ive)){ - parent->sequenceLock.unlock(); - } -} - -namespace { -/** Store information about an exception to be thrown later. - * If multiple exceptions are stored, save the first of the "most severe" - * exceptions, SESSION is les sever than CONNECTION etc. - */ -class ExInfo { - public: - enum Type { NONE, SESSION, CONNECTION, OTHER }; - - ExInfo(string exchange) : type(NONE), exchange(exchange) {} - void store(Type type_, const qpid::sys::ExceptionHolder& exception_, const boost::shared_ptr<Queue>& queue) { - QPID_LOG(warning, "Exchange " << exchange << " cannot deliver to queue " - << queue->getName() << ": " << exception_.what()); - if (type < type_) { // Replace less severe exception - type = type_; - exception = exception_; - } - } - - void raise() { - exception.raise(); - } - - private: - Type type; - string exchange; - qpid::sys::ExceptionHolder exception; -}; -} - -void Exchange::doRoute(Deliverable& msg, ConstBindingList b) -{ - int count = 0; - - if (b.get()) { - // Block the content release if the message is transient AND there is more than one binding - if (!msg.getMessage().isPersistent() && b->size() > 1) { - msg.getMessage().blockContentRelease(); - } - - - ExInfo error(getName()); // Save exception to throw at the end. - for(std::vector<Binding::shared_ptr>::const_iterator i = b->begin(); i != b->end(); i++, count++) { - try { - msg.deliverTo((*i)->queue); - if ((*i)->mgmtBinding != 0) - (*i)->mgmtBinding->inc_msgMatched(); - } - catch (const SessionException& e) { - error.store(ExInfo::SESSION, framing::createSessionException(e.code, e.what()),(*i)->queue); - } - catch (const ConnectionException& e) { - error.store(ExInfo::CONNECTION, framing::createConnectionException(e.code, e.what()), (*i)->queue); - } - catch (const std::exception& e) { - error.store(ExInfo::OTHER, qpid::sys::ExceptionHolder(new Exception(e.what())), (*i)->queue); - } - } - error.raise(); - } - - if (mgmtExchange != 0) - { - mgmtExchange->inc_msgReceives (); - mgmtExchange->inc_byteReceives (msg.contentSize ()); - if (count == 0) - { - //QPID_LOG(warning, "Exchange " << getName() << " could not route message; no matching binding found"); - mgmtExchange->inc_msgDrops (); - mgmtExchange->inc_byteDrops (msg.contentSize ()); - } - else - { - mgmtExchange->inc_msgRoutes (count); - mgmtExchange->inc_byteRoutes (count * msg.contentSize ()); - } - } -} - -void Exchange::routeIVE(){ - if (ive && lastMsg.get()){ - DeliverableMessage dmsg(lastMsg); - route(dmsg, lastMsg->getRoutingKey(), lastMsg->getApplicationHeaders()); - } -} - - -Exchange::Exchange (const string& _name, Manageable* parent, Broker* b) : - name(_name), durable(false), persistenceId(0), sequence(false), - sequenceNo(0), ive(false), mgmtExchange(0), broker(b), destroyed(false) -{ - if (parent != 0 && broker != 0) - { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) - { - mgmtExchange = new _qmf::Exchange (agent, this, parent, _name); - mgmtExchange->set_durable(durable); - mgmtExchange->set_autoDelete(false); - agent->addObject(mgmtExchange, 0, durable); - } - } -} - -Exchange::Exchange(const string& _name, bool _durable, const qpid::framing::FieldTable& _args, - Manageable* parent, Broker* b) - : name(_name), durable(_durable), alternateUsers(0), persistenceId(0), - args(_args), sequence(false), sequenceNo(0), ive(false), mgmtExchange(0), broker(b), destroyed(false) -{ - if (parent != 0 && broker != 0) - { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) - { - mgmtExchange = new _qmf::Exchange (agent, this, parent, _name); - mgmtExchange->set_durable(durable); - mgmtExchange->set_autoDelete(false); - mgmtExchange->set_arguments(ManagementAgent::toMap(args)); - agent->addObject(mgmtExchange, 0, durable); - } - } - - sequence = _args.get(qpidMsgSequence); - if (sequence) { - QPID_LOG(debug, "Configured exchange " << _name << " with Msg sequencing"); - args.setInt64(std::string(qpidSequenceCounter), sequenceNo); - } - - ive = _args.get(qpidIVE); - if (ive) { - if (broker && broker->isInCluster()) - throw framing::NotImplementedException("Cannot use Initial Value Exchanges in a cluster"); - QPID_LOG(debug, "Configured exchange " << _name << " with Initial Value"); - } -} - -Exchange::~Exchange () -{ - if (mgmtExchange != 0) - mgmtExchange->resourceDestroy (); -} - -void Exchange::setAlternate(Exchange::shared_ptr _alternate) -{ - alternate = _alternate; - if (mgmtExchange != 0) { - if (alternate.get() != 0) - mgmtExchange->set_altExchange(alternate->GetManagementObject()->getObjectId()); - else - mgmtExchange->clr_altExchange(); - } -} - -void Exchange::setPersistenceId(uint64_t id) const -{ - persistenceId = id; -} - -Exchange::shared_ptr Exchange::decode(ExchangeRegistry& exchanges, Buffer& buffer) -{ - string name; - string type; - string altName; - FieldTable args; - - buffer.getShortString(name); - bool durable(buffer.getOctet()); - buffer.getShortString(type); - buffer.get(args); - // For backwards compatibility on restoring exchanges from before the alt-exchange update, perform check - if (buffer.available()) - buffer.getShortString(altName); - - try { - Exchange::shared_ptr exch = exchanges.declare(name, type, durable, args).first; - exch->sequenceNo = args.getAsInt64(qpidSequenceCounter); - exch->alternateName.assign(altName); - return exch; - } catch (const UnknownExchangeTypeException&) { - QPID_LOG(warning, "Could not create exchange " << name << "; type " << type << " is not recognised"); - return Exchange::shared_ptr(); - } -} - -void Exchange::encode(Buffer& buffer) const -{ - buffer.putShortString(name); - buffer.putOctet(durable); - buffer.putShortString(getType()); - if (args.isSet(qpidSequenceCounter)) - args.setInt64(std::string(qpidSequenceCounter),sequenceNo); - buffer.put(args); - buffer.putShortString(alternate.get() ? alternate->getName() : string("")); -} - -uint32_t Exchange::encodedSize() const -{ - return name.size() + 1/*short string size*/ - + 1 /*durable*/ - + getType().size() + 1/*short string size*/ - + (alternate.get() ? alternate->getName().size() : 0) + 1/*short string size*/ - + args.encodedSize(); -} - -void Exchange::recoveryComplete(ExchangeRegistry& exchanges) -{ - if (!alternateName.empty()) { - try { - Exchange::shared_ptr ae = exchanges.get(alternateName); - setAlternate(ae); - } catch (const NotFoundException&) { - QPID_LOG(warning, "Could not set alternate exchange \"" << alternateName << "\": does not exist."); - } - } -} - -ManagementObject* Exchange::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtExchange; -} - -void Exchange::registerDynamicBridge(DynamicBridge* db) -{ - if (!supportsDynamicBinding()) - throw Exception("Exchange type does not support dynamic binding"); - - { - Mutex::ScopedLock l(bridgeLock); - for (std::vector<DynamicBridge*>::iterator iter = bridgeVector.begin(); - iter != bridgeVector.end(); iter++) - (*iter)->sendReorigin(); - - bridgeVector.push_back(db); - } - - FieldTable args; - args.setString(qpidFedOp, fedOpReorigin); - bind(Queue::shared_ptr(), string(), &args); -} - -void Exchange::removeDynamicBridge(DynamicBridge* db) -{ - Mutex::ScopedLock l(bridgeLock); - for (std::vector<DynamicBridge*>::iterator iter = bridgeVector.begin(); - iter != bridgeVector.end(); iter++) - if (*iter == db) { - bridgeVector.erase(iter); - break; - } -} - -void Exchange::handleHelloRequest() -{ -} - -void Exchange::propagateFedOp(const string& routingKey, const string& tags, const string& op, const string& origin, qpid::framing::FieldTable* extra_args) -{ - Mutex::ScopedLock l(bridgeLock); - string myOp(op.empty() ? fedOpBind : op); - - for (std::vector<DynamicBridge*>::iterator iter = bridgeVector.begin(); - iter != bridgeVector.end(); iter++) - (*iter)->propagateBinding(routingKey, tags, op, origin, extra_args); -} - -Exchange::Binding::Binding(const string& _key, Queue::shared_ptr _queue, Exchange* _parent, - FieldTable _args, const string& _origin) - : parent(_parent), queue(_queue), key(_key), args(_args), origin(_origin), mgmtBinding(0) -{ -} - -Exchange::Binding::~Binding () -{ - if (mgmtBinding != 0) { - ManagementObject* mo = queue->GetManagementObject(); - if (mo != 0) - static_cast<_qmf::Queue*>(mo)->dec_bindingCount(); - mgmtBinding->resourceDestroy (); - } -} - -void Exchange::Binding::startManagement() -{ - if (parent != 0) - { - Broker* broker = parent->getBroker(); - if (broker != 0) { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) { - ManagementObject* mo = queue->GetManagementObject(); - if (mo != 0) { - management::ObjectId queueId = mo->getObjectId(); - - mgmtBinding = new _qmf::Binding - (agent, this, (Manageable*) parent, queueId, key, ManagementAgent::toMap(args)); - if (!origin.empty()) - mgmtBinding->set_origin(origin); - agent->addObject(mgmtBinding); - static_cast<_qmf::Queue*>(mo)->inc_bindingCount(); - } - } - } - } -} - -ManagementObject* Exchange::Binding::GetManagementObject () const -{ - return (ManagementObject*) mgmtBinding; -} - -Exchange::MatchQueue::MatchQueue(Queue::shared_ptr q) : queue(q) {} - -bool Exchange::MatchQueue::operator()(Exchange::Binding::shared_ptr b) -{ - return b->queue == queue; -} - -void Exchange::setProperties(const boost::intrusive_ptr<Message>& msg) { - msg->getProperties<DeliveryProperties>()->setExchange(getName()); -} - -bool Exchange::routeWithAlternate(Deliverable& msg) -{ - route(msg, msg.getMessage().getRoutingKey(), msg.getMessage().getApplicationHeaders()); - if (!msg.delivered && alternate) { - alternate->route(msg, msg.getMessage().getRoutingKey(), msg.getMessage().getApplicationHeaders()); - } - return msg.delivered; -} diff --git a/cpp/src/qpid/broker/Exchange.h b/cpp/src/qpid/broker/Exchange.h deleted file mode 100644 index b12af9a1dd..0000000000 --- a/cpp/src/qpid/broker/Exchange.h +++ /dev/null @@ -1,248 +0,0 @@ -#ifndef _broker_Exchange_h -#define _broker_Exchange_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/PersistableExchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Mutex.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Exchange.h" -#include "qmf/org/apache/qpid/broker/Binding.h" - -namespace qpid { -namespace broker { - -class Broker; -class ExchangeRegistry; - -class QPID_BROKER_CLASS_EXTERN Exchange : public PersistableExchange, public management::Manageable { -public: - struct Binding : public management::Manageable { - typedef boost::shared_ptr<Binding> shared_ptr; - typedef std::vector<Binding::shared_ptr> vector; - - Exchange* parent; - boost::shared_ptr<Queue> queue; - const std::string key; - const framing::FieldTable args; - std::string origin; - qmf::org::apache::qpid::broker::Binding* mgmtBinding; - - Binding(const std::string& key, boost::shared_ptr<Queue> queue, Exchange* parent = 0, - framing::FieldTable args = framing::FieldTable(), const std::string& origin = std::string()); - ~Binding(); - void startManagement(); - management::ManagementObject* GetManagementObject() const; - }; - -private: - const std::string name; - const bool durable; - std::string alternateName; - boost::shared_ptr<Exchange> alternate; - uint32_t alternateUsers; - mutable uint64_t persistenceId; - -protected: - mutable qpid::framing::FieldTable args; - bool sequence; - mutable qpid::sys::Mutex sequenceLock; - int64_t sequenceNo; - bool ive; - boost::intrusive_ptr<Message> lastMsg; - - class PreRoute{ - public: - PreRoute(Deliverable& msg, Exchange* _p); - ~PreRoute(); - private: - Exchange* parent; - }; - - typedef boost::shared_ptr<const std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> > > ConstBindingList; - typedef boost::shared_ptr< std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> > > BindingList; - void doRoute(Deliverable& msg, ConstBindingList b); - void routeIVE(); - - - struct MatchQueue { - const boost::shared_ptr<Queue> queue; - MatchQueue(boost::shared_ptr<Queue> q); - bool operator()(Exchange::Binding::shared_ptr b); - }; - - /** A FedBinding keeps track of information that Federation needs - to know when to propagate changes. - - Dynamic federation needs to know which exchanges have at least - one local binding. The bindings on these exchanges need to be - propagated. - - Federated binds and unbinds need to know which federation - origins are associated with the bindings for each queue. When - origins are added or deleted, the corresponding bindings need - to be propagated. - - fedBindings[queueName] contains the origins associated with - the given queue. - */ - - class FedBinding { - uint32_t localBindings; - - typedef std::set<std::string> originSet; - std::map<std::string, originSet> fedBindings; - - public: - FedBinding() : localBindings(0) {} - bool hasLocal() const { return localBindings != 0; } - - /** Returns true if propagation is needed. */ - bool addOrigin(const std::string& queueName, const std::string& origin) { - if (origin.empty()) { - localBindings++; - return localBindings == 1; - } - fedBindings[queueName].insert(origin); - return true; - } - - /** Returns true if propagation is needed. */ - bool delOrigin(const std::string& queueName, const std::string& origin){ - if (origin.empty()) { // no remote == local binding - if (localBindings > 0) - localBindings--; - return localBindings == 0; - } - size_t match = fedBindings[queueName].erase(origin); - if (fedBindings[queueName].empty()) - fedBindings.erase(queueName); - return match != 0; - } - - uint32_t count() { - return localBindings + fedBindings.size(); - } - - uint32_t countFedBindings(const std::string& queueName) { - // don't use '[]' - it may increase size of fedBindings! - std::map<std::string, originSet>::iterator i; - if ((i = fedBindings.find(queueName)) != fedBindings.end()) - return i->second.size(); - return 0; - } - }; - - qmf::org::apache::qpid::broker::Exchange* mgmtExchange; - -public: - typedef boost::shared_ptr<Exchange> shared_ptr; - - QPID_BROKER_EXTERN explicit Exchange(const std::string& name, management::Manageable* parent = 0, - Broker* broker = 0); - QPID_BROKER_EXTERN Exchange(const std::string& _name, bool _durable, const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_INLINE_EXTERN virtual ~Exchange(); - - const std::string& getName() const { return name; } - bool isDurable() { return durable; } - qpid::framing::FieldTable& getArgs() { return args; } - - Exchange::shared_ptr getAlternate() { return alternate; } - void setAlternate(Exchange::shared_ptr _alternate); - void incAlternateUsers() { alternateUsers++; } - void decAlternateUsers() { alternateUsers--; } - bool inUseAsAlternate() { return alternateUsers > 0; } - - virtual std::string getType() const = 0; - - /** - * bind() is used for two distinct purposes: - * - * 1. To create a binding, in the conventional sense - * - * 2. As a vehicle for any FedOp, currently including federated - * binding, federated unbinding, federated reorigin. - * - */ - - virtual bool bind(boost::shared_ptr<Queue> queue, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0; - virtual bool unbind(boost::shared_ptr<Queue> queue, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0; - virtual bool isBound(boost::shared_ptr<Queue> queue, const std::string* const routingKey, const qpid::framing::FieldTable* const args) = 0; - QPID_BROKER_EXTERN virtual void setProperties(const boost::intrusive_ptr<Message>&); - virtual void route(Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0; - - //PersistableExchange: - QPID_BROKER_EXTERN void setPersistenceId(uint64_t id) const; - uint64_t getPersistenceId() const { return persistenceId; } - QPID_BROKER_EXTERN uint32_t encodedSize() const; - QPID_BROKER_EXTERN virtual void encode(framing::Buffer& buffer) const; - - static QPID_BROKER_EXTERN Exchange::shared_ptr decode(ExchangeRegistry& exchanges, framing::Buffer& buffer); - - // Manageable entry points - QPID_BROKER_EXTERN management::ManagementObject* GetManagementObject(void) const; - - // Federation hooks - class DynamicBridge { - public: - virtual ~DynamicBridge() {} - virtual void propagateBinding(const std::string& key, const std::string& tagList, const std::string& op, const std::string& origin, qpid::framing::FieldTable* extra_args=0) = 0; - virtual void sendReorigin() = 0; - virtual bool containsLocalTag(const std::string& tagList) const = 0; - virtual const std::string& getLocalTag() const = 0; - }; - - void registerDynamicBridge(DynamicBridge* db); - void removeDynamicBridge(DynamicBridge* db); - virtual bool supportsDynamicBinding() { return false; } - Broker* getBroker() const { return broker; } - /** - * Notify exchange that recovery has completed. - */ - void recoveryComplete(ExchangeRegistry& exchanges); - - bool routeWithAlternate(Deliverable& message); - - void destroy() { destroyed = true; } - bool isDestroyed() const { return destroyed; } - -protected: - qpid::sys::Mutex bridgeLock; - std::vector<DynamicBridge*> bridgeVector; - Broker* broker; - bool destroyed; - - QPID_BROKER_EXTERN virtual void handleHelloRequest(); - void propagateFedOp(const std::string& routingKey, const std::string& tags, - const std::string& op, const std::string& origin, - qpid::framing::FieldTable* extra_args=0); -}; - -}} - -#endif /*!_broker_Exchange.cpp_h*/ diff --git a/cpp/src/qpid/broker/ExchangeRegistry.cpp b/cpp/src/qpid/broker/ExchangeRegistry.cpp deleted file mode 100644 index 1c8d26c4f7..0000000000 --- a/cpp/src/qpid/broker/ExchangeRegistry.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/management/ManagementDirectExchange.h" -#include "qpid/management/ManagementTopicExchange.h" -#include "qpid/framing/reply_exceptions.h" - -using namespace qpid::broker; -using namespace qpid::sys; -using std::pair; -using std::string; -using qpid::framing::FieldTable; - -pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, const string& type){ - - return declare(name, type, false, FieldTable()); -} - -pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, const string& type, - bool durable, const FieldTable& args){ - RWlock::ScopedWlock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i == exchanges.end()) { - Exchange::shared_ptr exchange; - - if (type == TopicExchange::typeName){ - exchange = Exchange::shared_ptr(new TopicExchange(name, durable, args, parent, broker)); - }else if(type == DirectExchange::typeName){ - exchange = Exchange::shared_ptr(new DirectExchange(name, durable, args, parent, broker)); - }else if(type == FanOutExchange::typeName){ - exchange = Exchange::shared_ptr(new FanOutExchange(name, durable, args, parent, broker)); - }else if (type == HeadersExchange::typeName) { - exchange = Exchange::shared_ptr(new HeadersExchange(name, durable, args, parent, broker)); - }else if (type == ManagementDirectExchange::typeName) { - exchange = Exchange::shared_ptr(new ManagementDirectExchange(name, durable, args, parent, broker)); - }else if (type == ManagementTopicExchange::typeName) { - exchange = Exchange::shared_ptr(new ManagementTopicExchange(name, durable, args, parent, broker)); - }else{ - FunctionMap::iterator i = factory.find(type); - if (i == factory.end()) { - throw UnknownExchangeTypeException(); - } else { - exchange = i->second(name, durable, args, parent, broker); - } - } - exchanges[name] = exchange; - return std::pair<Exchange::shared_ptr, bool>(exchange, true); - } else { - return std::pair<Exchange::shared_ptr, bool>(i->second, false); - } -} - -void ExchangeRegistry::destroy(const string& name){ - if (name.empty() || - (name.find("amq.") == 0 && - (name == "amq.direct" || name == "amq.fanout" || name == "amq.topic" || name == "amq.match")) || - name == "qpid.management") - throw framing::NotAllowedException(QPID_MSG("Cannot delete default exchange: '" << name << "'")); - RWlock::ScopedWlock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i != exchanges.end()) { - i->second->destroy(); - exchanges.erase(i); - } -} - -Exchange::shared_ptr ExchangeRegistry::get(const string& name){ - RWlock::ScopedRlock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i == exchanges.end()) - throw framing::NotFoundException(QPID_MSG("Exchange not found: " << name)); - return i->second; -} - -bool ExchangeRegistry::registerExchange(const Exchange::shared_ptr& ex) { - return exchanges.insert(ExchangeMap::value_type(ex->getName(), ex)).second; -} - -void ExchangeRegistry::registerType(const std::string& type, FactoryFunction f) -{ - factory[type] = f; -} - - -namespace -{ -const std::string empty; -} - -Exchange::shared_ptr ExchangeRegistry::getDefault() -{ - return get(empty); -} diff --git a/cpp/src/qpid/broker/ExchangeRegistry.h b/cpp/src/qpid/broker/ExchangeRegistry.h deleted file mode 100644 index 2b75a8f3cf..0000000000 --- a/cpp/src/qpid/broker/ExchangeRegistry.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef _broker_ExchangeRegistry_h -#define _broker_ExchangeRegistry_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Monitor.h" -#include "qpid/management/Manageable.h" - -#include <boost/function.hpp> -#include <boost/bind.hpp> - -#include <algorithm> -#include <map> - -namespace qpid { -namespace broker { - -struct UnknownExchangeTypeException{}; - -class ExchangeRegistry{ - public: - typedef boost::function5<Exchange::shared_ptr, const std::string&, - bool, const qpid::framing::FieldTable&, qpid::management::Manageable*, qpid::broker::Broker*> FactoryFunction; - - ExchangeRegistry (Broker* b = 0) : parent(0), broker(b) {} - QPID_BROKER_EXTERN std::pair<Exchange::shared_ptr, bool> declare - (const std::string& name, const std::string& type); - QPID_BROKER_EXTERN std::pair<Exchange::shared_ptr, bool> declare - (const std::string& name, - const std::string& type, - bool durable, - const qpid::framing::FieldTable& args = framing::FieldTable()); - QPID_BROKER_EXTERN void destroy(const std::string& name); - QPID_BROKER_EXTERN Exchange::shared_ptr get(const std::string& name); - Exchange::shared_ptr getDefault(); - - /** - * Register the manageable parent for declared exchanges - */ - void setParent (management::Manageable* _parent) { parent = _parent; } - - /** Register an exchange instance. - *@return true if registered, false if exchange with same name is already registered. - */ - bool registerExchange(const Exchange::shared_ptr&); - - QPID_BROKER_EXTERN void registerType(const std::string& type, FactoryFunction); - - /** Call f for each exchange in the registry. */ - template <class F> void eachExchange(F f) const { - qpid::sys::RWlock::ScopedRlock l(lock); - for (ExchangeMap::const_iterator i = exchanges.begin(); i != exchanges.end(); ++i) - f(i->second); - } - - private: - typedef std::map<std::string, Exchange::shared_ptr> ExchangeMap; - typedef std::map<std::string, FactoryFunction > FunctionMap; - - ExchangeMap exchanges; - FunctionMap factory; - mutable qpid::sys::RWlock lock; - management::Manageable* parent; - Broker* broker; -}; - -}} // namespace qpid::broker - - -#endif /*!_broker_ExchangeRegistry_h*/ diff --git a/cpp/src/qpid/broker/ExpiryPolicy.cpp b/cpp/src/qpid/broker/ExpiryPolicy.cpp deleted file mode 100644 index 64a12d918a..0000000000 --- a/cpp/src/qpid/broker/ExpiryPolicy.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/broker/Message.h" -#include "qpid/sys/Time.h" - -namespace qpid { -namespace broker { - -ExpiryPolicy::~ExpiryPolicy() {} - -void ExpiryPolicy::willExpire(Message&) {} - -bool ExpiryPolicy::hasExpired(Message& m) { - return m.getExpiration() < sys::AbsTime::now(); -} - -void ExpiryPolicy::forget(Message&) {} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/ExpiryPolicy.h b/cpp/src/qpid/broker/ExpiryPolicy.h deleted file mode 100644 index a723eb0aa8..0000000000 --- a/cpp/src/qpid/broker/ExpiryPolicy.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef QPID_BROKER_EXPIRYPOLICY_H -#define QPID_BROKER_EXPIRYPOLICY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qpid/broker/BrokerImportExport.h" - -namespace qpid { -namespace broker { - -class Message; - -/** - * Default expiry policy. - */ -class QPID_BROKER_CLASS_EXTERN ExpiryPolicy : public RefCounted -{ - public: - QPID_BROKER_EXTERN virtual ~ExpiryPolicy(); - QPID_BROKER_EXTERN virtual void willExpire(Message&); - QPID_BROKER_EXTERN virtual bool hasExpired(Message&); - QPID_BROKER_EXTERN virtual void forget(Message&); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_EXPIRYPOLICY_H*/ diff --git a/cpp/src/qpid/broker/Fairshare.cpp b/cpp/src/qpid/broker/Fairshare.cpp deleted file mode 100644 index 17270ffd8d..0000000000 --- a/cpp/src/qpid/broker/Fairshare.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Fairshare.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/log/Statement.h" -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/assign/list_of.hpp> - -namespace qpid { -namespace broker { - -Fairshare::Fairshare(size_t levels, uint limit) : - PriorityQueue(levels), - limits(levels, limit), priority(levels-1), count(0) {} - - -void Fairshare::setLimit(size_t level, uint limit) -{ - limits[level] = limit; -} - -bool Fairshare::limitReached() -{ - uint l = limits[priority]; - return l && ++count > l; -} - -uint Fairshare::currentLevel() -{ - if (limitReached()) { - return nextLevel(); - } else { - return priority; - } -} - -uint Fairshare::nextLevel() -{ - count = 1; - if (priority) --priority; - else priority = levels-1; - return priority; -} - -bool Fairshare::isNull() -{ - for (int i = 0; i < levels; i++) if (limits[i]) return false; - return true; -} - -bool Fairshare::getState(uint& p, uint& c) const -{ - p = priority; - c = count; - return true; -} - -bool Fairshare::setState(uint p, uint c) -{ - priority = p; - count = c; - return true; -} - -bool Fairshare::findFrontLevel(uint& p, PriorityLevels& messages) -{ - const uint start = p = currentLevel(); - do { - if (!messages[p].empty()) return true; - } while ((p = nextLevel()) != start); - return false; -} - - - -bool Fairshare::getState(const Messages& m, uint& priority, uint& count) -{ - const Fairshare* fairshare = dynamic_cast<const Fairshare*>(&m); - return fairshare && fairshare->getState(priority, count); -} - -bool Fairshare::setState(Messages& m, uint priority, uint count) -{ - Fairshare* fairshare = dynamic_cast<Fairshare*>(&m); - return fairshare && fairshare->setState(priority, count); -} - -int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::vector<std::string>& keys) -{ - qpid::framing::FieldTable::ValuePtr v; - std::vector<std::string>::const_iterator i = keys.begin(); - while (!v && i != keys.end()) { - v = settings.get(*i++); - } - - if (!v) { - return 0; - } else if (v->convertsTo<int>()) { - return v->get<int>(); - } else if (v->convertsTo<std::string>()){ - std::string s = v->get<std::string>(); - try { - return boost::lexical_cast<int>(s); - } catch(const boost::bad_lexical_cast&) { - QPID_LOG(warning, "Ignoring invalid integer value for " << *i << ": " << s); - return 0; - } - } else { - QPID_LOG(warning, "Ignoring invalid integer value for " << *i << ": " << *v); - return 0; - } -} - -int getIntegerSettingForKey(const qpid::framing::FieldTable& settings, const std::string& key) -{ - return getIntegerSetting(settings, boost::assign::list_of<std::string>(key)); -} - -int getSetting(const qpid::framing::FieldTable& settings, const std::vector<std::string>& keys, int minvalue, int maxvalue) -{ - return std::max(minvalue,std::min(getIntegerSetting(settings, keys), maxvalue)); -} - -std::auto_ptr<Fairshare> getFairshareForKey(const qpid::framing::FieldTable& settings, uint levels, const std::string& key) -{ - uint defaultLimit = getIntegerSettingForKey(settings, key); - std::auto_ptr<Fairshare> fairshare(new Fairshare(levels, defaultLimit)); - for (uint i = 0; i < levels; i++) { - std::string levelKey = (boost::format("%1%-%2%") % key % i).str(); - if(settings.isSet(levelKey)) { - fairshare->setLimit(i, getIntegerSettingForKey(settings, levelKey)); - } - } - if (!fairshare->isNull()) { - return fairshare; - } else { - return std::auto_ptr<Fairshare>(); - } -} - -std::auto_ptr<Fairshare> getFairshare(const qpid::framing::FieldTable& settings, - uint levels, - const std::vector<std::string>& keys) -{ - std::auto_ptr<Fairshare> fairshare; - for (std::vector<std::string>::const_iterator i = keys.begin(); i != keys.end() && !fairshare.get(); ++i) { - fairshare = getFairshareForKey(settings, levels, *i); - } - return fairshare; -} - -std::auto_ptr<Messages> Fairshare::create(const qpid::framing::FieldTable& settings) -{ - using boost::assign::list_of; - std::auto_ptr<Messages> result; - size_t levels = getSetting(settings, list_of<std::string>("qpid.priorities")("x-qpid-priorities"), 1, 100); - if (levels) { - std::auto_ptr<Fairshare> fairshare = - getFairshare(settings, levels, list_of<std::string>("qpid.fairshare")("x-qpid-fairshare")); - if (fairshare.get()) result = fairshare; - else result = std::auto_ptr<Messages>(new PriorityQueue(levels)); - } - return result; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/Fairshare.h b/cpp/src/qpid/broker/Fairshare.h deleted file mode 100644 index 1b25721e0c..0000000000 --- a/cpp/src/qpid/broker/Fairshare.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_BROKER_FAIRSHARE_H -#define QPID_BROKER_FAIRSHARE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/PriorityQueue.h" - -namespace qpid { -namespace framing { -class FieldTable; -} -namespace broker { - -/** - * Modifies a basic prioirty queue by limiting the number of messages - * from each priority level that are dispatched before allowing - * dispatch from the next level. - */ -class Fairshare : public PriorityQueue -{ - public: - Fairshare(size_t levels, uint limit); - bool getState(uint& priority, uint& count) const; - bool setState(uint priority, uint count); - void setLimit(size_t level, uint limit); - bool isNull(); - static std::auto_ptr<Messages> create(const qpid::framing::FieldTable& settings); - static bool getState(const Messages&, uint& priority, uint& count); - static bool setState(Messages&, uint priority, uint count); - private: - std::vector<uint> limits; - - uint priority; - uint count; - - uint currentLevel(); - uint nextLevel(); - bool limitReached(); - bool findFrontLevel(uint& p, PriorityLevels&); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_FAIRSHARE_H*/ diff --git a/cpp/src/qpid/broker/FanOutExchange.cpp b/cpp/src/qpid/broker/FanOutExchange.cpp deleted file mode 100644 index 5879fa0892..0000000000 --- a/cpp/src/qpid/broker/FanOutExchange.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/log/Statement.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/FedOps.h" -#include <algorithm> - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -namespace _qmf = qmf::org::apache::qpid::broker; - -FanOutExchange::FanOutExchange(const std::string& _name, Manageable* _parent, Broker* b) : - Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -FanOutExchange::FanOutExchange(const std::string& _name, bool _durable, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -bool FanOutExchange::bind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* args) -{ - string fedOp(args ? args->getAsString(qpidFedOp) : fedOpBind); - string fedTags(args ? args->getAsString(qpidFedTags) : ""); - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - - if (args == 0 || fedOp.empty() || fedOp == fedOpBind) { - Binding::shared_ptr binding (new Binding ("", queue, this, FieldTable(), fedOrigin)); - if (bindings.add_unless(binding, MatchQueue(queue))) { - binding->startManagement(); - propagate = fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - // queue already present - still need to track fedOrigin - fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } else if (fedOp == fedOpUnbind) { - propagate = fedBinding.delOrigin(queue->getName(), fedOrigin); - if (fedBinding.countFedBindings(queue->getName()) == 0) - unbind(queue, "", args); - } else if (fedOp == fedOpReorigin) { - if (fedBinding.hasLocal()) { - propagateFedOp(string(), string(), fedOpBind, string()); - } - } - - routeIVE(); - if (propagate) - propagateFedOp(string(), fedTags, fedOp, fedOrigin); - return true; -} - -bool FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* args) -{ - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - - QPID_LOG(debug, "Unbinding queue " << queue->getName() - << " from exchange " << getName() << " origin=" << fedOrigin << ")" ); - - if (bindings.remove_if(MatchQueue(queue))) { - propagate = fedBinding.delOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - } else { - return false; - } - - if (propagate) - propagateFedOp(string(), string(), fedOpUnbind, string()); - return true; -} - -void FanOutExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* /*args*/) -{ - PreRoute pr(msg, this); - doRoute(msg, bindings.snapshot()); -} - -bool FanOutExchange::isBound(Queue::shared_ptr queue, const string* const, const FieldTable* const) -{ - BindingsArray::ConstPtr ptr = bindings.snapshot(); - return ptr && std::find_if(ptr->begin(), ptr->end(), MatchQueue(queue)) != ptr->end(); -} - - -FanOutExchange::~FanOutExchange() {} - -const std::string FanOutExchange::typeName("fanout"); diff --git a/cpp/src/qpid/broker/FanOutExchange.h b/cpp/src/qpid/broker/FanOutExchange.h deleted file mode 100644 index 1a7d486796..0000000000 --- a/cpp/src/qpid/broker/FanOutExchange.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _FanOutExchange_ -#define _FanOutExchange_ - -#include <map> -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/broker/Queue.h" - -namespace qpid { -namespace broker { - -class FanOutExchange : public virtual Exchange { - typedef qpid::sys::CopyOnWriteArray<Binding::shared_ptr> BindingsArray; - BindingsArray bindings; - FedBinding fedBinding; - public: - static const std::string typeName; - - QPID_BROKER_EXTERN FanOutExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN FanOutExchange(const std::string& _name, - bool _durable, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual bool isBound(Queue::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~FanOutExchange(); - virtual bool supportsDynamicBinding() { return true; } -}; - -} -} - - - -#endif diff --git a/cpp/src/qpid/broker/FedOps.h b/cpp/src/qpid/broker/FedOps.h deleted file mode 100644 index dc4a38e244..0000000000 --- a/cpp/src/qpid/broker/FedOps.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/* - * Strings used to identify federated operations and operands. - */ - -namespace -{ - const std::string qpidFedOp("qpid.fed.op"); // a federation primitive - const std::string qpidFedTags("qpid.fed.tags"); // a unique id for a broker - const std::string qpidFedOrigin("qpid.fed.origin"); // the tag of the broker on which a propagated binding originated - - // Operands for qpidFedOp - each identifies a federation primitive - - const std::string fedOpBind("B"); - const std::string fedOpUnbind("U"); - const std::string fedOpReorigin("R"); - const std::string fedOpHello("H"); -} diff --git a/cpp/src/qpid/broker/HandlerImpl.h b/cpp/src/qpid/broker/HandlerImpl.h deleted file mode 100644 index aae636e818..0000000000 --- a/cpp/src/qpid/broker/HandlerImpl.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _broker_HandlerImpl_h -#define _broker_HandlerImpl_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/broker/SemanticState.h" -#include "qpid/broker/SessionContext.h" -#include "qpid/broker/ConnectionState.h" - -namespace qpid { -namespace broker { - -class Broker; - -/** - * Base template for protocol handler implementations. - * Provides convenience methods for getting common session objects. - */ -class HandlerImpl { - protected: - SemanticState& state; - SessionContext& session; - - HandlerImpl(SemanticState& s) : state(s), session(s.getSession()) {} - - framing::AMQP_ClientProxy& getProxy() { return session.getProxy(); } - ConnectionState& getConnection() { return session.getConnection(); } - Broker& getBroker() { return session.getConnection().getBroker(); } -}; - -}} // namespace qpid::broker - - - -#endif /*!_broker_HandlerImpl_h*/ - - diff --git a/cpp/src/qpid/broker/HeadersExchange.cpp b/cpp/src/qpid/broker/HeadersExchange.cpp deleted file mode 100644 index abcaa5f69d..0000000000 --- a/cpp/src/qpid/broker/HeadersExchange.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/HeadersExchange.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include <algorithm> - - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -namespace _qmf = qmf::org::apache::qpid::broker; - -// TODO aconway 2006-09-20: More efficient matching algorithm. -// The current search algorithm really sucks. -// Fieldtables are heavy, maybe use shared_ptr to do handle-body. - -using namespace qpid::broker; - -namespace { - const std::string x_match("x-match"); - // possible values for x-match - const std::string all("all"); - const std::string any("any"); - const std::string empty; - - // federation related args and values - const std::string qpidFedOp("qpid.fed.op"); - const std::string qpidFedTags("qpid.fed.tags"); - const std::string qpidFedOrigin("qpid.fed.origin"); - - const std::string fedOpBind("B"); - const std::string fedOpUnbind("U"); - const std::string fedOpReorigin("R"); - const std::string fedOpHello("H"); -} - -HeadersExchange::HeadersExchange(const string& _name, Manageable* _parent, Broker* b) : - Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -HeadersExchange::HeadersExchange(const std::string& _name, bool _durable, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -std::string HeadersExchange::getMatch(const FieldTable* args) -{ - if (!args) { - throw InternalErrorException(QPID_MSG("No arguments given.")); - } - FieldTable::ValuePtr what = args->get(x_match); - if (!what) { - return empty; - } - if (!what->convertsTo<std::string>()) { - throw InternalErrorException(QPID_MSG("Invalid x-match binding format to headers exchange. Must be a string [\"all\" or \"any\"]")); - } - return what->get<std::string>(); -} - -bool HeadersExchange::bind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable* args) -{ - string fedOp(fedOpBind); - string fedTags; - string fedOrigin; - if (args) { - fedOp = args->getAsString(qpidFedOp); - fedTags = args->getAsString(qpidFedTags); - fedOrigin = args->getAsString(qpidFedOrigin); - } - - bool propagate = false; - - // The federation args get propagated directly, so we need to identify - // the non federation args in case a federated propagate is needed - FieldTable extra_args; - getNonFedArgs(args, extra_args); - - if (fedOp.empty() || fedOp == fedOpBind) { - // x-match arg MUST be present for a bind call - std::string x_match_value = getMatch(args); - - if (x_match_value != all && x_match_value != any) { - throw InternalErrorException(QPID_MSG("Invalid or missing x-match value binding to headers exchange. Must be a string [\"all\" or \"any\"]")); - } - - { - Mutex::ScopedLock l(lock); - Binding::shared_ptr binding (new Binding (bindingKey, queue, this, *args)); - BoundKey bk(binding); - if (bindings.add_unless(bk, MatchArgs(queue, args))) { - binding->startManagement(); - propagate = bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } // lock dropped - - } else if (fedOp == fedOpUnbind) { - Mutex::ScopedLock l(lock); - - FedUnbindModifier modifier(queue->getName(), fedOrigin); - bindings.modify_if(MatchKey(queue, bindingKey), modifier); - propagate = modifier.shouldPropagate; - if (modifier.shouldUnbind) { - unbind(queue, bindingKey, args); - } - - } else if (fedOp == fedOpReorigin) { - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()) - { - Mutex::ScopedLock l(lock); - for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) - { - if ((*i).fedBinding.hasLocal()) { - propagateFedOp( (*i).binding->key, string(), fedOpBind, string()); - } - } - } - } - routeIVE(); - if (propagate) { - FieldTable * prop_args = (extra_args.count() != 0 ? &extra_args : 0); - propagateFedOp(bindingKey, fedTags, fedOp, fedOrigin, prop_args); - } - - return true; -} - -bool HeadersExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable *args){ - bool propagate = false; - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - { - Mutex::ScopedLock l(lock); - - FedUnbindModifier modifier(queue->getName(), fedOrigin); - MatchKey match_key(queue, bindingKey); - bindings.modify_if(match_key, modifier); - propagate = modifier.shouldPropagate; - if (modifier.shouldUnbind) { - if (bindings.remove_if(match_key)) { - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - } else { - return false; - } - } - } - - if (propagate) { - propagateFedOp(bindingKey, string(), fedOpUnbind, string()); - } - return true; -} - - -void HeadersExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* args) -{ - if (!args) { - //can't match if there were no headers passed in - if (mgmtExchange != 0) { - mgmtExchange->inc_msgReceives(); - mgmtExchange->inc_byteReceives(msg.contentSize()); - mgmtExchange->inc_msgDrops(); - mgmtExchange->inc_byteDrops(msg.contentSize()); - } - return; - } - - PreRoute pr(msg, this); - - BindingList b(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >); - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()) { - for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) { - if (match((*i).binding->args, *args)) { - b->push_back((*i).binding); - } - } - } - doRoute(msg, b); -} - - -bool HeadersExchange::isBound(Queue::shared_ptr queue, const string* const, const FieldTable* const args) -{ - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()){ - for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) { - if ( (!args || equal((*i).binding->args, *args)) && (!queue || (*i).binding->queue == queue)) { - return true; - } - } - } - return false; -} - -void HeadersExchange::getNonFedArgs(const FieldTable* args, FieldTable& nonFedArgs) -{ - if (!args) - { - return; - } - - for (qpid::framing::FieldTable::ValueMap::const_iterator i=args->begin(); i != args->end(); ++i) - { - const string & name(i->first); - if (name == qpidFedOp || - name == qpidFedTags || - name == qpidFedOrigin) - { - continue; - } - nonFedArgs.insert((*i)); - } -} - -HeadersExchange::~HeadersExchange() {} - -const std::string HeadersExchange::typeName("headers"); - -namespace -{ - - bool match_values(const FieldValue& bind, const FieldValue& msg) { - return bind.getType() == 0xf0 || bind == msg; - } - -} - - -bool HeadersExchange::match(const FieldTable& bind, const FieldTable& msg) { - typedef FieldTable::ValueMap Map; - std::string what = getMatch(&bind); - if (what == all) { - for (Map::const_iterator i = bind.begin(); - i != bind.end(); - ++i) - { - if (i->first != x_match) - { - Map::const_iterator j = msg.find(i->first); - if (j == msg.end()) return false; - if (!match_values(*(i->second), *(j->second))) return false; - } - } - return true; - } else if (what == any) { - for (Map::const_iterator i = bind.begin(); - i != bind.end(); - ++i) - { - if (i->first != x_match) - { - Map::const_iterator j = msg.find(i->first); - if (j != msg.end()) { - if (match_values(*(i->second), *(j->second))) return true; - } - } - } - return false; - } else { - return false; - } -} - -bool HeadersExchange::equal(const FieldTable& a, const FieldTable& b) { - typedef FieldTable::ValueMap Map; - for (Map::const_iterator i = a.begin(); - i != a.end(); - ++i) - { - Map::const_iterator j = b.find(i->first); - if (j == b.end()) return false; - if (!match_values(*(i->second), *(j->second))) return false; - } - return true; -} - -//--------- -HeadersExchange::MatchArgs::MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a) : queue(q), args(a) {} - -bool HeadersExchange::MatchArgs::operator()(BoundKey & bk) -{ - return bk.binding->queue == queue && bk.binding->args == *args; -} - -//--------- -HeadersExchange::MatchKey::MatchKey(Queue::shared_ptr q, const std::string& k) : queue(q), key(k) {} - -bool HeadersExchange::MatchKey::operator()(BoundKey & bk) -{ - return bk.binding->queue == queue && bk.binding->key == key; -} - -//---------- -HeadersExchange::FedUnbindModifier::FedUnbindModifier(const string& queueName, const string& origin) : queueName(queueName), fedOrigin(origin), shouldUnbind(false), shouldPropagate(false) {} -HeadersExchange::FedUnbindModifier::FedUnbindModifier() : shouldUnbind(false), shouldPropagate(false) {} - -bool HeadersExchange::FedUnbindModifier::operator()(BoundKey & bk) -{ - shouldPropagate = bk.fedBinding.delOrigin(queueName, fedOrigin); - if (bk.fedBinding.countFedBindings(queueName) == 0) - { - shouldUnbind = true; - } - return true; -} - diff --git a/cpp/src/qpid/broker/HeadersExchange.h b/cpp/src/qpid/broker/HeadersExchange.h deleted file mode 100644 index 3b939d6851..0000000000 --- a/cpp/src/qpid/broker/HeadersExchange.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _HeadersExchange_ -#define _HeadersExchange_ - -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/Queue.h" - -namespace qpid { -namespace broker { - - -class HeadersExchange : public virtual Exchange { - - struct BoundKey - { - Binding::shared_ptr binding; - FedBinding fedBinding; - BoundKey(Binding::shared_ptr binding_) : binding(binding_) {} - }; - - struct MatchArgs - { - const Queue::shared_ptr queue; - const qpid::framing::FieldTable* args; - MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a); - bool operator()(BoundKey & bk); - }; - - struct MatchKey - { - const Queue::shared_ptr queue; - const std::string& key; - MatchKey(Queue::shared_ptr q, const std::string& k); - bool operator()(BoundKey & bk); - }; - - struct FedUnbindModifier - { - std::string queueName; - std::string fedOrigin; - bool shouldUnbind; - bool shouldPropagate; - FedUnbindModifier(); - FedUnbindModifier(const std::string& queueName, const std::string& origin); - bool operator()(BoundKey & bk); - }; - - typedef qpid::sys::CopyOnWriteArray<BoundKey> Bindings; - - Bindings bindings; - qpid::sys::Mutex lock; - - static std::string getMatch(const framing::FieldTable* args); - - protected: - void getNonFedArgs(const framing::FieldTable* args, - framing::FieldTable& nonFedArgs); - - public: - static const std::string typeName; - - QPID_BROKER_EXTERN HeadersExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN HeadersExchange(const std::string& _name, - bool _durable, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual bool isBound(Queue::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~HeadersExchange(); - - virtual bool supportsDynamicBinding() { return true; } - - static QPID_BROKER_EXTERN bool match(const qpid::framing::FieldTable& bindArgs, const qpid::framing::FieldTable& msgArgs); - static bool equal(const qpid::framing::FieldTable& bindArgs, const qpid::framing::FieldTable& msgArgs); -}; - - - -} -} - -#endif diff --git a/cpp/src/qpid/broker/LegacyLVQ.cpp b/cpp/src/qpid/broker/LegacyLVQ.cpp deleted file mode 100644 index a811a86492..0000000000 --- a/cpp/src/qpid/broker/LegacyLVQ.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/LegacyLVQ.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/QueuedMessage.h" - -namespace qpid { -namespace broker { - -LegacyLVQ::LegacyLVQ(const std::string& k, bool b, Broker* br) : MessageMap(k), noBrowse(b), broker(br) {} - -void LegacyLVQ::setNoBrowse(bool b) -{ - noBrowse = b; -} - -bool LegacyLVQ::remove(const framing::SequenceNumber& position, QueuedMessage& message) -{ - Ordering::iterator i = messages.find(position); - if (i != messages.end() && i->second.payload == message.payload) { - message = i->second; - erase(i); - return true; - } else { - return false; - } -} - -bool LegacyLVQ::next(const framing::SequenceNumber& position, QueuedMessage& message) -{ - if (MessageMap::next(position, message)) { - if (!noBrowse) index.erase(getKey(message)); - return true; - } else { - return false; - } -} - -bool LegacyLVQ::push(const QueuedMessage& added, QueuedMessage& removed) -{ - //Hack to disable LVQ behaviour on cluster update: - if (broker && broker->isClusterUpdatee()) { - messages[added.position] = added; - return false; - } else { - return MessageMap::push(added, removed); - } -} - -const QueuedMessage& LegacyLVQ::replace(const QueuedMessage& original, const QueuedMessage& update) -{ - //add the new message into the original position of the replaced message - Ordering::iterator i = messages.find(original.position); - i->second = update; - i->second.position = original.position; - return i->second; -} - -void LegacyLVQ::removeIf(Predicate p) -{ - //Note: This method is currently called periodically on the timer - //thread to expire messages. In a clustered broker this means that - //the purging does not occur on the cluster event dispatch thread - //and consequently that is not totally ordered w.r.t other events - //(including publication of messages). The cluster does ensure - //that the actual expiration of messages (as distinct from the - //removing of those expired messages from the queue) *is* - //consistently ordered w.r.t. cluster events. This means that - //delivery of messages is in general consistent across the cluster - //inspite of any non-determinism in the triggering of a - //purge. However at present purging a last value queue (of the - //legacy sort) could potentially cause inconsistencies in the - //cluster (as the order w.r.t publications can affect the order in - //which messages appear in the queue). Consequently periodic - //purging of an LVQ is not enabled if the broker is clustered - //(expired messages will be removed on delivery and consolidated - //by key as part of normal LVQ operation). - - //TODO: Is there a neater way to check whether broker is - //clustered? Here we assume that if the clustered timer is the - //same as the regular timer, we are not clustered: - if (!broker || &(broker->getClusterTimer()) == &(broker->getTimer())) - MessageMap::removeIf(p); -} - -std::auto_ptr<Messages> LegacyLVQ::updateOrReplace(std::auto_ptr<Messages> current, - const std::string& key, bool noBrowse, Broker* broker) -{ - LegacyLVQ* lvq = dynamic_cast<LegacyLVQ*>(current.get()); - if (lvq) { - lvq->setNoBrowse(noBrowse); - return current; - } else { - return std::auto_ptr<Messages>(new LegacyLVQ(key, noBrowse, broker)); - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/LegacyLVQ.h b/cpp/src/qpid/broker/LegacyLVQ.h deleted file mode 100644 index dd0fd7aaec..0000000000 --- a/cpp/src/qpid/broker/LegacyLVQ.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef QPID_BROKER_LEGACYLVQ_H -#define QPID_BROKER_LEGACYLVQ_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/MessageMap.h" -#include <memory> - -namespace qpid { -namespace broker { -class Broker; - -/** - * This class encapsulates the behaviour of the old style LVQ where a - * message replacing another messages for the given key will use the - * position in the queue of the previous message. This however causes - * problems for browsing. Either browsers stop the coalescing of - * messages by key (default) or they may mis updates (if the no-browse - * option is specified). - */ -class LegacyLVQ : public MessageMap -{ - public: - LegacyLVQ(const std::string& key, bool noBrowse = false, Broker* broker = 0); - bool remove(const framing::SequenceNumber&, QueuedMessage&); - bool next(const framing::SequenceNumber&, QueuedMessage&); - bool push(const QueuedMessage& added, QueuedMessage& removed); - void removeIf(Predicate); - void setNoBrowse(bool); - static std::auto_ptr<Messages> updateOrReplace(std::auto_ptr<Messages> current, - const std::string& key, bool noBrowse, - Broker* broker); - protected: - bool noBrowse; - Broker* broker; - - const QueuedMessage& replace(const QueuedMessage&, const QueuedMessage&); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_LEGACYLVQ_H*/ diff --git a/cpp/src/qpid/broker/Link.cpp b/cpp/src/qpid/broker/Link.cpp deleted file mode 100644 index 91861ade3f..0000000000 --- a/cpp/src/qpid/broker/Link.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Link.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Connection.h" -#include "qmf/org/apache/qpid/broker/EventBrokerLinkUp.h" -#include "qmf/org/apache/qpid/broker/EventBrokerLinkDown.h" -#include "boost/bind.hpp" -#include "qpid/log/Statement.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/broker/AclModule.h" - -using namespace qpid::broker; -using qpid::framing::Buffer; -using qpid::framing::FieldTable; -using qpid::framing::UnauthorizedAccessException; -using qpid::framing::connection::CLOSE_CODE_CONNECTION_FORCED; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::sys::Mutex; -using std::stringstream; -using std::string; -namespace _qmf = qmf::org::apache::qpid::broker; - -Link::Link(LinkRegistry* _links, - MessageStore* _store, - string& _host, - uint16_t _port, - string& _transport, - bool _durable, - string& _authMechanism, - string& _username, - string& _password, - Broker* _broker, - Manageable* parent) - : links(_links), store(_store), host(_host), port(_port), - transport(_transport), - durable(_durable), - authMechanism(_authMechanism), username(_username), password(_password), - persistenceId(0), mgmtObject(0), broker(_broker), state(0), - visitCount(0), - currentInterval(1), - closing(false), - updateUrls(false), - channelCounter(1), - connection(0), - agent(0) -{ - if (parent != 0 && broker != 0) - { - agent = broker->getManagementAgent(); - if (agent != 0) - { - mgmtObject = new _qmf::Link(agent, this, parent, _host, _port, _transport, _durable); - agent->addObject(mgmtObject, 0, durable); - } - } - setStateLH(STATE_WAITING); -} - -Link::~Link () -{ - if (state == STATE_OPERATIONAL && connection != 0) - connection->close(CLOSE_CODE_CONNECTION_FORCED, "closed by management"); - - if (mgmtObject != 0) - mgmtObject->resourceDestroy (); -} - -void Link::setStateLH (int newState) -{ - if (newState == state) - return; - - state = newState; - - if (hideManagement()) - return; - - switch (state) - { - case STATE_WAITING : mgmtObject->set_state("Waiting"); break; - case STATE_CONNECTING : mgmtObject->set_state("Connecting"); break; - case STATE_OPERATIONAL : mgmtObject->set_state("Operational"); break; - case STATE_FAILED : mgmtObject->set_state("Failed"); break; - case STATE_CLOSED : mgmtObject->set_state("Closed"); break; - case STATE_PASSIVE : mgmtObject->set_state("Passive"); break; - } -} - -void Link::startConnectionLH () -{ - try { - // Set the state before calling connect. It is possible that connect - // will fail synchronously and call Link::closed before returning. - setStateLH(STATE_CONNECTING); - broker->connect (host, port, transport, - boost::bind (&Link::closed, this, _1, _2)); - QPID_LOG (debug, "Inter-broker link connecting to " << host << ":" << port); - } catch(std::exception& e) { - setStateLH(STATE_WAITING); - if (!hideManagement()) - mgmtObject->set_lastError (e.what()); - } -} - -void Link::established () -{ - stringstream addr; - addr << host << ":" << port; - QPID_LOG (info, "Inter-broker link established to " << addr.str()); - - if (!hideManagement() && agent) - agent->raiseEvent(_qmf::EventBrokerLinkUp(addr.str())); - - { - Mutex::ScopedLock mutex(lock); - setStateLH(STATE_OPERATIONAL); - currentInterval = 1; - visitCount = 0; - if (closing) - destroy(); - } -} - -void Link::closed (int, std::string text) -{ - Mutex::ScopedLock mutex(lock); - QPID_LOG (info, "Inter-broker link disconnected from " << host << ":" << port << " " << text); - - connection = 0; - - if (state == STATE_OPERATIONAL) { - stringstream addr; - addr << host << ":" << port; - QPID_LOG (warning, "Inter-broker link disconnected from " << addr.str()); - if (!hideManagement() && agent) - agent->raiseEvent(_qmf::EventBrokerLinkDown(addr.str())); - } - - for (Bridges::iterator i = active.begin(); i != active.end(); i++) { - (*i)->closed(); - created.push_back(*i); - } - active.clear(); - - if (state != STATE_FAILED) - { - setStateLH(STATE_WAITING); - if (!hideManagement()) - mgmtObject->set_lastError (text); - } - - if (closing) - destroy(); -} - -void Link::destroy () -{ - Bridges toDelete; - { - Mutex::ScopedLock mutex(lock); - - QPID_LOG (info, "Inter-broker link to " << host << ":" << port << " removed by management"); - if (connection) - connection->close(CLOSE_CODE_CONNECTION_FORCED, "closed by management"); - - setStateLH(STATE_CLOSED); - - // Move the bridges to be deleted into a local vector so there is no - // corruption of the iterator caused by bridge deletion. - for (Bridges::iterator i = active.begin(); i != active.end(); i++) { - (*i)->closed(); - toDelete.push_back(*i); - } - active.clear(); - - for (Bridges::iterator i = created.begin(); i != created.end(); i++) - toDelete.push_back(*i); - created.clear(); - } - // Now delete all bridges on this link (don't hold the lock for this). - for (Bridges::iterator i = toDelete.begin(); i != toDelete.end(); i++) - (*i)->destroy(); - toDelete.clear(); - links->destroy (host, port); -} - -void Link::add(Bridge::shared_ptr bridge) -{ - Mutex::ScopedLock mutex(lock); - created.push_back (bridge); -} - -void Link::cancel(Bridge::shared_ptr bridge) -{ - { - Mutex::ScopedLock mutex(lock); - - for (Bridges::iterator i = created.begin(); i != created.end(); i++) { - if ((*i).get() == bridge.get()) { - created.erase(i); - break; - } - } - for (Bridges::iterator i = active.begin(); i != active.end(); i++) { - if ((*i).get() == bridge.get()) { - cancellations.push_back(bridge); - bridge->closed(); - active.erase(i); - break; - } - } - } - if (!cancellations.empty()) { - connection->requestIOProcessing (boost::bind(&Link::ioThreadProcessing, this)); - } -} - -void Link::ioThreadProcessing() -{ - Mutex::ScopedLock mutex(lock); - - if (state != STATE_OPERATIONAL) - return; - QPID_LOG(debug, "Link::ioThreadProcessing()"); - - //process any pending creates and/or cancellations - if (!created.empty()) { - for (Bridges::iterator i = created.begin(); i != created.end(); ++i) { - active.push_back(*i); - (*i)->create(*connection); - } - created.clear(); - } - if (!cancellations.empty()) { - for (Bridges::iterator i = cancellations.begin(); i != cancellations.end(); ++i) { - (*i)->cancel(*connection); - } - cancellations.clear(); - } -} - -void Link::setConnection(Connection* c) -{ - Mutex::ScopedLock mutex(lock); - connection = c; - updateUrls = true; -} - -void Link::maintenanceVisit () -{ - Mutex::ScopedLock mutex(lock); - - if (connection && updateUrls) { - urls.reset(connection->getKnownHosts()); - QPID_LOG(debug, "Known hosts for peer of inter-broker link: " << urls); - updateUrls = false; - } - - if (state == STATE_WAITING) - { - visitCount++; - if (visitCount >= currentInterval) - { - visitCount = 0; - //switch host and port to next in url list if possible - if (!tryFailover()) { - currentInterval *= 2; - if (currentInterval > MAX_INTERVAL) - currentInterval = MAX_INTERVAL; - startConnectionLH(); - } - } - } - else if (state == STATE_OPERATIONAL && (!created.empty() || !cancellations.empty()) && connection != 0) - connection->requestIOProcessing (boost::bind(&Link::ioThreadProcessing, this)); -} - -void Link::reconnect(const qpid::Address& a) -{ - Mutex::ScopedLock mutex(lock); - host = a.host; - port = a.port; - transport = a.protocol; - startConnectionLH(); - if (!hideManagement()) { - stringstream errorString; - errorString << "Failed over to " << a; - mgmtObject->set_lastError(errorString.str()); - } -} - -bool Link::tryFailover() -{ - Address next; - if (urls.next(next) && - (next.host != host || next.port != port || next.protocol != transport)) { - links->changeAddress(Address(transport, host, port), next); - QPID_LOG(debug, "Link failing over to " << host << ":" << port); - return true; - } else { - return false; - } -} - -// Management updates for a linke are inconsistent in a cluster, so they are -// suppressed. -bool Link::hideManagement() const { - return !mgmtObject || ( broker && broker->isInCluster()); -} - -uint Link::nextChannel() -{ - Mutex::ScopedLock mutex(lock); - - return channelCounter++; -} - -void Link::notifyConnectionForced(const string text) -{ - Mutex::ScopedLock mutex(lock); - - setStateLH(STATE_FAILED); - if (!hideManagement()) - mgmtObject->set_lastError(text); -} - -void Link::setPersistenceId(uint64_t id) const -{ - persistenceId = id; -} - -const string& Link::getName() const -{ - return host; -} - -Link::shared_ptr Link::decode(LinkRegistry& links, Buffer& buffer) -{ - string host; - uint16_t port; - string transport; - string authMechanism; - string username; - string password; - - buffer.getShortString(host); - port = buffer.getShort(); - buffer.getShortString(transport); - bool durable(buffer.getOctet()); - buffer.getShortString(authMechanism); - buffer.getShortString(username); - buffer.getShortString(password); - - return links.declare(host, port, transport, durable, authMechanism, username, password).first; -} - -void Link::encode(Buffer& buffer) const -{ - buffer.putShortString(string("link")); - buffer.putShortString(host); - buffer.putShort(port); - buffer.putShortString(transport); - buffer.putOctet(durable ? 1 : 0); - buffer.putShortString(authMechanism); - buffer.putShortString(username); - buffer.putShortString(password); -} - -uint32_t Link::encodedSize() const -{ - return host.size() + 1 // short-string (host) - + 5 // short-string ("link") - + 2 // port - + transport.size() + 1 // short-string(transport) - + 1 // durable - + authMechanism.size() + 1 - + username.size() + 1 - + password.size() + 1; -} - -ManagementObject* Link::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t Link::ManagementMethod (uint32_t op, Args& args, string& text) -{ - switch (op) - { - case _qmf::Link::METHOD_CLOSE : - if (!closing) { - closing = true; - if (state != STATE_CONNECTING && connection) { - //connection can only be closed on the connections own IO processing thread - connection->requestIOProcessing(boost::bind(&Link::destroy, this)); - } - } - return Manageable::STATUS_OK; - - case _qmf::Link::METHOD_BRIDGE : - _qmf::ArgsLinkBridge& iargs = (_qmf::ArgsLinkBridge&) args; - QPID_LOG(debug, "Link::bridge() request received"); - - // Durable bridges are only valid on durable links - if (iargs.i_durable && !durable) { - text = "Can't create a durable route on a non-durable link"; - return Manageable::STATUS_USER; - } - - if (iargs.i_dynamic) { - Exchange::shared_ptr exchange = getBroker()->getExchanges().get(iargs.i_src); - if (exchange.get() == 0) { - text = "Exchange not found"; - return Manageable::STATUS_USER; - } - if (!exchange->supportsDynamicBinding()) { - text = "Exchange type does not support dynamic routing"; - return Manageable::STATUS_USER; - } - } - - std::pair<Bridge::shared_ptr, bool> result = - links->declare (host, port, iargs.i_durable, iargs.i_src, - iargs.i_dest, iargs.i_key, iargs.i_srcIsQueue, - iargs.i_srcIsLocal, iargs.i_tag, iargs.i_excludes, - iargs.i_dynamic, iargs.i_sync); - - if (result.second && iargs.i_durable) - store->create(*result.first); - - return Manageable::STATUS_OK; - } - - return Manageable::STATUS_UNKNOWN_METHOD; -} - -void Link::setPassive(bool passive) -{ - Mutex::ScopedLock mutex(lock); - if (passive) { - setStateLH(STATE_PASSIVE); - } else { - if (state == STATE_PASSIVE) { - setStateLH(STATE_WAITING); - } else { - QPID_LOG(warning, "Ignoring attempt to activate non-passive link"); - } - } -} diff --git a/cpp/src/qpid/broker/Link.h b/cpp/src/qpid/broker/Link.h deleted file mode 100644 index 4badd8b3a1..0000000000 --- a/cpp/src/qpid/broker/Link.h +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef _broker_Link_h -#define _broker_Link_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/PersistableConfig.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/RetryList.h" -#include "qpid/sys/Mutex.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/management/Manageable.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/broker/Link.h" -#include <boost/ptr_container/ptr_vector.hpp> - -namespace qpid { - namespace broker { - - class LinkRegistry; - class Broker; - class Connection; - - class Link : public PersistableConfig, public management::Manageable { - private: - sys::Mutex lock; - LinkRegistry* links; - MessageStore* store; - std::string host; - uint16_t port; - std::string transport; - bool durable; - std::string authMechanism; - std::string username; - std::string password; - mutable uint64_t persistenceId; - qmf::org::apache::qpid::broker::Link* mgmtObject; - Broker* broker; - int state; - uint32_t visitCount; - uint32_t currentInterval; - bool closing; - RetryList urls; - bool updateUrls; - - typedef std::vector<Bridge::shared_ptr> Bridges; - Bridges created; // Bridges pending creation - Bridges active; // Bridges active - Bridges cancellations; // Bridges pending cancellation - uint channelCounter; - Connection* connection; - management::ManagementAgent* agent; - - static const int STATE_WAITING = 1; - static const int STATE_CONNECTING = 2; - static const int STATE_OPERATIONAL = 3; - static const int STATE_FAILED = 4; - static const int STATE_CLOSED = 5; - static const int STATE_PASSIVE = 6; - - static const uint32_t MAX_INTERVAL = 32; - - void setStateLH (int newState); - void startConnectionLH(); // Start the IO Connection - void destroy(); // Called when mgmt deletes this link - void ioThreadProcessing(); // Called on connection's IO thread by request - bool tryFailover(); // Called during maintenance visit - bool hideManagement() const; - - public: - typedef boost::shared_ptr<Link> shared_ptr; - - Link(LinkRegistry* links, - MessageStore* store, - std::string& host, - uint16_t port, - std::string& transport, - bool durable, - std::string& authMechanism, - std::string& username, - std::string& password, - Broker* broker, - management::Manageable* parent = 0); - virtual ~Link(); - - std::string getHost() { return host; } - uint16_t getPort() { return port; } - bool isDurable() { return durable; } - void maintenanceVisit (); - uint nextChannel(); - void add(Bridge::shared_ptr); - void cancel(Bridge::shared_ptr); - - void established(); // Called when connection is created - void closed(int, std::string); // Called when connection goes away - void setConnection(Connection*); // Set pointer to the AMQP Connection - void reconnect(const Address&); //called by LinkRegistry - - std::string getAuthMechanism() { return authMechanism; } - std::string getUsername() { return username; } - std::string getPassword() { return password; } - Broker* getBroker() { return broker; } - - void notifyConnectionForced(const std::string text); - void setPassive(bool p); - - // PersistableConfig: - void setPersistenceId(uint64_t id) const; - uint64_t getPersistenceId() const { return persistenceId; } - uint32_t encodedSize() const; - void encode(framing::Buffer& buffer) const; - const std::string& getName() const; - - static Link::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer); - - // Manageable entry points - management::ManagementObject* GetManagementObject(void) const; - management::Manageable::status_t ManagementMethod(uint32_t, management::Args&, std::string&); - - }; - } -} - - -#endif /*!_broker_Link.cpp_h*/ diff --git a/cpp/src/qpid/broker/LinkRegistry.cpp b/cpp/src/qpid/broker/LinkRegistry.cpp deleted file mode 100644 index e9885f5462..0000000000 --- a/cpp/src/qpid/broker/LinkRegistry.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" -#include <iostream> -#include <boost/format.hpp> - -using namespace qpid::broker; -using namespace qpid::sys; -using std::string; -using std::pair; -using std::stringstream; -using boost::intrusive_ptr; -using boost::format; -using boost::str; -namespace _qmf = qmf::org::apache::qpid::broker; - -#define LINK_MAINT_INTERVAL 2 - -// TODO: This constructor is only used by the store unit tests - -// That probably indicates that LinkRegistry isn't correctly -// factored: The persistence element and maintenance element -// should be factored separately -LinkRegistry::LinkRegistry () : - broker(0), timer(0), - parent(0), store(0), passive(false), passiveChanged(false), - realm("") -{ -} - -LinkRegistry::LinkRegistry (Broker* _broker) : - broker(_broker), timer(&broker->getTimer()), - maintenanceTask(new Periodic(*this)), - parent(0), store(0), passive(false), passiveChanged(false), - realm(broker->getOptions().realm) -{ - timer->add(maintenanceTask); -} - -LinkRegistry::~LinkRegistry() -{ - // This test is only necessary if the default constructor above is present - if (maintenanceTask) - maintenanceTask->cancel(); -} - -LinkRegistry::Periodic::Periodic (LinkRegistry& _links) : - TimerTask (Duration (LINK_MAINT_INTERVAL * TIME_SEC),"LinkRegistry"), links(_links) {} - -void LinkRegistry::Periodic::fire () -{ - links.periodicMaintenance (); - setupNextFire(); - links.timer->add(this); -} - -void LinkRegistry::periodicMaintenance () -{ - Mutex::ScopedLock locker(lock); - - linksToDestroy.clear(); - bridgesToDestroy.clear(); - if (passiveChanged) { - if (passive) { QPID_LOG(info, "Passivating links"); } - else { QPID_LOG(info, "Activating links"); } - for (LinkMap::iterator i = links.begin(); i != links.end(); i++) { - i->second->setPassive(passive); - } - passiveChanged = false; - } - for (LinkMap::iterator i = links.begin(); i != links.end(); i++) - i->second->maintenanceVisit(); - //now process any requests for re-addressing - for (AddressMap::iterator i = reMappings.begin(); i != reMappings.end(); i++) - updateAddress(i->first, i->second); - reMappings.clear(); -} - -void LinkRegistry::changeAddress(const qpid::Address& oldAddress, const qpid::Address& newAddress) -{ - //done on periodic maintenance thread; hold changes in separate - //map to avoid modifying the link map that is iterated over - reMappings[createKey(oldAddress)] = newAddress; -} - -bool LinkRegistry::updateAddress(const std::string& oldKey, const qpid::Address& newAddress) -{ - std::string newKey = createKey(newAddress); - if (links.find(newKey) != links.end()) { - QPID_LOG(error, "Attempted to update key from " << oldKey << " to " << newKey << " which is already in use"); - return false; - } else { - LinkMap::iterator i = links.find(oldKey); - if (i == links.end()) { - QPID_LOG(error, "Attempted to update key from " << oldKey << " which does not exist, to " << newKey); - return false; - } else { - links[newKey] = i->second; - i->second->reconnect(newAddress); - links.erase(oldKey); - QPID_LOG(info, "Updated link key from " << oldKey << " to " << newKey); - return true; - } - } -} - -pair<Link::shared_ptr, bool> LinkRegistry::declare(string& host, - uint16_t port, - string& transport, - bool durable, - string& authMechanism, - string& username, - string& password) - -{ - Mutex::ScopedLock locker(lock); - string key = createKey(host, port); - - LinkMap::iterator i = links.find(key); - if (i == links.end()) - { - Link::shared_ptr link; - - link = Link::shared_ptr (new Link (this, store, host, port, transport, durable, - authMechanism, username, password, - broker, parent)); - if (passive) link->setPassive(true); - links[key] = link; - return std::pair<Link::shared_ptr, bool>(link, true); - } - return std::pair<Link::shared_ptr, bool>(i->second, false); -} - -pair<Bridge::shared_ptr, bool> LinkRegistry::declare(std::string& host, - uint16_t port, - bool durable, - std::string& src, - std::string& dest, - std::string& key, - bool isQueue, - bool isLocal, - std::string& tag, - std::string& excludes, - bool dynamic, - uint16_t sync) -{ - Mutex::ScopedLock locker(lock); - QPID_LOG(debug, "Bridge declared " << host << ": " << port << " from " << src << " to " << dest << " (" << key << ")"); - - string linkKey = createKey(host, port); - stringstream keystream; - keystream << linkKey << "!" << src << "!" << dest << "!" << key; - string bridgeKey = keystream.str(); - - LinkMap::iterator l = links.find(linkKey); - if (l == links.end()) - return pair<Bridge::shared_ptr, bool>(Bridge::shared_ptr(), false); - - BridgeMap::iterator b = bridges.find(bridgeKey); - if (b == bridges.end()) - { - _qmf::ArgsLinkBridge args; - Bridge::shared_ptr bridge; - - args.i_durable = durable; - args.i_src = src; - args.i_dest = dest; - args.i_key = key; - args.i_srcIsQueue = isQueue; - args.i_srcIsLocal = isLocal; - args.i_tag = tag; - args.i_excludes = excludes; - args.i_dynamic = dynamic; - args.i_sync = sync; - - bridge = Bridge::shared_ptr - (new Bridge (l->second.get(), l->second->nextChannel(), - boost::bind(&LinkRegistry::destroy, this, - host, port, src, dest, key), args)); - bridges[bridgeKey] = bridge; - l->second->add(bridge); - return std::pair<Bridge::shared_ptr, bool>(bridge, true); - } - return std::pair<Bridge::shared_ptr, bool>(b->second, false); -} - -void LinkRegistry::destroy(const string& host, const uint16_t port) -{ - Mutex::ScopedLock locker(lock); - string key = createKey(host, port); - - LinkMap::iterator i = links.find(key); - if (i != links.end()) - { - if (i->second->isDurable() && store) - store->destroy(*(i->second)); - linksToDestroy[key] = i->second; - links.erase(i); - } -} - -void LinkRegistry::destroy(const std::string& host, - const uint16_t port, - const std::string& src, - const std::string& dest, - const std::string& key) -{ - Mutex::ScopedLock locker(lock); - string linkKey = createKey(host, port); - stringstream keystream; - keystream << linkKey << "!" << src << "!" << dest << "!" << key; - string bridgeKey = keystream.str(); - - LinkMap::iterator l = links.find(linkKey); - if (l == links.end()) - return; - - BridgeMap::iterator b = bridges.find(bridgeKey); - if (b == bridges.end()) - return; - - l->second->cancel(b->second); - if (b->second->isDurable()) - store->destroy(*(b->second)); - bridgesToDestroy[bridgeKey] = b->second; - bridges.erase(b); -} - -void LinkRegistry::setStore (MessageStore* _store) -{ - store = _store; -} - -MessageStore* LinkRegistry::getStore() const { - return store; -} - -Link::shared_ptr LinkRegistry::findLink(const std::string& keyOrMgmtId) -{ - // Convert keyOrMgmtId to a host:port key. - // - // TODO aconway 2011-02-01: centralize code that constructs/parses - // connection management IDs. Currently sys:: protocol factories - // and IO plugins construct the IDs and LinkRegistry parses them. - size_t separator = keyOrMgmtId.find('-'); - if (separator == std::string::npos) separator = 0; - std::string key = keyOrMgmtId.substr(separator+1, std::string::npos); - - Mutex::ScopedLock locker(lock); - LinkMap::iterator l = links.find(key); - if (l != links.end()) return l->second; - else return Link::shared_ptr(); -} - -void LinkRegistry::notifyConnection(const std::string& key, Connection* c) -{ - Link::shared_ptr link = findLink(key); - if (link) { - link->established(); - link->setConnection(c); - c->setUserId(str(format("%1%@%2%") % link->getUsername() % realm)); - } -} - -void LinkRegistry::notifyClosed(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (link) { - link->closed(0, "Closed by peer"); - } -} - -void LinkRegistry::notifyConnectionForced(const std::string& key, const std::string& text) -{ - Link::shared_ptr link = findLink(key); - if (link) { - link->notifyConnectionForced(text); - } -} - -std::string LinkRegistry::getAuthMechanism(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (link) - return link->getAuthMechanism(); - return string("ANONYMOUS"); -} - -std::string LinkRegistry::getAuthCredentials(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - string result; - result += '\0'; - result += link->getUsername(); - result += '\0'; - result += link->getPassword(); - - return result; -} - -std::string LinkRegistry::getUsername(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getUsername(); -} - -std::string LinkRegistry::getHost(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getHost(); -} - -uint16_t LinkRegistry::getPort(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return 0; - - return link->getPort(); -} - -std::string LinkRegistry::getPassword(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getPassword(); -} - -std::string LinkRegistry::getAuthIdentity(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getUsername(); -} - - -std::string LinkRegistry::createKey(const qpid::Address& a) { - // TODO aconway 2010-05-11: key should also include protocol/transport to - // be unique. Requires refactor of LinkRegistry interface. - return createKey(a.host, a.port); -} - -std::string LinkRegistry::createKey(const std::string& host, uint16_t port) { - // TODO aconway 2010-05-11: key should also include protocol/transport to - // be unique. Requires refactor of LinkRegistry interface. - stringstream keystream; - keystream << host << ":" << port; - return keystream.str(); -} - -void LinkRegistry::setPassive(bool p) -{ - Mutex::ScopedLock locker(lock); - passiveChanged = p != passive; - passive = p; - //will activate or passivate links on maintenance visit -} - -void LinkRegistry::eachLink(boost::function<void(boost::shared_ptr<Link>)> f) { - for (LinkMap::iterator i = links.begin(); i != links.end(); ++i) f(i->second); -} - -void LinkRegistry::eachBridge(boost::function<void(boost::shared_ptr<Bridge>)> f) { - for (BridgeMap::iterator i = bridges.begin(); i != bridges.end(); ++i) f(i->second); -} - diff --git a/cpp/src/qpid/broker/LinkRegistry.h b/cpp/src/qpid/broker/LinkRegistry.h deleted file mode 100644 index 4c97e4f9d8..0000000000 --- a/cpp/src/qpid/broker/LinkRegistry.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef _broker_LinkRegistry_h -#define _broker_LinkRegistry_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <map> -#include "qpid/broker/Bridge.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/Address.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Timer.h" -#include "qpid/management/Manageable.h" -#include <boost/shared_ptr.hpp> -#include <boost/intrusive_ptr.hpp> -#include <boost/function.hpp> - -namespace qpid { -namespace broker { - - class Link; - class Broker; - class Connection; - class LinkRegistry { - - // Declare a timer task to manage the establishment of link connections and the - // re-establishment of lost link connections. - struct Periodic : public sys::TimerTask - { - LinkRegistry& links; - - Periodic(LinkRegistry& links); - virtual ~Periodic() {}; - void fire(); - }; - - typedef std::map<std::string, boost::shared_ptr<Link> > LinkMap; - typedef std::map<std::string, Bridge::shared_ptr> BridgeMap; - typedef std::map<std::string, Address> AddressMap; - - LinkMap links; - LinkMap linksToDestroy; - BridgeMap bridges; - BridgeMap bridgesToDestroy; - AddressMap reMappings; - - qpid::sys::Mutex lock; - Broker* broker; - sys::Timer* timer; - boost::intrusive_ptr<qpid::sys::TimerTask> maintenanceTask; - management::Manageable* parent; - MessageStore* store; - bool passive; - bool passiveChanged; - std::string realm; - - void periodicMaintenance (); - bool updateAddress(const std::string& oldKey, const Address& newAddress); - boost::shared_ptr<Link> findLink(const std::string& key); - static std::string createKey(const Address& address); - static std::string createKey(const std::string& host, uint16_t port); - - public: - LinkRegistry (); // Only used in store tests - LinkRegistry (Broker* _broker); - ~LinkRegistry(); - - std::pair<boost::shared_ptr<Link>, bool> - declare(std::string& host, - uint16_t port, - std::string& transport, - bool durable, - std::string& authMechanism, - std::string& username, - std::string& password); - std::pair<Bridge::shared_ptr, bool> - declare(std::string& host, - uint16_t port, - bool durable, - std::string& src, - std::string& dest, - std::string& key, - bool isQueue, - bool isLocal, - std::string& id, - std::string& excludes, - bool dynamic, - uint16_t sync); - - void destroy(const std::string& host, const uint16_t port); - void destroy(const std::string& host, - const uint16_t port, - const std::string& src, - const std::string& dest, - const std::string& key); - - /** - * Register the manageable parent for declared queues - */ - void setParent (management::Manageable* _parent) { parent = _parent; } - - /** - * Set the store to use. May only be called once. - */ - void setStore (MessageStore*); - - /** - * Return the message store used. - */ - MessageStore* getStore() const; - - void notifyConnection (const std::string& key, Connection* c); - void notifyClosed (const std::string& key); - void notifyConnectionForced (const std::string& key, const std::string& text); - std::string getAuthMechanism (const std::string& key); - std::string getAuthCredentials (const std::string& key); - std::string getAuthIdentity (const std::string& key); - std::string getUsername (const std::string& key); - std::string getPassword (const std::string& key); - std::string getHost (const std::string& key); - uint16_t getPort (const std::string& key); - - /** - * Called by links failing over to new address - */ - void changeAddress(const Address& oldAddress, const Address& newAddress); - /** - * Called to alter passive state. In passive state the links - * and bridges managed by a link registry will be recorded and - * updated but links won't actually establish connections and - * bridges won't therefore pull or push any messages. - */ - void setPassive(bool); - - - /** Iterate over each link in the registry. Used for cluster updates. */ - void eachLink(boost::function<void(boost::shared_ptr<Link>)> f); - /** Iterate over each bridge in the registry. Used for cluster updates. */ - void eachBridge(boost::function<void(boost::shared_ptr< Bridge>)> f); - }; -} -} - - -#endif /*!_broker_LinkRegistry_h*/ diff --git a/cpp/src/qpid/broker/Message.cpp b/cpp/src/qpid/broker/Message.cpp deleted file mode 100644 index 763dc55e40..0000000000 --- a/cpp/src/qpid/broker/Message.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/StringUtils.h" -#include "qpid/framing/frame_functors.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/SendContent.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/TypeFilter.h" -#include "qpid/log/Statement.h" - -#include <time.h> - -using boost::intrusive_ptr; -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::sys::TIME_MSEC; -using qpid::sys::FAR_FUTURE; -using std::string; -using namespace qpid::framing; - -namespace qpid { -namespace broker { - -TransferAdapter Message::TRANSFER; - -Message::Message(const framing::SequenceNumber& id) : - frames(id), persistenceId(0), redelivered(false), loaded(false), - staged(false), forcePersistentPolicy(false), publisher(0), adapter(0), - expiration(FAR_FUTURE), dequeueCallback(0), - inCallback(false), requiredCredit(0), isManagementMessage(false) -{} - -Message::Message(const Message& original) : - PersistableMessage(), frames(original.frames), persistenceId(0), redelivered(false), loaded(false), - staged(false), forcePersistentPolicy(false), publisher(0), adapter(0), - expiration(original.expiration), dequeueCallback(0), - inCallback(false), requiredCredit(0) -{ - setExpiryPolicy(original.expiryPolicy); -} - -Message::~Message() -{ - if (expiryPolicy) - expiryPolicy->forget(*this); -} - -void Message::forcePersistent() -{ - // only set forced bit if we actually need to force. - if (! getAdapter().isPersistent(frames) ){ - forcePersistentPolicy = true; - } -} - -bool Message::isForcedPersistent() -{ - return forcePersistentPolicy; -} - -std::string Message::getRoutingKey() const -{ - return getAdapter().getRoutingKey(frames); -} - -std::string Message::getExchangeName() const -{ - return getAdapter().getExchange(frames); -} - -const boost::shared_ptr<Exchange> Message::getExchange(ExchangeRegistry& registry) const -{ - if (!exchange) { - exchange = registry.get(getExchangeName()); - } - return exchange; -} - -bool Message::isImmediate() const -{ - return getAdapter().isImmediate(frames); -} - -const FieldTable* Message::getApplicationHeaders() const -{ - return getAdapter().getApplicationHeaders(frames); -} - -std::string Message::getAppId() const -{ - return getAdapter().getAppId(frames); -} - -bool Message::isPersistent() const -{ - return (getAdapter().isPersistent(frames) || forcePersistentPolicy); -} - -bool Message::requiresAccept() -{ - return getAdapter().requiresAccept(frames); -} - -uint32_t Message::getRequiredCredit() -{ - sys::Mutex::ScopedLock l(lock); - if (!requiredCredit) { - //add up payload for all header and content frames in the frameset - SumBodySize sum; - frames.map_if(sum, TypeFilter2<HEADER_BODY, CONTENT_BODY>()); - requiredCredit = sum.getSize(); - } - return requiredCredit; -} - -void Message::encode(framing::Buffer& buffer) const -{ - //encode method and header frames - EncodeFrame f1(buffer); - frames.map_if(f1, TypeFilter2<METHOD_BODY, HEADER_BODY>()); - - //then encode the payload of each content frame - framing::EncodeBody f2(buffer); - frames.map_if(f2, TypeFilter<CONTENT_BODY>()); -} - -void Message::encodeContent(framing::Buffer& buffer) const -{ - //encode the payload of each content frame - EncodeBody f2(buffer); - frames.map_if(f2, TypeFilter<CONTENT_BODY>()); -} - -uint32_t Message::encodedSize() const -{ - return encodedHeaderSize() + encodedContentSize(); -} - -uint32_t Message::encodedContentSize() const -{ - return frames.getContentSize(); -} - -uint32_t Message::encodedHeaderSize() const -{ - //add up the size for all method and header frames in the frameset - SumFrameSize sum; - frames.map_if(sum, TypeFilter2<METHOD_BODY, HEADER_BODY>()); - return sum.getSize(); -} - -void Message::decodeHeader(framing::Buffer& buffer) -{ - AMQFrame method; - method.decode(buffer); - frames.append(method); - - AMQFrame header; - header.decode(buffer); - frames.append(header); -} - -void Message::decodeContent(framing::Buffer& buffer) -{ - if (buffer.available()) { - //get the data as a string and set that as the content - //body on a frame then add that frame to the frameset - AMQFrame frame((AMQContentBody())); - frame.castBody<AMQContentBody>()->decode(buffer, buffer.available()); - frame.setFirstSegment(false); - frames.append(frame); - } else { - //adjust header flags - MarkLastSegment f; - frames.map_if(f, TypeFilter<HEADER_BODY>()); - } - //mark content loaded - loaded = true; -} - -// Used for testing only -void Message::tryReleaseContent() -{ - if (checkContentReleasable()) { - releaseContent(); - } -} - -void Message::releaseContent(MessageStore* s) -{ - //deprecated, use setStore(store); releaseContent(); instead - if (!store) setStore(s); - releaseContent(); -} - -void Message::releaseContent() -{ - sys::Mutex::ScopedLock l(lock); - if (store) { - if (!getPersistenceId()) { - intrusive_ptr<PersistableMessage> pmsg(this); - store->stage(pmsg); - staged = true; - } - //ensure required credit is cached before content frames are released - getRequiredCredit(); - //remove any content frames from the frameset - frames.remove(TypeFilter<CONTENT_BODY>()); - setContentReleased(); - } -} - -void Message::destroy() -{ - if (staged) { - if (store) { - store->destroy(*this); - } else { - QPID_LOG(error, "Message content was staged but no store is set so it can't be destroyed"); - } - } -} - -bool Message::getContentFrame(const Queue& queue, AMQFrame& frame, uint16_t maxContentSize, uint64_t offset) const -{ - intrusive_ptr<const PersistableMessage> pmsg(this); - - bool done = false; - string& data = frame.castBody<AMQContentBody>()->getData(); - store->loadContent(queue, pmsg, data, offset, maxContentSize); - done = data.size() < maxContentSize; - frame.setBof(false); - frame.setEof(true); - QPID_LOG(debug, "loaded frame" << frame); - if (offset > 0) { - frame.setBos(false); - } - if (!done) { - frame.setEos(false); - } else return false; - return true; -} - -void Message::sendContent(const Queue& queue, framing::FrameHandler& out, uint16_t maxFrameSize) const -{ - sys::Mutex::ScopedLock l(lock); - if (isContentReleased() && !frames.isComplete()) { - sys::Mutex::ScopedUnlock u(lock); - uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead(); - bool morecontent = true; - for (uint64_t offset = 0; morecontent; offset += maxContentSize) - { - AMQFrame frame((AMQContentBody())); - morecontent = getContentFrame(queue, frame, maxContentSize, offset); - out.handle(frame); - } - } else { - Count c; - frames.map_if(c, TypeFilter<CONTENT_BODY>()); - - SendContent f(out, maxFrameSize, c.getCount()); - frames.map_if(f, TypeFilter<CONTENT_BODY>()); - } -} - -void Message::sendHeader(framing::FrameHandler& out, uint16_t /*maxFrameSize*/) const -{ - sys::Mutex::ScopedLock l(lock); - Relay f(out); - frames.map_if(f, TypeFilter<HEADER_BODY>()); -} - -// TODO aconway 2007-11-09: Obsolete, remove. Was used to cover over -// 0-8/0-9 message differences. -MessageAdapter& Message::getAdapter() const -{ - if (!adapter) { - if(frames.isA<MessageTransferBody>()) { - adapter = &TRANSFER; - } else { - const AMQMethodBody* method = frames.getMethod(); - if (!method) throw Exception("Can't adapt message with no method"); - else throw Exception(QPID_MSG("Can't adapt message based on " << *method)); - } - } - return *adapter; -} - -uint64_t Message::contentSize() const -{ - return frames.getContentSize(); -} - -bool Message::isContentLoaded() const -{ - return loaded; -} - - -namespace -{ -const std::string X_QPID_TRACE("x-qpid.trace"); -} - -bool Message::isExcluded(const std::vector<std::string>& excludes) const -{ - const FieldTable* headers = getApplicationHeaders(); - if (headers) { - std::string traceStr = headers->getAsString(X_QPID_TRACE); - if (traceStr.size()) { - std::vector<std::string> trace = split(traceStr, ", "); - - for (std::vector<std::string>::const_iterator i = excludes.begin(); i != excludes.end(); i++) { - for (std::vector<std::string>::const_iterator j = trace.begin(); j != trace.end(); j++) { - if (*i == *j) { - return true; - } - } - } - } - } - return false; -} - -void Message::addTraceId(const std::string& id) -{ - sys::Mutex::ScopedLock l(lock); - if (isA<MessageTransferBody>()) { - FieldTable& headers = getProperties<MessageProperties>()->getApplicationHeaders(); - std::string trace = headers.getAsString(X_QPID_TRACE); - if (trace.empty()) { - headers.setString(X_QPID_TRACE, id); - } else if (trace.find(id) == std::string::npos) { - trace += ","; - trace += id; - headers.setString(X_QPID_TRACE, trace); - } - } -} - -void Message::setTimestamp(const boost::intrusive_ptr<ExpiryPolicy>& e) -{ - DeliveryProperties* props = getProperties<DeliveryProperties>(); - if (props->getTtl()) { - // AMQP requires setting the expiration property to be posix - // time_t in seconds. TTL is in milliseconds - if (!props->getExpiration()) { - //only set expiration in delivery properties if not already set - time_t now = ::time(0); - props->setExpiration(now + (props->getTtl()/1000)); - } - // Use higher resolution time for the internal expiry calculation. - Duration ttl(std::min(props->getTtl() * TIME_MSEC, (uint64_t) std::numeric_limits<int64_t>::max()));//Prevent overflow - expiration = AbsTime(AbsTime::now(), ttl); - setExpiryPolicy(e); - } -} - -void Message::adjustTtl() -{ - DeliveryProperties* props = getProperties<DeliveryProperties>(); - if (props->getTtl()) { - sys::Mutex::ScopedLock l(lock); - if (expiration < FAR_FUTURE) { - sys::Duration d(sys::AbsTime::now(), getExpiration()); - props->setTtl(int64_t(d) > 0 ? int64_t(d)/1000000 : 1); // convert from ns to ms; set to 1 if expired - } - } -} - -void Message::setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e) { - expiryPolicy = e; - if (expiryPolicy) - expiryPolicy->willExpire(*this); -} - -bool Message::hasExpired() -{ - return expiryPolicy && expiryPolicy->hasExpired(*this); -} - -namespace { -struct ScopedSet { - sys::Monitor& lock; - bool& flag; - ScopedSet(sys::Monitor& l, bool& f) : lock(l), flag(f) { - sys::Monitor::ScopedLock sl(lock); - flag = true; - } - ~ScopedSet(){ - sys::Monitor::ScopedLock sl(lock); - flag = false; - lock.notifyAll(); - } -}; -} - -void Message::allDequeuesComplete() { - ScopedSet ss(callbackLock, inCallback); - MessageCallback* cb = dequeueCallback; - if (cb && *cb) (*cb)(intrusive_ptr<Message>(this)); -} - -void Message::setDequeueCompleteCallback(MessageCallback& cb) { - sys::Mutex::ScopedLock l(callbackLock); - while (inCallback) callbackLock.wait(); - dequeueCallback = &cb; -} - -void Message::resetDequeueCompleteCallback() { - sys::Mutex::ScopedLock l(callbackLock); - while (inCallback) callbackLock.wait(); - dequeueCallback = 0; -} - -uint8_t Message::getPriority() const { - return getAdapter().getPriority(frames); -} - -framing::FieldTable& Message::getOrInsertHeaders() -{ - return getProperties<MessageProperties>()->getApplicationHeaders(); -} - -bool Message::getIsManagementMessage() const { return isManagementMessage; } -void Message::setIsManagementMessage(bool b) { isManagementMessage = b; } - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/Message.h b/cpp/src/qpid/broker/Message.h deleted file mode 100644 index d85ee434db..0000000000 --- a/cpp/src/qpid/broker/Message.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef _broker_Message_h -#define _broker_Message_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/PersistableMessage.h" -#include "qpid/broker/MessageAdapter.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Time.h" -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include <string> -#include <vector> - -namespace qpid { - -namespace framing { -class FieldTable; -class SequenceNumber; -} - -namespace broker { -class ConnectionToken; -class Exchange; -class ExchangeRegistry; -class MessageStore; -class Queue; -class ExpiryPolicy; - -class Message : public PersistableMessage { -public: - typedef boost::function<void (const boost::intrusive_ptr<Message>&)> MessageCallback; - - QPID_BROKER_EXTERN Message(const framing::SequenceNumber& id = framing::SequenceNumber()); - QPID_BROKER_EXTERN Message(const Message&); - QPID_BROKER_EXTERN ~Message(); - - uint64_t getPersistenceId() const { return persistenceId; } - void setPersistenceId(uint64_t _persistenceId) const { persistenceId = _persistenceId; } - - bool getRedelivered() const { return redelivered; } - void redeliver() { redelivered = true; } - - const ConnectionToken* getPublisher() const { return publisher; } - void setPublisher(ConnectionToken* p) { publisher = p; } - - const framing::SequenceNumber& getCommandId() { return frames.getId(); } - - QPID_BROKER_EXTERN uint64_t contentSize() const; - - QPID_BROKER_EXTERN std::string getRoutingKey() const; - const boost::shared_ptr<Exchange> getExchange(ExchangeRegistry&) const; - QPID_BROKER_EXTERN std::string getExchangeName() const; - bool isImmediate() const; - QPID_BROKER_EXTERN const framing::FieldTable* getApplicationHeaders() const; - QPID_BROKER_EXTERN std::string getAppId() const; - framing::FieldTable& getOrInsertHeaders(); - QPID_BROKER_EXTERN bool isPersistent() const; - bool requiresAccept(); - - QPID_BROKER_EXTERN void setTimestamp(const boost::intrusive_ptr<ExpiryPolicy>& e); - void setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e); - bool hasExpired(); - sys::AbsTime getExpiration() const { return expiration; } - void adjustTtl(); - - framing::FrameSet& getFrames() { return frames; } - const framing::FrameSet& getFrames() const { return frames; } - - template <class T> T* getProperties() { - qpid::framing::AMQHeaderBody* p = frames.getHeaders(); - return p->get<T>(true); - } - - template <class T> const T* getProperties() const { - const qpid::framing::AMQHeaderBody* p = frames.getHeaders(); - return p->get<T>(true); - } - - template <class T> const T* hasProperties() const { - const qpid::framing::AMQHeaderBody* p = frames.getHeaders(); - return p->get<T>(); - } - - template <class T> const T* getMethod() const { - return frames.as<T>(); - } - - template <class T> T* getMethod() { - return frames.as<T>(); - } - - template <class T> bool isA() const { - return frames.isA<T>(); - } - - uint32_t getRequiredCredit(); - - void encode(framing::Buffer& buffer) const; - void encodeContent(framing::Buffer& buffer) const; - - /** - * @returns the size of the buffer needed to encode this - * message in its entirety - */ - uint32_t encodedSize() const; - /** - * @returns the size of the buffer needed to encode the - * 'header' of this message (not just the header frame, - * but other meta data e.g.routing key and exchange) - */ - uint32_t encodedHeaderSize() const; - uint32_t encodedContentSize() const; - - QPID_BROKER_EXTERN void decodeHeader(framing::Buffer& buffer); - QPID_BROKER_EXTERN void decodeContent(framing::Buffer& buffer); - - void QPID_BROKER_EXTERN tryReleaseContent(); - void releaseContent(); - void releaseContent(MessageStore* s);//deprecated, use 'setStore(store); releaseContent();' instead - void destroy(); - - bool getContentFrame(const Queue& queue, framing::AMQFrame& frame, uint16_t maxContentSize, uint64_t offset) const; - QPID_BROKER_EXTERN void sendContent(const Queue& queue, framing::FrameHandler& out, uint16_t maxFrameSize) const; - void sendHeader(framing::FrameHandler& out, uint16_t maxFrameSize) const; - - QPID_BROKER_EXTERN bool isContentLoaded() const; - - bool isExcluded(const std::vector<std::string>& excludes) const; - void addTraceId(const std::string& id); - - void forcePersistent(); - bool isForcedPersistent(); - - - /** Call cb when dequeue is complete, may call immediately. Holds cb by reference. */ - void setDequeueCompleteCallback(MessageCallback& cb); - void resetDequeueCompleteCallback(); - - uint8_t getPriority() const; - bool getIsManagementMessage() const; - void setIsManagementMessage(bool b); - private: - MessageAdapter& getAdapter() const; - void allDequeuesComplete(); - - mutable sys::Mutex lock; - framing::FrameSet frames; - mutable boost::shared_ptr<Exchange> exchange; - mutable uint64_t persistenceId; - bool redelivered; - bool loaded; - bool staged; - bool forcePersistentPolicy; // used to force message as durable, via a broker policy - ConnectionToken* publisher; - mutable MessageAdapter* adapter; - qpid::sys::AbsTime expiration; - boost::intrusive_ptr<ExpiryPolicy> expiryPolicy; - - static TransferAdapter TRANSFER; - - mutable boost::intrusive_ptr<Message> empty; - - sys::Monitor callbackLock; - MessageCallback* dequeueCallback; - bool inCallback; - - uint32_t requiredCredit; - bool isManagementMessage; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/MessageAdapter.cpp b/cpp/src/qpid/broker/MessageAdapter.cpp deleted file mode 100644 index 0eb4a6fa22..0000000000 --- a/cpp/src/qpid/broker/MessageAdapter.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/MessageAdapter.h" - -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/MessageTransferBody.h" - -namespace { - const std::string empty; -} - -namespace qpid { -namespace broker{ - - std::string TransferAdapter::getRoutingKey(const framing::FrameSet& f) - { - const framing::DeliveryProperties* p = f.getHeaders()->get<framing::DeliveryProperties>(); - return p ? p->getRoutingKey() : empty; - } - - std::string TransferAdapter::getExchange(const framing::FrameSet& f) - { - return f.as<framing::MessageTransferBody>()->getDestination(); - } - - bool TransferAdapter::isImmediate(const framing::FrameSet&) - { - //TODO: delete this, immediate is no longer part of the spec - return false; - } - - const framing::FieldTable* TransferAdapter::getApplicationHeaders(const framing::FrameSet& f) - { - const framing::MessageProperties* p = f.getHeaders()->get<framing::MessageProperties>(); - return p ? &(p->getApplicationHeaders()) : 0; - } - - bool TransferAdapter::isPersistent(const framing::FrameSet& f) - { - const framing::DeliveryProperties* p = f.getHeaders()->get<framing::DeliveryProperties>(); - return p && p->getDeliveryMode() == 2; - } - - bool TransferAdapter::requiresAccept(const framing::FrameSet& f) - { - const framing::MessageTransferBody* b = f.as<framing::MessageTransferBody>(); - return b && b->getAcceptMode() == 0/*EXPLICIT == 0*/; - } - - uint8_t TransferAdapter::getPriority(const framing::FrameSet& f) - { - const framing::DeliveryProperties* p = f.getHeaders()->get<framing::DeliveryProperties>(); - return p ? p->getPriority() : 0; - } - - std::string TransferAdapter::getAppId(const framing::FrameSet& f) - { - const framing::MessageProperties* p = f.getHeaders()->get<framing::MessageProperties>(); - return p ? p->getAppId() : empty; - } -}} diff --git a/cpp/src/qpid/broker/MessageAdapter.h b/cpp/src/qpid/broker/MessageAdapter.h deleted file mode 100644 index df50db4063..0000000000 --- a/cpp/src/qpid/broker/MessageAdapter.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _broker_MessageAdapter_h -#define _broker_MessageAdapter_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FrameSet.h" - -namespace qpid { -namespace broker { - -// TODO aconway 2007-11-09: No longer needed, we only have one type of message. -struct MessageAdapter -{ - virtual ~MessageAdapter() {} - - virtual std::string getRoutingKey(const framing::FrameSet& f) = 0; - virtual std::string getExchange(const framing::FrameSet& f) = 0; - virtual bool isImmediate(const framing::FrameSet& f) = 0; - virtual const framing::FieldTable* getApplicationHeaders(const framing::FrameSet& f) = 0; - virtual bool isPersistent(const framing::FrameSet& f) = 0; - virtual bool requiresAccept(const framing::FrameSet& f) = 0; - virtual uint8_t getPriority(const framing::FrameSet& f) = 0; - virtual std::string getAppId(const framing::FrameSet& f) = 0; -}; - -struct TransferAdapter : MessageAdapter -{ - virtual std::string getRoutingKey(const framing::FrameSet& f); - virtual std::string getExchange(const framing::FrameSet& f); - virtual const framing::FieldTable* getApplicationHeaders(const framing::FrameSet& f); - virtual bool isPersistent(const framing::FrameSet& f); - bool isImmediate(const framing::FrameSet&); - bool requiresAccept(const framing::FrameSet& f); - uint8_t getPriority(const framing::FrameSet& f); - virtual std::string getAppId(const framing::FrameSet& f); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/MessageBuilder.cpp b/cpp/src/qpid/broker/MessageBuilder.cpp deleted file mode 100644 index a6d605c296..0000000000 --- a/cpp/src/qpid/broker/MessageBuilder.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/MessageBuilder.h" - -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/reply_exceptions.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; -using namespace qpid::framing; - -namespace -{ - std::string type_str(uint8_t type); - const std::string QPID_MANAGEMENT("qpid.management"); -} - -MessageBuilder::MessageBuilder(MessageStore* const _store) : - state(DORMANT), store(_store) {} - -void MessageBuilder::handle(AMQFrame& frame) -{ - uint8_t type = frame.getBody()->type(); - switch(state) { - case METHOD: - checkType(METHOD_BODY, type); - state = HEADER; - break; - case HEADER: - if (type == CONTENT_BODY) { - //TODO: rethink how to handle non-existent headers(?)... - //didn't get a header: add in a dummy - AMQFrame header((AMQHeaderBody())); - header.setBof(false); - header.setEof(false); - message->getFrames().append(header); - } else if (type != HEADER_BODY) { - throw CommandInvalidException( - QPID_MSG("Invalid frame sequence for message, expected header or content got " - << type_str(type) << ")")); - } - state = CONTENT; - break; - case CONTENT: - checkType(CONTENT_BODY, type); - break; - default: - throw CommandInvalidException(QPID_MSG("Invalid frame sequence for message (state=" << state << ")")); - } - message->getFrames().append(frame); -} - -void MessageBuilder::end() -{ - message = 0; - state = DORMANT; -} - -void MessageBuilder::start(const SequenceNumber& id) -{ - message = intrusive_ptr<Message>(new Message(id)); - message->setStore(store); - state = METHOD; -} - -namespace { - -const std::string HEADER_BODY_S = "HEADER"; -const std::string METHOD_BODY_S = "METHOD"; -const std::string CONTENT_BODY_S = "CONTENT"; -const std::string HEARTBEAT_BODY_S = "HEARTBEAT"; -const std::string UNKNOWN = "unknown"; - -std::string type_str(uint8_t type) -{ - switch(type) { - case METHOD_BODY: return METHOD_BODY_S; - case HEADER_BODY: return HEADER_BODY_S; - case CONTENT_BODY: return CONTENT_BODY_S; - case HEARTBEAT_BODY: return HEARTBEAT_BODY_S; - } - return UNKNOWN; -} - -} - -void MessageBuilder::checkType(uint8_t expected, uint8_t actual) -{ - if (expected != actual) { - throw CommandInvalidException(QPID_MSG("Invalid frame sequence for message (expected " - << type_str(expected) << " got " << type_str(actual) << ")")); - } -} diff --git a/cpp/src/qpid/broker/MessageBuilder.h b/cpp/src/qpid/broker/MessageBuilder.h deleted file mode 100644 index b99b8efee6..0000000000 --- a/cpp/src/qpid/broker/MessageBuilder.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _MessageBuilder_ -#define _MessageBuilder_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/RefCounted.h" - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - namespace broker { - class Message; - class MessageStore; - - class QPID_BROKER_CLASS_EXTERN MessageBuilder : public framing::FrameHandler{ - public: - QPID_BROKER_EXTERN MessageBuilder(MessageStore* const store); - QPID_BROKER_EXTERN void handle(framing::AMQFrame& frame); - boost::intrusive_ptr<Message> getMessage() { return message; } - QPID_BROKER_EXTERN void start(const framing::SequenceNumber& id); - void end(); - private: - enum State {DORMANT, METHOD, HEADER, CONTENT}; - State state; - boost::intrusive_ptr<Message> message; - MessageStore* const store; - - void checkType(uint8_t expected, uint8_t actual); - }; - } -} - - -#endif - diff --git a/cpp/src/qpid/broker/MessageDeque.cpp b/cpp/src/qpid/broker/MessageDeque.cpp deleted file mode 100644 index 24b8f6f895..0000000000 --- a/cpp/src/qpid/broker/MessageDeque.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/MessageDeque.h" -#include "qpid/broker/QueuedMessage.h" - -namespace qpid { -namespace broker { - -size_t MessageDeque::size() -{ - return messages.size(); -} - -bool MessageDeque::empty() -{ - return messages.empty(); -} - -void MessageDeque::reinsert(const QueuedMessage& message) -{ - messages.insert(lower_bound(messages.begin(), messages.end(), message), message); -} - -MessageDeque::Deque::iterator MessageDeque::seek(const framing::SequenceNumber& position) -{ - if (!messages.empty()) { - QueuedMessage comp; - comp.position = position; - unsigned long diff = position.getValue() - messages.front().position.getValue(); - long maxEnd = diff < messages.size()? diff : messages.size(); - return lower_bound(messages.begin(),messages.begin()+maxEnd,comp); - } else { - return messages.end(); - } -} - -bool MessageDeque::find(const framing::SequenceNumber& position, QueuedMessage& message, bool remove) -{ - Deque::iterator i = seek(position); - if (i != messages.end() && i->position == position) { - message = *i; - if (remove) messages.erase(i); - return true; - } else { - return false; - } -} - -bool MessageDeque::remove(const framing::SequenceNumber& position, QueuedMessage& message) -{ - return find(position, message, true); -} - -bool MessageDeque::find(const framing::SequenceNumber& position, QueuedMessage& message) -{ - return find(position, message, false); -} - -bool MessageDeque::next(const framing::SequenceNumber& position, QueuedMessage& message) -{ - if (messages.empty()) { - return false; - } else if (position < front().position) { - message = front(); - return true; - } else { - Deque::iterator i = seek(position+1); - if (i != messages.end()) { - message = *i; - return true; - } else { - return false; - } - } -} - -QueuedMessage& MessageDeque::front() -{ - return messages.front(); -} - -void MessageDeque::pop() -{ - if (!messages.empty()) { - messages.pop_front(); - } -} - -bool MessageDeque::pop(QueuedMessage& out) -{ - if (messages.empty()) { - return false; - } else { - out = front(); - messages.pop_front(); - return true; - } -} - -bool MessageDeque::push(const QueuedMessage& added, QueuedMessage& /*not needed*/) -{ - messages.push_back(added); - return false;//adding a message never causes one to be removed for deque -} - -void MessageDeque::foreach(Functor f) -{ - std::for_each(messages.begin(), messages.end(), f); -} - -void MessageDeque::removeIf(Predicate p) -{ - for (Deque::iterator i = messages.begin(); i != messages.end();) { - if (p(*i)) { - i = messages.erase(i); - } else { - ++i; - } - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/MessageDeque.h b/cpp/src/qpid/broker/MessageDeque.h deleted file mode 100644 index 0e1aef2986..0000000000 --- a/cpp/src/qpid/broker/MessageDeque.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_BROKER_MESSAGEDEQUE_H -#define QPID_BROKER_MESSAGEDEQUE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Messages.h" -#include "qpid/broker/QueuedMessage.h" -#include <deque> - -namespace qpid { -namespace broker { - -/** - * Provides the standard FIFO queue behaviour. - */ -class MessageDeque : public Messages -{ - public: - size_t size(); - bool empty(); - - void reinsert(const QueuedMessage&); - bool remove(const framing::SequenceNumber&, QueuedMessage&); - bool find(const framing::SequenceNumber&, QueuedMessage&); - bool next(const framing::SequenceNumber&, QueuedMessage&); - - QueuedMessage& front(); - void pop(); - bool pop(QueuedMessage&); - bool push(const QueuedMessage& added, QueuedMessage& removed); - - void foreach(Functor); - void removeIf(Predicate); - - private: - typedef std::deque<QueuedMessage> Deque; - Deque messages; - - Deque::iterator seek(const framing::SequenceNumber&); - bool find(const framing::SequenceNumber&, QueuedMessage&, bool remove); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGEDEQUE_H*/ diff --git a/cpp/src/qpid/broker/MessageMap.cpp b/cpp/src/qpid/broker/MessageMap.cpp deleted file mode 100644 index 39e23df533..0000000000 --- a/cpp/src/qpid/broker/MessageMap.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/MessageMap.h" -#include "qpid/broker/QueuedMessage.h" - -namespace qpid { -namespace broker { -namespace { -const std::string EMPTY; -} - -std::string MessageMap::getKey(const QueuedMessage& message) -{ - const framing::FieldTable* ft = message.payload->getApplicationHeaders(); - if (ft) return ft->getAsString(key); - else return EMPTY; -} - -size_t MessageMap::size() -{ - return messages.size(); -} - -bool MessageMap::empty() -{ - return messages.empty(); -} - -void MessageMap::reinsert(const QueuedMessage& message) -{ - std::string key = getKey(message); - Index::iterator i = index.find(key); - if (i == index.end()) { - index[key] = message; - messages[message.position] = message; - } //else message has already been replaced -} - -bool MessageMap::remove(const framing::SequenceNumber& position, QueuedMessage& message) -{ - Ordering::iterator i = messages.find(position); - if (i != messages.end()) { - message = i->second; - erase(i); - return true; - } else { - return false; - } -} - -bool MessageMap::find(const framing::SequenceNumber& position, QueuedMessage& message) -{ - Ordering::iterator i = messages.find(position); - if (i != messages.end()) { - message = i->second; - return true; - } else { - return false; - } -} - -bool MessageMap::next(const framing::SequenceNumber& position, QueuedMessage& message) -{ - if (!messages.empty() && position < front().position) { - message = front(); - return true; - } else { - Ordering::iterator i = messages.lower_bound(position+1); - if (i != messages.end()) { - message = i->second; - return true; - } else { - return false; - } - } -} - -QueuedMessage& MessageMap::front() -{ - return messages.begin()->second; -} - -void MessageMap::pop() -{ - QueuedMessage dummy; - pop(dummy); -} - -bool MessageMap::pop(QueuedMessage& out) -{ - Ordering::iterator i = messages.begin(); - if (i != messages.end()) { - out = i->second; - erase(i); - return true; - } else { - return false; - } -} - -const QueuedMessage& MessageMap::replace(const QueuedMessage& original, const QueuedMessage& update) -{ - messages.erase(original.position); - messages[update.position] = update; - return update; -} - -bool MessageMap::push(const QueuedMessage& added, QueuedMessage& removed) -{ - std::pair<Index::iterator, bool> result = index.insert(Index::value_type(getKey(added), added)); - if (result.second) { - //there was no previous message for this key; nothing needs to - //be removed, just add the message into its correct position - messages[added.position] = added; - return false; - } else { - //there is already a message with that key which needs to be replaced - removed = result.first->second; - result.first->second = replace(result.first->second, added); - return true; - } -} - -void MessageMap::foreach(Functor f) -{ - for (Ordering::iterator i = messages.begin(); i != messages.end(); ++i) { - f(i->second); - } -} - -void MessageMap::removeIf(Predicate p) -{ - for (Ordering::iterator i = messages.begin(); i != messages.end(); i++) { - if (p(i->second)) { - erase(i); - } - } -} - -void MessageMap::erase(Ordering::iterator i) -{ - index.erase(getKey(i->second)); - messages.erase(i); -} - -MessageMap::MessageMap(const std::string& k) : key(k) {} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/MessageMap.h b/cpp/src/qpid/broker/MessageMap.h deleted file mode 100644 index 1128a1d54a..0000000000 --- a/cpp/src/qpid/broker/MessageMap.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef QPID_BROKER_MESSAGEMAP_H -#define QPID_BROKER_MESSAGEMAP_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Messages.h" -#include "qpid/framing/SequenceNumber.h" -#include <map> -#include <string> - -namespace qpid { -namespace broker { - -/** - * Provides a last value queue behaviour, whereby a messages replace - * any previous message with the same value for a defined property - * (i.e. the key). - */ -class MessageMap : public Messages -{ - public: - MessageMap(const std::string& key); - virtual ~MessageMap() {} - - size_t size(); - bool empty(); - - void reinsert(const QueuedMessage&); - virtual bool remove(const framing::SequenceNumber&, QueuedMessage&); - bool find(const framing::SequenceNumber&, QueuedMessage&); - virtual bool next(const framing::SequenceNumber&, QueuedMessage&); - - QueuedMessage& front(); - void pop(); - bool pop(QueuedMessage&); - virtual bool push(const QueuedMessage& added, QueuedMessage& removed); - - void foreach(Functor); - virtual void removeIf(Predicate); - - protected: - typedef std::map<std::string, QueuedMessage> Index; - typedef std::map<framing::SequenceNumber, QueuedMessage> Ordering; - const std::string key; - Index index; - Ordering messages; - - std::string getKey(const QueuedMessage&); - virtual const QueuedMessage& replace(const QueuedMessage&, const QueuedMessage&); - void erase(Ordering::iterator); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGEMAP_H*/ diff --git a/cpp/src/qpid/broker/MessageStore.h b/cpp/src/qpid/broker/MessageStore.h deleted file mode 100644 index ab0225ef6b..0000000000 --- a/cpp/src/qpid/broker/MessageStore.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _MessageStore_ -#define _MessageStore_ - -#include "qpid/broker/PersistableExchange.h" -#include "qpid/broker/PersistableMessage.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/broker/PersistableConfig.h" -#include "qpid/broker/RecoveryManager.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/framing/FieldTable.h" - -#include <qpid/Options.h> - -#include <boost/shared_ptr.hpp> -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * An abstraction of the persistent storage for messages. (In - * all methods, any pointers/references to queues or messages - * are valid only for the duration of the call). - */ -class MessageStore : public TransactionalStore, public Recoverable { - public: - - /** - * If called after initialization but before recovery, will discard the database - * content and reinitialize as though it were a new installation. If the parameter - * saveStoreContent is true, the content of the store will be saved in such a way - * that the truncate can be reversed. This is used when cluster nodes recover and - * must get their content from a cluster sync rather than directly from the store. - * - * @param saveStoreContent If true, will move content of the store to a backup - * location where they may be restored later if needed. It is - * not necessary to save more than one prior version of the - * store. - */ - virtual void truncateInit(const bool saveStoreContent = false) = 0; - - /** - * Record the existence of a durable queue - */ - virtual void create(PersistableQueue& queue, - const framing::FieldTable& args) = 0; - /** - * Destroy a durable queue - */ - virtual void destroy(PersistableQueue& queue) = 0; - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange, - const framing::FieldTable& args) = 0; - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange) = 0; - - /** - * Record a binding - */ - virtual void bind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args) = 0; - - /** - * Forget a binding - */ - virtual void unbind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args) = 0; - - /** - * Record generic durable configuration - */ - virtual void create(const PersistableConfig& config) = 0; - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const PersistableConfig& config) = 0; - - /** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr<PersistableMessage>& msg) = 0; - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(PersistableMessage& msg) = 0; - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const std::string& data) = 0; - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr<const PersistableMessage>& msg, - std::string& data, uint64_t offset, uint32_t length) = 0; - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) = 0; - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) = 0; - - /** - * Flushes all async messages to disk for the specified queue - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const qpid::broker::PersistableQueue& queue)=0; - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue) = 0; - - - virtual ~MessageStore(){} -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/MessageStoreModule.cpp b/cpp/src/qpid/broker/MessageStoreModule.cpp deleted file mode 100644 index cd9fd4c933..0000000000 --- a/cpp/src/qpid/broker/MessageStoreModule.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/MessageStoreModule.h" -#include "qpid/broker/NullMessageStore.h" -#include <iostream> - -// This transfer protects against the unloading of the store lib prior to the handling of the exception -#define TRANSFER_EXCEPTION(fn) try { fn; } catch (std::exception& e) { throw Exception(e.what()); } - -using boost::intrusive_ptr; -using qpid::framing::FieldTable; -using std::string; - -namespace qpid { -namespace broker { - -MessageStoreModule::MessageStoreModule(boost::shared_ptr<MessageStore>& _store) - : store(_store) {} - -MessageStoreModule::~MessageStoreModule() -{ -} - -bool MessageStoreModule::init(const Options*) { return true; } - -void MessageStoreModule::truncateInit(const bool pushDownStoreFiles) -{ - TRANSFER_EXCEPTION(store->truncateInit(pushDownStoreFiles)); -} - -void MessageStoreModule::create(PersistableQueue& queue, const FieldTable& args) -{ - TRANSFER_EXCEPTION(store->create(queue, args)); -} - -void MessageStoreModule::destroy(PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->destroy(queue)); -} - -void MessageStoreModule::create(const PersistableExchange& exchange, const FieldTable& args) -{ - TRANSFER_EXCEPTION(store->create(exchange, args)); -} - -void MessageStoreModule::destroy(const PersistableExchange& exchange) -{ - TRANSFER_EXCEPTION(store->destroy(exchange)); -} - -void MessageStoreModule::bind(const PersistableExchange& e, const PersistableQueue& q, - const std::string& k, const framing::FieldTable& a) -{ - TRANSFER_EXCEPTION(store->bind(e, q, k, a)); -} - -void MessageStoreModule::unbind(const PersistableExchange& e, const PersistableQueue& q, - const std::string& k, const framing::FieldTable& a) -{ - TRANSFER_EXCEPTION(store->unbind(e, q, k, a)); -} - -void MessageStoreModule::create(const PersistableConfig& config) -{ - TRANSFER_EXCEPTION(store->create(config)); -} - -void MessageStoreModule::destroy(const PersistableConfig& config) -{ - TRANSFER_EXCEPTION(store->destroy(config)); -} - -void MessageStoreModule::recover(RecoveryManager& registry) -{ - TRANSFER_EXCEPTION(store->recover(registry)); -} - -void MessageStoreModule::stage(const intrusive_ptr<PersistableMessage>& msg) -{ - TRANSFER_EXCEPTION(store->stage(msg)); -} - -void MessageStoreModule::destroy(PersistableMessage& msg) -{ - TRANSFER_EXCEPTION(store->destroy(msg)); -} - -void MessageStoreModule::appendContent(const intrusive_ptr<const PersistableMessage>& msg, - const std::string& data) -{ - TRANSFER_EXCEPTION(store->appendContent(msg, data)); -} - -void MessageStoreModule::loadContent( - const qpid::broker::PersistableQueue& queue, - const intrusive_ptr<const PersistableMessage>& msg, - string& data, uint64_t offset, uint32_t length) -{ - TRANSFER_EXCEPTION(store->loadContent(queue, msg, data, offset, length)); -} - -void MessageStoreModule::enqueue(TransactionContext* ctxt, - const intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->enqueue(ctxt, msg, queue)); -} - -void MessageStoreModule::dequeue(TransactionContext* ctxt, - const intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->dequeue(ctxt, msg, queue)); -} - -void MessageStoreModule::flush(const qpid::broker::PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->flush(queue)); -} - -uint32_t MessageStoreModule::outstandingQueueAIO(const PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(return store->outstandingQueueAIO(queue)); -} - -std::auto_ptr<TransactionContext> MessageStoreModule::begin() -{ - TRANSFER_EXCEPTION(return store->begin()); -} - -std::auto_ptr<TPCTransactionContext> MessageStoreModule::begin(const std::string& xid) -{ - TRANSFER_EXCEPTION(return store->begin(xid)); -} - -void MessageStoreModule::prepare(TPCTransactionContext& txn) -{ - TRANSFER_EXCEPTION(store->prepare(txn)); -} - -void MessageStoreModule::commit(TransactionContext& ctxt) -{ - TRANSFER_EXCEPTION(store->commit(ctxt)); -} - -void MessageStoreModule::abort(TransactionContext& ctxt) -{ - TRANSFER_EXCEPTION(store->abort(ctxt)); -} - -void MessageStoreModule::collectPreparedXids(std::set<std::string>& xids) -{ - TRANSFER_EXCEPTION(store->collectPreparedXids(xids)); -} - -bool MessageStoreModule::isNull() const -{ - return NullMessageStore::isNullStore(store.get()); -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/MessageStoreModule.h b/cpp/src/qpid/broker/MessageStoreModule.h deleted file mode 100644 index 56b5a3c1ae..0000000000 --- a/cpp/src/qpid/broker/MessageStoreModule.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _MessageStoreModule_ -#define _MessageStoreModule_ - -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/RecoveryManager.h" - -#include <boost/intrusive_ptr.hpp> -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * A null implementation of the MessageStore interface - */ -class MessageStoreModule : public MessageStore -{ - boost::shared_ptr<MessageStore> store; - public: - MessageStoreModule(boost::shared_ptr<MessageStore>& store); - - bool init(const Options* options); - void truncateInit(const bool pushDownStoreFiles = false); - std::auto_ptr<TransactionContext> begin(); - std::auto_ptr<TPCTransactionContext> begin(const std::string& xid); - void prepare(TPCTransactionContext& txn); - void commit(TransactionContext& txn); - void abort(TransactionContext& txn); - void collectPreparedXids(std::set<std::string>& xids); - - void create(PersistableQueue& queue, const framing::FieldTable& args); - void destroy(PersistableQueue& queue); - void create(const PersistableExchange& exchange, const framing::FieldTable& args); - void destroy(const PersistableExchange& exchange); - void bind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args); - void unbind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args); - void create(const PersistableConfig& config); - void destroy(const PersistableConfig& config); - void recover(RecoveryManager& queues); - void stage(const boost::intrusive_ptr<PersistableMessage>& msg); - void destroy(PersistableMessage& msg); - void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, const std::string& data); - void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr<const PersistableMessage>& msg, std::string& data, - uint64_t offset, uint32_t length); - - void enqueue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - void dequeue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - uint32_t outstandingQueueAIO(const PersistableQueue& queue); - void flush(const qpid::broker::PersistableQueue& queue); - bool isNull() const; - - ~MessageStoreModule(); -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/Messages.h b/cpp/src/qpid/broker/Messages.h deleted file mode 100644 index 0d75417640..0000000000 --- a/cpp/src/qpid/broker/Messages.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef QPID_BROKER_MESSAGES_H -#define QPID_BROKER_MESSAGES_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <boost/function.hpp> - -namespace qpid { -namespace framing { -class SequenceNumber; -} -namespace broker { -struct QueuedMessage; - -/** - * This interface abstracts out the access to the messages held for - * delivery by a Queue instance. - */ -class Messages -{ - public: - typedef boost::function1<void, QueuedMessage&> Functor; - typedef boost::function1<bool, QueuedMessage&> Predicate; - - virtual ~Messages() {} - /** - * @return the number of messages available for delivery. - */ - virtual size_t size() = 0; - /** - * @return true if there are no messages for delivery, false otherwise - */ - virtual bool empty() = 0; - - /** - * Re-inserts a message back into its original position - used - * when requeing released messages. - */ - virtual void reinsert(const QueuedMessage&) = 0; - /** - * Remove the message at the specified position, returning true if - * found, false otherwise. The removed message is passed back via - * the second parameter. - */ - virtual bool remove(const framing::SequenceNumber&, QueuedMessage&) = 0; - /** - * Find the message at the specified position, returning true if - * found, false otherwise. The matched message is passed back via - * the second parameter. - */ - virtual bool find(const framing::SequenceNumber&, QueuedMessage&) = 0; - /** - * Return the next message to be given to a browsing subscrption - * that has reached the specified poisition. The next messages is - * passed back via the second parameter. - * - * @return true if there is another message, false otherwise. - */ - virtual bool next(const framing::SequenceNumber&, QueuedMessage&) = 0; - - /** - * Note: Caller is responsible for ensuring that there is a front - * (e.g. empty() returns false) - * - * @return the next message to be delivered - */ - virtual QueuedMessage& front() = 0; - /** - * Removes the front message - */ - virtual void pop() = 0; - /** - * @return true if there is a mesage to be delivered - in which - * case that message will be returned via the parameter and - * removed - otherwise false. - */ - virtual bool pop(QueuedMessage&) = 0; - /** - * Pushes a message to the back of the 'queue'. For some types of - * queue this may cause another message to be removed; if that is - * the case the method will return true and the removed message - * will be passed out via the second parameter. - */ - virtual bool push(const QueuedMessage& added, QueuedMessage& removed) = 0; - - /** - * Apply the functor to each message held - */ - virtual void foreach(Functor) = 0; - /** - * Remove every message held that for which the specified - * predicate returns true - */ - virtual void removeIf(Predicate) = 0; - private: -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGES_H*/ diff --git a/cpp/src/qpid/broker/NameGenerator.cpp b/cpp/src/qpid/broker/NameGenerator.cpp deleted file mode 100644 index e7f193d546..0000000000 --- a/cpp/src/qpid/broker/NameGenerator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/NameGenerator.h" -#include <sstream> - -using namespace qpid::broker; - -NameGenerator::NameGenerator(const std::string& _base) : base(_base), counter(1) {} - -std::string NameGenerator::generate(){ - std::stringstream ss; - ss << base << counter++; - return ss.str(); -} diff --git a/cpp/src/qpid/broker/NameGenerator.h b/cpp/src/qpid/broker/NameGenerator.h deleted file mode 100644 index 6ea25c9797..0000000000 --- a/cpp/src/qpid/broker/NameGenerator.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _NameGenerator_ -#define _NameGenerator_ - -#include <string> - -namespace qpid { - namespace broker { - class NameGenerator{ - const std::string base; - unsigned int counter; - public: - NameGenerator(const std::string& base); - std::string generate(); - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/NullMessageStore.cpp b/cpp/src/qpid/broker/NullMessageStore.cpp deleted file mode 100644 index 43f600eaf1..0000000000 --- a/cpp/src/qpid/broker/NullMessageStore.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/MessageStoreModule.h" -#include "qpid/broker/RecoveryManager.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" - -#include <iostream> - -using boost::intrusive_ptr; - -namespace qpid{ -namespace broker{ - -const std::string nullxid = ""; - -class SimpleDummyCtxt : public TransactionContext {}; - -class DummyCtxt : public TPCTransactionContext -{ - const std::string xid; -public: - DummyCtxt(const std::string& _xid) : xid(_xid) {} - static std::string getXid(TransactionContext& ctxt) - { - DummyCtxt* c(dynamic_cast<DummyCtxt*>(&ctxt)); - return c ? c->xid : nullxid; - } -}; - -NullMessageStore::NullMessageStore() : nextPersistenceId(1) {} - -bool NullMessageStore::init(const Options* /*options*/) {return true;} - -void NullMessageStore::truncateInit(const bool /*pushDownStoreFiles*/) {} - -void NullMessageStore::create(PersistableQueue& queue, const framing::FieldTable& /*args*/) -{ - queue.setPersistenceId(nextPersistenceId++); -} - -void NullMessageStore::destroy(PersistableQueue&) {} - -void NullMessageStore::create(const PersistableExchange& exchange, const framing::FieldTable& /*args*/) -{ - exchange.setPersistenceId(nextPersistenceId++); -} - -void NullMessageStore::destroy(const PersistableExchange& ) {} - -void NullMessageStore::bind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&){} - -void NullMessageStore::unbind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&){} - -void NullMessageStore::create(const PersistableConfig& config) -{ - config.setPersistenceId(nextPersistenceId++); -} - -void NullMessageStore::destroy(const PersistableConfig&) {} - -void NullMessageStore::recover(RecoveryManager&) {} - -void NullMessageStore::stage(const intrusive_ptr<PersistableMessage>&) {} - -void NullMessageStore::destroy(PersistableMessage&) {} - -void NullMessageStore::appendContent(const intrusive_ptr<const PersistableMessage>&, const std::string&) {} - -void NullMessageStore::loadContent(const qpid::broker::PersistableQueue&, - const intrusive_ptr<const PersistableMessage>&, - std::string&, uint64_t, uint32_t) -{ - throw qpid::framing::InternalErrorException("Can't load content; persistence not enabled"); -} - -void NullMessageStore::enqueue(TransactionContext*, - const intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue&) -{ - msg->enqueueComplete(); -} - -void NullMessageStore::dequeue(TransactionContext*, - const intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue&) -{ - msg->dequeueComplete(); -} - -void NullMessageStore::flush(const qpid::broker::PersistableQueue&) {} - -uint32_t NullMessageStore::outstandingQueueAIO(const PersistableQueue& ) { - return 0; -} - -std::auto_ptr<TransactionContext> NullMessageStore::begin() -{ - return std::auto_ptr<TransactionContext>(new SimpleDummyCtxt()); -} - -std::auto_ptr<TPCTransactionContext> NullMessageStore::begin(const std::string& xid) -{ - return std::auto_ptr<TPCTransactionContext>(new DummyCtxt(xid)); -} - -void NullMessageStore::prepare(TPCTransactionContext& ctxt) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock); - prepared.insert(DummyCtxt::getXid(ctxt)); -} - -void NullMessageStore::commit(TransactionContext& ctxt) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock); - prepared.erase(DummyCtxt::getXid(ctxt)); -} - -void NullMessageStore::abort(TransactionContext& ctxt) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock); - prepared.erase(DummyCtxt::getXid(ctxt)); -} - -void NullMessageStore::collectPreparedXids(std::set<std::string>& out) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock); - out.insert(prepared.begin(), prepared.end()); -} - -bool NullMessageStore::isNull() const -{ - return true; -} - -bool NullMessageStore::isNullStore(const MessageStore* store) -{ - const MessageStoreModule* wrapper = dynamic_cast<const MessageStoreModule*>(store); - if (wrapper) { - return wrapper->isNull(); - } else { - const NullMessageStore* test = dynamic_cast<const NullMessageStore*>(store); - return test && test->isNull(); - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/NullMessageStore.h b/cpp/src/qpid/broker/NullMessageStore.h deleted file mode 100644 index c6f402662e..0000000000 --- a/cpp/src/qpid/broker/NullMessageStore.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _NullMessageStore_ -#define _NullMessageStore_ - -#include <set> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/Queue.h" -#include "qpid/sys/Mutex.h" - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * A null implementation of the MessageStore interface - */ -class QPID_BROKER_CLASS_EXTERN NullMessageStore : public MessageStore -{ - std::set<std::string> prepared; - uint64_t nextPersistenceId; - qpid::sys::Mutex lock; - public: - QPID_BROKER_EXTERN NullMessageStore(); - - QPID_BROKER_EXTERN virtual bool init(const Options* options); - QPID_BROKER_EXTERN virtual void truncateInit(const bool pushDownStoreFiles = false); - QPID_BROKER_EXTERN virtual std::auto_ptr<TransactionContext> begin(); - QPID_BROKER_EXTERN virtual std::auto_ptr<TPCTransactionContext> begin(const std::string& xid); - QPID_BROKER_EXTERN virtual void prepare(TPCTransactionContext& txn); - QPID_BROKER_EXTERN virtual void commit(TransactionContext& txn); - QPID_BROKER_EXTERN virtual void abort(TransactionContext& txn); - QPID_BROKER_EXTERN virtual void collectPreparedXids(std::set<std::string>& xids); - - QPID_BROKER_EXTERN virtual void create(PersistableQueue& queue, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void destroy(PersistableQueue& queue); - QPID_BROKER_EXTERN virtual void create(const PersistableExchange& exchange, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void destroy(const PersistableExchange& exchange); - - QPID_BROKER_EXTERN virtual void bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void create(const PersistableConfig& config); - QPID_BROKER_EXTERN virtual void destroy(const PersistableConfig& config); - QPID_BROKER_EXTERN virtual void recover(RecoveryManager& queues); - QPID_BROKER_EXTERN virtual void stage(const boost::intrusive_ptr<PersistableMessage>& msg); - QPID_BROKER_EXTERN virtual void destroy(PersistableMessage& msg); - QPID_BROKER_EXTERN virtual void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const std::string& data); - QPID_BROKER_EXTERN virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr<const PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length); - QPID_BROKER_EXTERN virtual void enqueue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - QPID_BROKER_EXTERN virtual void dequeue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - QPID_BROKER_EXTERN virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue); - QPID_BROKER_EXTERN virtual void flush(const qpid::broker::PersistableQueue& queue); - ~NullMessageStore(){} - - QPID_BROKER_EXTERN virtual bool isNull() const; - static bool isNullStore(const MessageStore*); -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/OwnershipToken.h b/cpp/src/qpid/broker/OwnershipToken.h deleted file mode 100644 index effd2f5b3c..0000000000 --- a/cpp/src/qpid/broker/OwnershipToken.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _OwnershipToken_ -#define _OwnershipToken_ - -namespace qpid { -namespace broker { - -class ConnectionToken; - -class OwnershipToken{ -public: - virtual bool isLocal(const ConnectionToken* t) const = 0; - virtual ~OwnershipToken(){} -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/Persistable.h b/cpp/src/qpid/broker/Persistable.h deleted file mode 100644 index 36499c7a1a..0000000000 --- a/cpp/src/qpid/broker/Persistable.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _broker_Persistable_h -#define _broker_Persistable_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" -#include "qpid/RefCounted.h" - -namespace qpid { -namespace broker { - -/** - * Base class for all persistable objects - */ -class Persistable : public RefCounted -{ -public: - /** - * Allows the store to attach its own identifier to this object - */ - virtual void setPersistenceId(uint64_t id) const = 0; - /** - * Returns any identifier the store may have attached to this - * object - */ - virtual uint64_t getPersistenceId() const = 0; - /** - * Encodes the persistable state of this object into the supplied - * buffer - */ - virtual void encode(framing::Buffer& buffer) const = 0; - /** - * @returns the size of the buffer needed to encode this object - */ - virtual uint32_t encodedSize() const = 0; - - virtual ~Persistable() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PersistableConfig.h b/cpp/src/qpid/broker/PersistableConfig.h deleted file mode 100644 index 8ddb84d129..0000000000 --- a/cpp/src/qpid/broker/PersistableConfig.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _broker_PersistableConfig_h -#define _broker_PersistableConfig_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include "qpid/broker/Persistable.h" - -namespace qpid { -namespace broker { - -/** - * The interface used by general-purpose persistable configuration for - * the message store. - */ -class PersistableConfig : public Persistable -{ -public: - virtual const std::string& getName() const = 0; - virtual ~PersistableConfig() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PersistableExchange.h b/cpp/src/qpid/broker/PersistableExchange.h deleted file mode 100644 index e1a0853247..0000000000 --- a/cpp/src/qpid/broker/PersistableExchange.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _broker_PersistableExchange_h -#define _broker_PersistableExchange_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include "qpid/broker/Persistable.h" - -namespace qpid { -namespace broker { - -/** - * The interface exchanges must expose to the MessageStore in order to be - * persistable. - */ -class PersistableExchange : public Persistable -{ -public: - virtual const std::string& getName() const = 0; - virtual ~PersistableExchange() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PersistableMessage.cpp b/cpp/src/qpid/broker/PersistableMessage.cpp deleted file mode 100644 index 7ba28eb293..0000000000 --- a/cpp/src/qpid/broker/PersistableMessage.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -#include "qpid/broker/PersistableMessage.h" -#include "qpid/broker/MessageStore.h" -#include <iostream> - -using namespace qpid::broker; - -namespace qpid { -namespace broker { - -class MessageStore; - -PersistableMessage::~PersistableMessage() {} - -PersistableMessage::PersistableMessage() : - asyncDequeueCounter(0), - store(0) -{} - -void PersistableMessage::flush() -{ - syncList copy; - { - sys::ScopedLock<sys::Mutex> l(storeLock); - if (store) { - copy = synclist; - } else { - return;//early exit as nothing to do - } - } - for (syncList::iterator i = copy.begin(); i != copy.end(); ++i) { - PersistableQueue::shared_ptr q(i->lock()); - if (q) { - q->flush(); - } - } -} - -void PersistableMessage::setContentReleased() -{ - contentReleaseState.released = true; -} - -bool PersistableMessage::isContentReleased() const -{ - return contentReleaseState.released; -} - - -bool PersistableMessage::isStoredOnQueue(PersistableQueue::shared_ptr queue){ - if (store && (queue->getPersistenceId()!=0)) { - for (syncList::iterator i = synclist.begin(); i != synclist.end(); ++i) { - PersistableQueue::shared_ptr q(i->lock()); - if (q && q->getPersistenceId() == queue->getPersistenceId()) return true; - } - } - return false; -} - - -void PersistableMessage::addToSyncList(PersistableQueue::shared_ptr queue, MessageStore* _store) { - if (_store){ - sys::ScopedLock<sys::Mutex> l(storeLock); - store = _store; - boost::weak_ptr<PersistableQueue> q(queue); - synclist.push_back(q); - } -} - -void PersistableMessage::enqueueAsync(PersistableQueue::shared_ptr queue, MessageStore* _store) { - addToSyncList(queue, _store); - enqueueStart(); -} - -bool PersistableMessage::isDequeueComplete() { - sys::ScopedLock<sys::Mutex> l(asyncDequeueLock); - return asyncDequeueCounter == 0; -} - -void PersistableMessage::dequeueComplete() { - bool notify = false; - { - sys::ScopedLock<sys::Mutex> l(asyncDequeueLock); - if (asyncDequeueCounter > 0) { - if (--asyncDequeueCounter == 0) { - notify = true; - } - } - } - if (notify) allDequeuesComplete(); -} - -void PersistableMessage::dequeueAsync(PersistableQueue::shared_ptr queue, MessageStore* _store) { - if (_store){ - sys::ScopedLock<sys::Mutex> l(storeLock); - store = _store; - boost::weak_ptr<PersistableQueue> q(queue); - synclist.push_back(q); - } - dequeueAsync(); -} - -void PersistableMessage::dequeueAsync() { - sys::ScopedLock<sys::Mutex> l(asyncDequeueLock); - asyncDequeueCounter++; -} - -PersistableMessage::ContentReleaseState::ContentReleaseState() : blocked(false), requested(false), released(false) {} - -void PersistableMessage::setStore(MessageStore* s) -{ - store = s; -} - -void PersistableMessage::requestContentRelease() -{ - contentReleaseState.requested = true; -} -void PersistableMessage::blockContentRelease() -{ - contentReleaseState.blocked = true; -} -bool PersistableMessage::checkContentReleasable() -{ - return contentReleaseState.requested && !contentReleaseState.blocked; -} - -bool PersistableMessage::isContentReleaseBlocked() -{ - return contentReleaseState.blocked; -} - -bool PersistableMessage::isContentReleaseRequested() -{ - return contentReleaseState.requested; -} - -}} - - diff --git a/cpp/src/qpid/broker/PersistableMessage.h b/cpp/src/qpid/broker/PersistableMessage.h deleted file mode 100644 index d29c2c45b4..0000000000 --- a/cpp/src/qpid/broker/PersistableMessage.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef _broker_PersistableMessage_h -#define _broker_PersistableMessage_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include <list> -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Persistable.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/broker/AsyncCompletion.h" - -namespace qpid { -namespace broker { - -class MessageStore; - -/** - * Base class for persistable messages. - */ -class PersistableMessage : public Persistable -{ - typedef std::list< boost::weak_ptr<PersistableQueue> > syncList; - sys::Mutex asyncDequeueLock; - sys::Mutex storeLock; - - /** - * "Ingress" messages == messages sent _to_ the broker. - * Tracks the number of outstanding asynchronous operations that must - * complete before an inbound message can be considered fully received by the - * broker. E.g. all enqueues have completed, the message has been written - * to store, credit has been replenished, etc. Once all outstanding - * operations have completed, the transfer of this message from the client - * may be considered complete. - */ - AsyncCompletion ingressCompletion; - - /** - * Tracks the number of outstanding asynchronous dequeue - * operations. When the message is dequeued asynchronously the - * count is incremented; when that dequeue completes it is - * decremented. Thus when it is 0, there are no outstanding - * dequeues. - */ - int asyncDequeueCounter; - - void dequeueAsync(); - - syncList synclist; - struct ContentReleaseState - { - bool blocked; - bool requested; - bool released; - - ContentReleaseState(); - }; - ContentReleaseState contentReleaseState; - - protected: - /** Called when all dequeues are complete for this message. */ - virtual void allDequeuesComplete() = 0; - - void setContentReleased(); - - MessageStore* store; - - - public: - typedef boost::shared_ptr<PersistableMessage> shared_ptr; - - /** - * @returns the size of the headers when encoded - */ - virtual uint32_t encodedHeaderSize() const = 0; - - virtual ~PersistableMessage(); - - PersistableMessage(); - - void flush(); - - QPID_BROKER_EXTERN bool isContentReleased() const; - - QPID_BROKER_EXTERN void setStore(MessageStore*); - void requestContentRelease(); - void blockContentRelease(); - bool checkContentReleasable(); - bool isContentReleaseBlocked(); - bool isContentReleaseRequested(); - - virtual QPID_BROKER_EXTERN bool isPersistent() const = 0; - - /** track the progress of a message received by the broker - see ingressCompletion above */ - QPID_BROKER_INLINE_EXTERN bool isIngressComplete() { return ingressCompletion.isDone(); } - QPID_BROKER_INLINE_EXTERN AsyncCompletion& getIngressCompletion() { return ingressCompletion; } - - QPID_BROKER_INLINE_EXTERN void enqueueStart() { ingressCompletion.startCompleter(); } - QPID_BROKER_INLINE_EXTERN void enqueueComplete() { ingressCompletion.finishCompleter(); } - - QPID_BROKER_EXTERN void enqueueAsync(PersistableQueue::shared_ptr queue, - MessageStore* _store); - - - QPID_BROKER_EXTERN bool isDequeueComplete(); - - QPID_BROKER_EXTERN void dequeueComplete(); - - QPID_BROKER_EXTERN void dequeueAsync(PersistableQueue::shared_ptr queue, - MessageStore* _store); - - bool isStoredOnQueue(PersistableQueue::shared_ptr queue); - - void addToSyncList(PersistableQueue::shared_ptr queue, MessageStore* _store); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PersistableQueue.h b/cpp/src/qpid/broker/PersistableQueue.h deleted file mode 100644 index 655d26bc74..0000000000 --- a/cpp/src/qpid/broker/PersistableQueue.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _broker_PersistableQueue_h -#define _broker_PersistableQueue_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include "qpid/broker/Persistable.h" -#include "qpid/management/Manageable.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - - -/** -* Empty class to be used by any module that wanted to set an external per queue store into -* persistableQueue -*/ - -class ExternalQueueStore : public management::Manageable -{ -public: - virtual ~ExternalQueueStore() {}; - -}; - - -/** - * The interface queues must expose to the MessageStore in order to be - * persistable. - */ -class PersistableQueue : public Persistable -{ -public: - typedef boost::shared_ptr<PersistableQueue> shared_ptr; - - virtual const std::string& getName() const = 0; - virtual ~PersistableQueue() { - if (externalQueueStore) - delete externalQueueStore; - }; - - virtual void setExternalQueueStore(ExternalQueueStore* inst) = 0; - virtual void flush() = 0; - - inline ExternalQueueStore* getExternalQueueStore() const {return externalQueueStore;}; - - PersistableQueue():externalQueueStore(NULL){ - }; - -protected: - ExternalQueueStore* externalQueueStore; - -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PriorityQueue.cpp b/cpp/src/qpid/broker/PriorityQueue.cpp deleted file mode 100644 index e07e73d323..0000000000 --- a/cpp/src/qpid/broker/PriorityQueue.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/PriorityQueue.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/framing/reply_exceptions.h" -#include <cmath> - -namespace qpid { -namespace broker { - -PriorityQueue::PriorityQueue(int l) : - levels(l), - messages(levels, Deque()), - frontLevel(0), haveFront(false), cached(false) {} - -size_t PriorityQueue::size() -{ - size_t total(0); - for (int i = 0; i < levels; ++i) { - total += messages[i].size(); - } - return total; -} - -bool PriorityQueue::empty() -{ - for (int i = 0; i < levels; ++i) { - if (!messages[i].empty()) return false; - } - return true; -} - -void PriorityQueue::reinsert(const QueuedMessage& message) -{ - uint p = getPriorityLevel(message); - messages[p].insert(lower_bound(messages[p].begin(), messages[p].end(), message), message); - clearCache(); -} - -bool PriorityQueue::find(const framing::SequenceNumber& position, QueuedMessage& message, bool remove) -{ - QueuedMessage comp; - comp.position = position; - for (int i = 0; i < levels; ++i) { - if (!messages[i].empty()) { - unsigned long diff = position.getValue() - messages[i].front().position.getValue(); - long maxEnd = diff < messages[i].size() ? diff : messages[i].size(); - Deque::iterator l = lower_bound(messages[i].begin(),messages[i].begin()+maxEnd,comp); - if (l != messages[i].end() && l->position == position) { - message = *l; - if (remove) { - messages[i].erase(l); - clearCache(); - } - return true; - } - } - } - return false; -} - -bool PriorityQueue::remove(const framing::SequenceNumber& position, QueuedMessage& message) -{ - return find(position, message, true); -} - -bool PriorityQueue::find(const framing::SequenceNumber& position, QueuedMessage& message) -{ - return find(position, message, false); -} - -bool PriorityQueue::next(const framing::SequenceNumber& position, QueuedMessage& message) -{ - QueuedMessage match; - match.position = position+1; - Deque::iterator lowest; - bool found = false; - for (int i = 0; i < levels; ++i) { - Deque::iterator m = lower_bound(messages[i].begin(), messages[i].end(), match); - if (m != messages[i].end()) { - if (m->position == match.position) { - message = *m; - return true; - } else if (!found || m->position < lowest->position) { - lowest = m; - found = true; - } - } - } - if (found) { - message = *lowest; - } - return found; -} - -QueuedMessage& PriorityQueue::front() -{ - if (checkFront()) { - return messages[frontLevel].front(); - } else { - throw qpid::framing::InternalErrorException(QPID_MSG("No message available")); - } -} - -bool PriorityQueue::pop(QueuedMessage& message) -{ - if (checkFront()) { - message = messages[frontLevel].front(); - messages[frontLevel].pop_front(); - clearCache(); - return true; - } else { - return false; - } -} - -void PriorityQueue::pop() -{ - QueuedMessage dummy; - pop(dummy); -} - -bool PriorityQueue::push(const QueuedMessage& added, QueuedMessage& /*not needed*/) -{ - messages[getPriorityLevel(added)].push_back(added); - clearCache(); - return false;//adding a message never causes one to be removed for deque -} - -void PriorityQueue::foreach(Functor f) -{ - for (int i = 0; i < levels; ++i) { - std::for_each(messages[i].begin(), messages[i].end(), f); - } -} - -void PriorityQueue::removeIf(Predicate p) -{ - for (int priority = 0; priority < levels; ++priority) { - for (Deque::iterator i = messages[priority].begin(); i != messages[priority].end();) { - if (p(*i)) { - i = messages[priority].erase(i); - clearCache(); - } else { - ++i; - } - } - } -} - -uint PriorityQueue::getPriorityLevel(const QueuedMessage& m) const -{ - uint priority = m.payload->getPriority(); - //Use AMQP 0-10 approach to mapping priorities to a fixed level - //(see rule priority-level-implementation) - const uint firstLevel = 5 - uint(std::min(5.0, std::ceil((double) levels/2.0))); - if (priority <= firstLevel) return 0; - return std::min(priority - firstLevel, (uint)levels-1); -} - -void PriorityQueue::clearCache() -{ - cached = false; -} - -bool PriorityQueue::findFrontLevel(uint& l, PriorityLevels& m) -{ - for (int p = levels-1; p >= 0; --p) { - if (!m[p].empty()) { - l = p; - return true; - } - } - return false; -} - -bool PriorityQueue::checkFront() -{ - if (!cached) { - haveFront = findFrontLevel(frontLevel, messages); - cached = true; - } - return haveFront; -} - -uint PriorityQueue::getPriority(const QueuedMessage& message) -{ - const PriorityQueue* queue = dynamic_cast<const PriorityQueue*>(&(message.queue->getMessages())); - if (queue) return queue->getPriorityLevel(message); - else return 0; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/PriorityQueue.h b/cpp/src/qpid/broker/PriorityQueue.h deleted file mode 100644 index 4bf9d26a9d..0000000000 --- a/cpp/src/qpid/broker/PriorityQueue.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_BROKER_PRIORITYQUEUE_H -#define QPID_BROKER_PRIORITYQUEUE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Messages.h" -#include "qpid/sys/IntegerTypes.h" -#include <deque> -#include <vector> - -namespace qpid { -namespace broker { - -/** - * Basic priority queue with a configurable number of recognised - * priority levels. This is implemented as a separate deque per - * priority level. Browsing is FIFO not priority order. - */ -class PriorityQueue : public Messages -{ - public: - PriorityQueue(int levels); - virtual ~PriorityQueue() {} - size_t size(); - bool empty(); - - void reinsert(const QueuedMessage&); - bool remove(const framing::SequenceNumber&, QueuedMessage&); - bool find(const framing::SequenceNumber&, QueuedMessage&); - bool next(const framing::SequenceNumber&, QueuedMessage&); - - QueuedMessage& front(); - void pop(); - bool pop(QueuedMessage&); - bool push(const QueuedMessage& added, QueuedMessage& removed); - - void foreach(Functor); - void removeIf(Predicate); - static uint getPriority(const QueuedMessage&); - protected: - typedef std::deque<QueuedMessage> Deque; - typedef std::vector<Deque> PriorityLevels; - virtual bool findFrontLevel(uint& p, PriorityLevels&); - - const int levels; - private: - PriorityLevels messages; - uint frontLevel; - bool haveFront; - bool cached; - - bool find(const framing::SequenceNumber&, QueuedMessage&, bool remove); - uint getPriorityLevel(const QueuedMessage&) const; - void clearCache(); - bool checkFront(); -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_PRIORITYQUEUE_H*/ diff --git a/cpp/src/qpid/broker/Queue.cpp b/cpp/src/qpid/broker/Queue.cpp deleted file mode 100644 index 8efa8be3dc..0000000000 --- a/cpp/src/qpid/broker/Queue.cpp +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueEvents.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Fairshare.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/LegacyLVQ.h" -#include "qpid/broker/MessageDeque.h" -#include "qpid/broker/MessageMap.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/QueueFlowLimit.h" -#include "qpid/broker/ThresholdAlerts.h" - -#include "qpid/StringUtils.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/ClusterSafe.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Time.h" -#include "qmf/org/apache/qpid/broker/ArgsQueuePurge.h" -#include "qmf/org/apache/qpid/broker/ArgsQueueReroute.h" - -#include <iostream> -#include <algorithm> -#include <functional> - -#include <boost/bind.hpp> -#include <boost/intrusive_ptr.hpp> - - -using namespace qpid::broker; -using namespace qpid::sys; -using namespace qpid::framing; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using std::for_each; -using std::mem_fun; -namespace _qmf = qmf::org::apache::qpid::broker; - - -namespace -{ -const std::string qpidMaxSize("qpid.max_size"); -const std::string qpidMaxCount("qpid.max_count"); -const std::string qpidNoLocal("no-local"); -const std::string qpidTraceIdentity("qpid.trace.id"); -const std::string qpidTraceExclude("qpid.trace.exclude"); -const std::string qpidLastValueQueueKey("qpid.last_value_queue_key"); -const std::string qpidLastValueQueue("qpid.last_value_queue"); -const std::string qpidLastValueQueueNoBrowse("qpid.last_value_queue_no_browse"); -const std::string qpidPersistLastNode("qpid.persist_last_node"); -const std::string qpidVQMatchProperty("qpid.LVQ_key"); -const std::string qpidQueueEventGeneration("qpid.queue_event_generation"); -const std::string qpidAutoDeleteTimeout("qpid.auto_delete_timeout"); -//following feature is not ready for general use as it doesn't handle -//the case where a message is enqueued on more than one queue well enough: -const std::string qpidInsertSequenceNumbers("qpid.insert_sequence_numbers"); - -const int ENQUEUE_ONLY=1; -const int ENQUEUE_AND_DEQUEUE=2; -} - -Queue::Queue(const string& _name, bool _autodelete, - MessageStore* const _store, - const OwnershipToken* const _owner, - Manageable* parent, - Broker* b) : - - name(_name), - autodelete(_autodelete), - store(_store), - owner(_owner), - consumerCount(0), - exclusive(0), - noLocal(false), - persistLastNode(false), - inLastNodeFailure(false), - messages(new MessageDeque()), - persistenceId(0), - policyExceeded(false), - mgmtObject(0), - eventMode(0), - insertSeqNo(0), - broker(b), - deleted(false), - barrier(*this), - autoDeleteTimeout(0) -{ - if (parent != 0 && broker != 0) { - ManagementAgent* agent = broker->getManagementAgent(); - - if (agent != 0) { - mgmtObject = new _qmf::Queue(agent, this, parent, _name, _store != 0, _autodelete, _owner != 0); - agent->addObject(mgmtObject, 0, store != 0); - } - } -} - -Queue::~Queue() -{ - if (mgmtObject != 0) - mgmtObject->resourceDestroy(); -} - -bool isLocalTo(const OwnershipToken* token, boost::intrusive_ptr<Message>& msg) -{ - return token && token->isLocal(msg->getPublisher()); -} - -bool Queue::isLocal(boost::intrusive_ptr<Message>& msg) -{ - //message is considered local if it was published on the same - //connection as that of the session which declared this queue - //exclusive (owner) or which has an exclusive subscription - //(exclusive) - return noLocal && (isLocalTo(owner, msg) || isLocalTo(exclusive, msg)); -} - -bool Queue::isExcluded(boost::intrusive_ptr<Message>& msg) -{ - return traceExclude.size() && msg->isExcluded(traceExclude); -} - -void Queue::deliver(boost::intrusive_ptr<Message> msg){ - // Check for deferred delivery in a cluster. - if (broker && broker->deferDelivery(name, msg)) - return; - if (msg->isImmediate() && getConsumerCount() == 0) { - if (alternateExchange) { - DeliverableMessage deliverable(msg); - alternateExchange->route(deliverable, msg->getRoutingKey(), msg->getApplicationHeaders()); - } - } else if (isLocal(msg)) { - //drop message - QPID_LOG(info, "Dropping 'local' message from " << getName()); - } else if (isExcluded(msg)) { - //drop message - QPID_LOG(info, "Dropping excluded message from " << getName()); - } else { - enqueue(0, msg); - push(msg); - QPID_LOG(debug, "Message " << msg << " enqueued on " << name); - } -} - -void Queue::recoverPrepared(boost::intrusive_ptr<Message>& msg) -{ - if (policy.get()) policy->recoverEnqueued(msg); -} - -void Queue::recover(boost::intrusive_ptr<Message>& msg){ - if (policy.get()) policy->recoverEnqueued(msg); - - push(msg, true); - if (store){ - // setup synclist for recovered messages, so they don't get re-stored on lastNodeFailure - msg->addToSyncList(shared_from_this(), store); - } - - if (store && (!msg->isContentLoaded() || msg->checkContentReleasable())) { - //content has not been loaded, need to ensure that lazy loading mode is set: - //TODO: find a nicer way to do this - msg->releaseContent(store); - // NOTE: The log message in this section are used for flow-to-disk testing (which checks the log for the - // presence of this message). Do not change this without also checking these tests. - QPID_LOG(debug, "Message id=\"" << msg->getProperties<MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content released after recovery"); - } -} - -void Queue::process(boost::intrusive_ptr<Message>& msg){ - push(msg); - if (mgmtObject != 0){ - mgmtObject->inc_msgTxnEnqueues (); - mgmtObject->inc_byteTxnEnqueues (msg->contentSize ()); - } -} - -void Queue::requeue(const QueuedMessage& msg){ - assertClusterSafe(); - QueueListeners::NotificationSet copy; - { - Mutex::ScopedLock locker(messageLock); - if (!isEnqueued(msg)) return; - messages->reinsert(msg); - listeners.populate(copy); - - // for persistLastNode - don't force a message twice to disk, but force it if no force before - if(inLastNodeFailure && persistLastNode && !msg.payload->isStoredOnQueue(shared_from_this())) { - msg.payload->forcePersistent(); - if (msg.payload->isForcedPersistent() ){ - boost::intrusive_ptr<Message> payload = msg.payload; - enqueue(0, payload); - } - } - } - copy.notify(); -} - -bool Queue::acquireMessageAt(const SequenceNumber& position, QueuedMessage& message) -{ - Mutex::ScopedLock locker(messageLock); - assertClusterSafe(); - QPID_LOG(debug, "Attempting to acquire message at " << position); - if (messages->remove(position, message)) { - QPID_LOG(debug, "Acquired message at " << position << " from " << name); - return true; - } else { - QPID_LOG(debug, "Could not acquire message at " << position << " from " << name << "; no message at that position"); - return false; - } -} - -bool Queue::acquire(const QueuedMessage& msg) { - QueuedMessage copy = msg; - return acquireMessageAt(msg.position, copy); -} - -void Queue::notifyListener() -{ - assertClusterSafe(); - QueueListeners::NotificationSet set; - { - Mutex::ScopedLock locker(messageLock); - if (messages->size()) { - listeners.populate(set); - } - } - set.notify(); -} - -bool Queue::getNextMessage(QueuedMessage& m, Consumer::shared_ptr c) -{ - checkNotDeleted(); - if (c->preAcquires()) { - switch (consumeNextMessage(m, c)) { - case CONSUMED: - return true; - case CANT_CONSUME: - notifyListener();//let someone else try - case NO_MESSAGES: - default: - return false; - } - } else { - return browseNextMessage(m, c); - } -} - -Queue::ConsumeCode Queue::consumeNextMessage(QueuedMessage& m, Consumer::shared_ptr c) -{ - while (true) { - Mutex::ScopedLock locker(messageLock); - if (messages->empty()) { - QPID_LOG(debug, "No messages to dispatch on queue '" << name << "'"); - listeners.addListener(c); - return NO_MESSAGES; - } else { - QueuedMessage msg = messages->front(); - if (msg.payload->hasExpired()) { - QPID_LOG(debug, "Message expired from queue '" << name << "'"); - popAndDequeue(); - continue; - } - - if (c->filter(msg.payload)) { - if (c->accept(msg.payload)) { - m = msg; - pop(); - return CONSUMED; - } else { - //message(s) are available but consumer hasn't got enough credit - QPID_LOG(debug, "Consumer can't currently accept message from '" << name << "'"); - return CANT_CONSUME; - } - } else { - //consumer will never want this message - QPID_LOG(debug, "Consumer doesn't want message from '" << name << "'"); - return CANT_CONSUME; - } - } - } -} - - -bool Queue::browseNextMessage(QueuedMessage& m, Consumer::shared_ptr c) -{ - QueuedMessage msg(this); - while (seek(msg, c)) { - if (c->filter(msg.payload) && !msg.payload->hasExpired()) { - if (c->accept(msg.payload)) { - //consumer wants the message - c->position = msg.position; - m = msg; - return true; - } else { - //browser hasn't got enough credit for the message - QPID_LOG(debug, "Browser can't currently accept message from '" << name << "'"); - return false; - } - } else { - //consumer will never want this message, continue seeking - c->position = msg.position; - QPID_LOG(debug, "Browser skipping message from '" << name << "'"); - } - } - return false; -} - -void Queue::removeListener(Consumer::shared_ptr c) -{ - QueueListeners::NotificationSet set; - { - Mutex::ScopedLock locker(messageLock); - listeners.removeListener(c); - if (messages->size()) { - listeners.populate(set); - } - } - set.notify(); -} - -bool Queue::dispatch(Consumer::shared_ptr c) -{ - QueuedMessage msg(this); - if (getNextMessage(msg, c)) { - c->deliver(msg); - return true; - } else { - return false; - } -} - -// Find the next message -bool Queue::seek(QueuedMessage& msg, Consumer::shared_ptr c) { - Mutex::ScopedLock locker(messageLock); - if (messages->next(c->position, msg)) { - return true; - } else { - listeners.addListener(c); - return false; - } -} - -QueuedMessage Queue::find(SequenceNumber pos) const { - - Mutex::ScopedLock locker(messageLock); - QueuedMessage msg; - messages->find(pos, msg); - return msg; -} - -void Queue::consume(Consumer::shared_ptr c, bool requestExclusive){ - assertClusterSafe(); - Mutex::ScopedLock locker(consumerLock); - if(exclusive) { - throw ResourceLockedException( - QPID_MSG("Queue " << getName() << " has an exclusive consumer. No more consumers allowed.")); - } else if(requestExclusive) { - if(consumerCount) { - throw ResourceLockedException( - QPID_MSG("Queue " << getName() << " already has consumers. Exclusive access denied.")); - } else { - exclusive = c->getSession(); - } - } - consumerCount++; - if (mgmtObject != 0) - mgmtObject->inc_consumerCount (); - //reset auto deletion timer if necessary - if (autoDeleteTimeout && autoDeleteTask) { - autoDeleteTask->cancel(); - } -} - -void Queue::cancel(Consumer::shared_ptr c){ - removeListener(c); - Mutex::ScopedLock locker(consumerLock); - consumerCount--; - if(exclusive) exclusive = 0; - if (mgmtObject != 0) - mgmtObject->dec_consumerCount (); -} - -QueuedMessage Queue::get(){ - Mutex::ScopedLock locker(messageLock); - QueuedMessage msg(this); - messages->pop(msg); - return msg; -} - -bool collect_if_expired(std::deque<QueuedMessage>& expired, QueuedMessage& message) -{ - if (message.payload->hasExpired()) { - expired.push_back(message); - return true; - } else { - return false; - } -} - -void Queue::purgeExpired() -{ - //As expired messages are discarded during dequeue also, only - //bother explicitly expiring if the rate of dequeues since last - //attempt is less than one per second. - - if (dequeueTracker.sampleRatePerSecond() < 1) { - std::deque<QueuedMessage> expired; - { - Mutex::ScopedLock locker(messageLock); - messages->removeIf(boost::bind(&collect_if_expired, expired, _1)); - } - for_each(expired.begin(), expired.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1)); - } -} - -/** - * purge - for purging all or some messages on a queue - * depending on the purge_request - * - * purge_request == 0 then purge all messages - * == N then purge N messages from queue - * Sometimes purge_request == 1 to unblock the top of queue - * - * The dest exchange may be supplied to re-route messages through the exchange. - * It is safe to re-route messages such that they arrive back on the same queue, - * even if the queue is ordered by priority. - */ -uint32_t Queue::purge(const uint32_t purge_request, boost::shared_ptr<Exchange> dest) -{ - Mutex::ScopedLock locker(messageLock); - uint32_t purge_count = purge_request; // only comes into play if >0 - std::deque<DeliverableMessage> rerouteQueue; - - uint32_t count = 0; - // Either purge them all or just the some (purge_count) while the queue isn't empty. - while((!purge_request || purge_count--) && !messages->empty()) { - if (dest.get()) { - // - // If there is a destination exchange, stage the messages onto a reroute queue - // so they don't wind up getting purged more than once. - // - DeliverableMessage msg(messages->front().payload); - rerouteQueue.push_back(msg); - } - popAndDequeue(); - count++; - } - - // - // Re-route purged messages into the destination exchange. Note that there's no need - // to test dest.get() here because if it is NULL, the rerouteQueue will be empty. - // - while (!rerouteQueue.empty()) { - DeliverableMessage msg(rerouteQueue.front()); - rerouteQueue.pop_front(); - dest->routeWithAlternate(msg); - } - - return count; -} - -uint32_t Queue::move(const Queue::shared_ptr destq, uint32_t qty) { - Mutex::ScopedLock locker(messageLock); - uint32_t move_count = qty; // only comes into play if qty >0 - uint32_t count = 0; // count how many were moved for returning - - while((!qty || move_count--) && !messages->empty()) { - QueuedMessage qmsg = messages->front(); - boost::intrusive_ptr<Message> msg = qmsg.payload; - destq->deliver(msg); // deliver message to the destination queue - pop(); - dequeue(0, qmsg); - count++; - } - return count; -} - -void Queue::pop() -{ - assertClusterSafe(); - messages->pop(); - ++dequeueTracker; -} - -void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){ - assertClusterSafe(); - QueueListeners::NotificationSet copy; - QueuedMessage removed; - bool dequeueRequired = false; - { - Mutex::ScopedLock locker(messageLock); - QueuedMessage qm(this, msg, ++sequence); - if (insertSeqNo) msg->getOrInsertHeaders().setInt64(seqNoKey, sequence); - - dequeueRequired = messages->push(qm, removed); - listeners.populate(copy); - enqueued(qm); - } - copy.notify(); - if (dequeueRequired) { - if (isRecovery) { - //can't issue new requests for the store until - //recovery is complete - pendingDequeues.push_back(removed); - } else { - dequeue(0, removed); - } - } -} - -void isEnqueueComplete(uint32_t* result, const QueuedMessage& message) -{ - if (message.payload->isIngressComplete()) (*result)++; -} - -/** function only provided for unit tests, or code not in critical message path */ -uint32_t Queue::getEnqueueCompleteMessageCount() const -{ - Mutex::ScopedLock locker(messageLock); - uint32_t count = 0; - messages->foreach(boost::bind(&isEnqueueComplete, &count, _1)); - return count; -} - -uint32_t Queue::getMessageCount() const -{ - Mutex::ScopedLock locker(messageLock); - return messages->size(); -} - -uint32_t Queue::getConsumerCount() const -{ - Mutex::ScopedLock locker(consumerLock); - return consumerCount; -} - -bool Queue::canAutoDelete() const -{ - Mutex::ScopedLock locker(consumerLock); - return autodelete && !consumerCount && !owner; -} - -void Queue::clearLastNodeFailure() -{ - inLastNodeFailure = false; -} - -void Queue::forcePersistent(QueuedMessage& message) -{ - if(!message.payload->isStoredOnQueue(shared_from_this())) { - message.payload->forcePersistent(); - if (message.payload->isForcedPersistent() ){ - enqueue(0, message.payload); - } - } -} - -void Queue::setLastNodeFailure() -{ - if (persistLastNode){ - Mutex::ScopedLock locker(messageLock); - try { - messages->foreach(boost::bind(&Queue::forcePersistent, this, _1)); - } catch (const std::exception& e) { - // Could not go into last node standing (for example journal not large enough) - QPID_LOG(error, "Unable to fail to last node standing for queue: " << name << " : " << e.what()); - } - inLastNodeFailure = true; - } -} - - -// return true if store exists, -bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg, bool suppressPolicyCheck) -{ - ScopedUse u(barrier); - if (!u.acquired) return false; - - if (policy.get() && !suppressPolicyCheck) { - std::deque<QueuedMessage> dequeues; - { - Mutex::ScopedLock locker(messageLock); - policy->tryEnqueue(msg); - policy->getPendingDequeues(dequeues); - } - //depending on policy, may have some dequeues that need to performed without holding the lock - for_each(dequeues.begin(), dequeues.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1)); - } - - if (inLastNodeFailure && persistLastNode){ - msg->forcePersistent(); - } - - if (traceId.size()) { - //copy on write: take deep copy of message before modifying it - //as the frames may already be available for delivery on other - //threads - boost::intrusive_ptr<Message> copy(new Message(*msg)); - msg = copy; - msg->addTraceId(traceId); - } - - if ((msg->isPersistent() || msg->checkContentReleasable()) && store) { - // mark the message as being enqueued - the store MUST CALL msg->enqueueComplete() - // when it considers the message stored. - msg->enqueueAsync(shared_from_this(), store); - boost::intrusive_ptr<PersistableMessage> pmsg = boost::static_pointer_cast<PersistableMessage>(msg); - store->enqueue(ctxt, pmsg, *this); - return true; - } - if (!store) { - //Messages enqueued on a transient queue should be prevented - //from having their content released as it may not be - //recoverable by these queue for delivery - msg->blockContentRelease(); - } - return false; -} - -void Queue::enqueueAborted(boost::intrusive_ptr<Message> msg) -{ - Mutex::ScopedLock locker(messageLock); - if (policy.get()) policy->enqueueAborted(msg); -} - -// return true if store exists, -bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg) -{ - ScopedUse u(barrier); - if (!u.acquired) return false; - - { - Mutex::ScopedLock locker(messageLock); - if (!isEnqueued(msg)) return false; - if (!ctxt) { - dequeued(msg); - } - } - // This check prevents messages which have been forced persistent on one queue from dequeuing - // from another on which no forcing has taken place and thus causing a store error. - bool fp = msg.payload->isForcedPersistent(); - if (!fp || (fp && msg.payload->isStoredOnQueue(shared_from_this()))) { - if ((msg.payload->isPersistent() || msg.payload->checkContentReleasable()) && store) { - msg.payload->dequeueAsync(shared_from_this(), store); //increment to async counter -- for message sent to more than one queue - boost::intrusive_ptr<PersistableMessage> pmsg = boost::static_pointer_cast<PersistableMessage>(msg.payload); - store->dequeue(ctxt, pmsg, *this); - return true; - } - } - return false; -} - -void Queue::dequeueCommitted(const QueuedMessage& msg) -{ - Mutex::ScopedLock locker(messageLock); - dequeued(msg); - if (mgmtObject != 0) { - mgmtObject->inc_msgTxnDequeues(); - mgmtObject->inc_byteTxnDequeues(msg.payload->contentSize()); - } -} - -/** - * Removes a message from the in-memory delivery queue as well - * dequeing it from the logical (and persistent if applicable) queue - */ -void Queue::popAndDequeue() -{ - QueuedMessage msg = messages->front(); - pop(); - dequeue(0, msg); -} - -/** - * Updates policy and management when a message has been dequeued, - * expects messageLock to be held - */ -void Queue::dequeued(const QueuedMessage& msg) -{ - if (policy.get()) policy->dequeued(msg); - mgntDeqStats(msg.payload); - for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) { - try{ - (*i)->dequeued(msg); - } catch (const std::exception& e) { - QPID_LOG(warning, "Exception on notification of dequeue for queue " << getName() << ": " << e.what()); - } - } -} - - -void Queue::create(const FieldTable& _settings) -{ - settings = _settings; - if (store) { - store->create(*this, _settings); - } - configureImpl(_settings); -} - - -int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::string& key) -{ - qpid::framing::FieldTable::ValuePtr v = settings.get(key); - if (!v) { - return 0; - } else if (v->convertsTo<int>()) { - return v->get<int>(); - } else if (v->convertsTo<std::string>()){ - std::string s = v->get<std::string>(); - try { - return boost::lexical_cast<int>(s); - } catch(const boost::bad_lexical_cast&) { - QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << s); - return 0; - } - } else { - QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << *v); - return 0; - } -} - -void Queue::configure(const FieldTable& _settings) -{ - settings = _settings; - configureImpl(settings); -} - -void Queue::configureImpl(const FieldTable& _settings) -{ - eventMode = _settings.getAsInt(qpidQueueEventGeneration); - if (eventMode && broker) { - broker->getQueueEvents().observe(*this, eventMode == ENQUEUE_ONLY); - } - - if (QueuePolicy::getType(_settings) == QueuePolicy::FLOW_TO_DISK && - (!store || NullMessageStore::isNullStore(store) || (broker && !(broker->getQueueEvents().isSync())) )) { - if ( NullMessageStore::isNullStore(store)) { - QPID_LOG(warning, "Flow to disk not valid for non-persisted queue:" << getName()); - } else if (broker && !(broker->getQueueEvents().isSync()) ) { - QPID_LOG(warning, "Flow to disk not valid with async Queue Events:" << getName()); - } - FieldTable copy(_settings); - copy.erase(QueuePolicy::typeKey); - setPolicy(QueuePolicy::createQueuePolicy(getName(), copy)); - } else { - setPolicy(QueuePolicy::createQueuePolicy(getName(), _settings)); - } - if (broker && broker->getManagementAgent()) { - ThresholdAlerts::observe(*this, *(broker->getManagementAgent()), _settings, broker->getOptions().queueThresholdEventRatio); - } - - //set this regardless of owner to allow use of no-local with exclusive consumers also - noLocal = _settings.get(qpidNoLocal); - QPID_LOG(debug, "Configured queue " << getName() << " with no-local=" << noLocal); - - std::string lvqKey = _settings.getAsString(qpidLastValueQueueKey); - if (lvqKey.size()) { - QPID_LOG(debug, "Configured queue " << getName() << " as Last Value Queue with key " << lvqKey); - messages = std::auto_ptr<Messages>(new MessageMap(lvqKey)); - } else if (_settings.get(qpidLastValueQueueNoBrowse)) { - QPID_LOG(debug, "Configured queue " << getName() << " as Legacy Last Value Queue with 'no-browse' on"); - messages = LegacyLVQ::updateOrReplace(messages, qpidVQMatchProperty, true, broker); - } else if (_settings.get(qpidLastValueQueue)) { - QPID_LOG(debug, "Configured queue " << getName() << " as Legacy Last Value Queue"); - messages = LegacyLVQ::updateOrReplace(messages, qpidVQMatchProperty, false, broker); - } else { - std::auto_ptr<Messages> m = Fairshare::create(_settings); - if (m.get()) { - messages = m; - QPID_LOG(debug, "Configured queue " << getName() << " as priority queue."); - } - } - - persistLastNode= _settings.get(qpidPersistLastNode); - if (persistLastNode) QPID_LOG(debug, "Configured queue to Persist data if cluster fails to one node for: " << getName()); - - traceId = _settings.getAsString(qpidTraceIdentity); - std::string excludeList = _settings.getAsString(qpidTraceExclude); - if (excludeList.size()) { - split(traceExclude, excludeList, ", "); - } - QPID_LOG(debug, "Configured queue " << getName() << " with qpid.trace.id='" << traceId - << "' and qpid.trace.exclude='"<< excludeList << "' i.e. " << traceExclude.size() << " elements"); - - FieldTable::ValuePtr p =_settings.get(qpidInsertSequenceNumbers); - if (p && p->convertsTo<std::string>()) insertSequenceNumbers(p->get<std::string>()); - - autoDeleteTimeout = getIntegerSetting(_settings, qpidAutoDeleteTimeout); - if (autoDeleteTimeout) - QPID_LOG(debug, "Configured queue " << getName() << " with qpid.auto_delete_timeout=" << autoDeleteTimeout); - - if (mgmtObject != 0) { - mgmtObject->set_arguments(ManagementAgent::toMap(_settings)); - } - - QueueFlowLimit::observe(*this, _settings); -} - -void Queue::destroyed() -{ - unbind(broker->getExchanges()); - if (alternateExchange.get()) { - Mutex::ScopedLock locker(messageLock); - while(!messages->empty()){ - DeliverableMessage msg(messages->front().payload); - alternateExchange->routeWithAlternate(msg); - popAndDequeue(); - } - alternateExchange->decAlternateUsers(); - } - - if (store) { - barrier.destroy(); - store->flush(*this); - store->destroy(*this); - store = 0;//ensure we make no more calls to the store for this queue - } - if (autoDeleteTask) autoDeleteTask = boost::intrusive_ptr<TimerTask>(); - notifyDeleted(); -} - -void Queue::notifyDeleted() -{ - QueueListeners::ListenerSet set; - { - Mutex::ScopedLock locker(messageLock); - listeners.snapshot(set); - deleted = true; - } - set.notifyAll(); -} - -void Queue::bound(const string& exchange, const string& key, - const FieldTable& args) -{ - bindings.add(exchange, key, args); -} - -void Queue::unbind(ExchangeRegistry& exchanges) -{ - bindings.unbind(exchanges, shared_from_this()); -} - -void Queue::setPolicy(std::auto_ptr<QueuePolicy> _policy) -{ - policy = _policy; -} - -const QueuePolicy* Queue::getPolicy() -{ - return policy.get(); -} - -uint64_t Queue::getPersistenceId() const -{ - return persistenceId; -} - -void Queue::setPersistenceId(uint64_t _persistenceId) const -{ - if (mgmtObject != 0 && persistenceId == 0 && externalQueueStore) - { - ManagementObject* childObj = externalQueueStore->GetManagementObject(); - if (childObj != 0) - childObj->setReference(mgmtObject->getObjectId()); - } - persistenceId = _persistenceId; -} - -void Queue::encode(Buffer& buffer) const -{ - buffer.putShortString(name); - buffer.put(settings); - if (policy.get()) { - buffer.put(*policy); - } - buffer.putShortString(alternateExchange.get() ? alternateExchange->getName() : std::string("")); -} - -uint32_t Queue::encodedSize() const -{ - return name.size() + 1/*short string size octet*/ - + (alternateExchange.get() ? alternateExchange->getName().size() : 0) + 1 /* short string */ - + settings.encodedSize() - + (policy.get() ? (*policy).encodedSize() : 0); -} - -Queue::shared_ptr Queue::restore( QueueRegistry& queues, Buffer& buffer ) -{ - string name; - buffer.getShortString(name); - FieldTable settings; - buffer.get(settings); - boost::shared_ptr<Exchange> alternate; - std::pair<Queue::shared_ptr, bool> result = queues.declare(name, true, false, 0, alternate, settings, true); - if (result.first->policy.get() && buffer.available() >= result.first->policy->encodedSize()) { - buffer.get ( *(result.first->policy) ); - } - if (buffer.available()) { - string altExch; - buffer.getShortString(altExch); - result.first->alternateExchangeName.assign(altExch); - } - - return result.first; -} - - -void Queue::setAlternateExchange(boost::shared_ptr<Exchange> exchange) -{ - alternateExchange = exchange; - if (mgmtObject) { - if (exchange.get() != 0) - mgmtObject->set_altExchange(exchange->GetManagementObject()->getObjectId()); - else - mgmtObject->clr_altExchange(); - } -} - -boost::shared_ptr<Exchange> Queue::getAlternateExchange() -{ - return alternateExchange; -} - -void tryAutoDeleteImpl(Broker& broker, Queue::shared_ptr queue) -{ - if (broker.getQueues().destroyIf(queue->getName(), - boost::bind(boost::mem_fn(&Queue::canAutoDelete), queue))) { - QPID_LOG(debug, "Auto-deleting " << queue->getName()); - queue->destroyed(); - } -} - -struct AutoDeleteTask : qpid::sys::TimerTask -{ - Broker& broker; - Queue::shared_ptr queue; - - AutoDeleteTask(Broker& b, Queue::shared_ptr q, AbsTime fireTime) - : qpid::sys::TimerTask(fireTime, "DelayedAutoDeletion"), broker(b), queue(q) {} - - void fire() - { - //need to detect case where queue was used after the task was - //created, but then became unused again before the task fired; - //in this case ignore this request as there will have already - //been a later task added - tryAutoDeleteImpl(broker, queue); - } -}; - -void Queue::tryAutoDelete(Broker& broker, Queue::shared_ptr queue) -{ - if (queue->autoDeleteTimeout && queue->canAutoDelete()) { - AbsTime time(now(), Duration(queue->autoDeleteTimeout * TIME_SEC)); - queue->autoDeleteTask = boost::intrusive_ptr<qpid::sys::TimerTask>(new AutoDeleteTask(broker, queue, time)); - broker.getClusterTimer().add(queue->autoDeleteTask); - QPID_LOG(debug, "Timed auto-delete for " << queue->getName() << " initiated"); - } else { - tryAutoDeleteImpl(broker, queue); - } -} - -bool Queue::isExclusiveOwner(const OwnershipToken* const o) const -{ - Mutex::ScopedLock locker(ownershipLock); - return o == owner; -} - -void Queue::releaseExclusiveOwnership() -{ - Mutex::ScopedLock locker(ownershipLock); - owner = 0; -} - -bool Queue::setExclusiveOwner(const OwnershipToken* const o) -{ - //reset auto deletion timer if necessary - if (autoDeleteTimeout && autoDeleteTask) { - autoDeleteTask->cancel(); - } - Mutex::ScopedLock locker(ownershipLock); - if (owner) { - return false; - } else { - owner = o; - return true; - } -} - -bool Queue::hasExclusiveOwner() const -{ - Mutex::ScopedLock locker(ownershipLock); - return owner != 0; -} - -bool Queue::hasExclusiveConsumer() const -{ - return exclusive; -} - -void Queue::setExternalQueueStore(ExternalQueueStore* inst) { - if (externalQueueStore!=inst && externalQueueStore) - delete externalQueueStore; - externalQueueStore = inst; - - if (inst) { - ManagementObject* childObj = inst->GetManagementObject(); - if (childObj != 0 && mgmtObject != 0) - childObj->setReference(mgmtObject->getObjectId()); - } -} - -ManagementObject* Queue::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t Queue::ManagementMethod (uint32_t methodId, Args& args, string& etext) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - QPID_LOG (debug, "Queue::ManagementMethod [id=" << methodId << "]"); - - switch (methodId) { - case _qmf::Queue::METHOD_PURGE : - { - _qmf::ArgsQueuePurge& purgeArgs = (_qmf::ArgsQueuePurge&) args; - purge(purgeArgs.i_request); - status = Manageable::STATUS_OK; - } - break; - - case _qmf::Queue::METHOD_REROUTE : - { - _qmf::ArgsQueueReroute& rerouteArgs = (_qmf::ArgsQueueReroute&) args; - boost::shared_ptr<Exchange> dest; - if (rerouteArgs.i_useAltExchange) - dest = alternateExchange; - else { - try { - dest = broker->getExchanges().get(rerouteArgs.i_exchange); - } catch(const std::exception&) { - status = Manageable::STATUS_PARAMETER_INVALID; - etext = "Exchange not found"; - break; - } - } - - purge(rerouteArgs.i_request, dest); - status = Manageable::STATUS_OK; - } - break; - } - - return status; -} - -void Queue::setPosition(SequenceNumber n) { - Mutex::ScopedLock locker(messageLock); - sequence = n; -} - -SequenceNumber Queue::getPosition() { - return sequence; -} - -int Queue::getEventMode() { return eventMode; } - -void Queue::recoveryComplete(ExchangeRegistry& exchanges) -{ - // set the alternate exchange - if (!alternateExchangeName.empty()) { - try { - Exchange::shared_ptr ae = exchanges.get(alternateExchangeName); - setAlternateExchange(ae); - } catch (const NotFoundException&) { - QPID_LOG(warning, "Could not set alternate exchange \"" << alternateExchangeName << "\" on queue \"" << name << "\": exchange does not exist."); - } - } - //process any pending dequeues - for_each(pendingDequeues.begin(), pendingDequeues.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1)); - pendingDequeues.clear(); -} - -void Queue::insertSequenceNumbers(const std::string& key) -{ - seqNoKey = key; - insertSeqNo = !seqNoKey.empty(); - QPID_LOG(debug, "Inserting sequence numbers as " << key); -} - -void Queue::enqueued(const QueuedMessage& m) -{ - for (Observers::iterator i = observers.begin(); i != observers.end(); ++i) { - try { - (*i)->enqueued(m); - } catch (const std::exception& e) { - QPID_LOG(warning, "Exception on notification of enqueue for queue " << getName() << ": " << e.what()); - } - } - if (policy.get()) { - policy->enqueued(m); - } - mgntEnqStats(m.payload); -} - -void Queue::updateEnqueued(const QueuedMessage& m) -{ - if (m.payload) { - boost::intrusive_ptr<Message> payload = m.payload; - enqueue ( 0, payload, true ); - if (policy.get()) { - policy->recoverEnqueued(payload); - } - enqueued(m); - } else { - QPID_LOG(warning, "Queue informed of enqueued message that has no payload"); - } -} - -bool Queue::isEnqueued(const QueuedMessage& msg) -{ - return !policy.get() || policy->isEnqueued(msg); -} - -QueueListeners& Queue::getListeners() { return listeners; } -Messages& Queue::getMessages() { return *messages; } -const Messages& Queue::getMessages() const { return *messages; } - -void Queue::checkNotDeleted() -{ - if (deleted) { - throw ResourceDeletedException(QPID_MSG("Queue " << getName() << " has been deleted.")); - } -} - -void Queue::addObserver(boost::shared_ptr<QueueObserver> observer) -{ - observers.insert(observer); -} - -void Queue::flush() -{ - ScopedUse u(barrier); - if (u.acquired && store) store->flush(*this); -} - - -bool Queue::bind(boost::shared_ptr<Exchange> exchange, const std::string& key, - const qpid::framing::FieldTable& arguments) -{ - if (exchange->bind(shared_from_this(), key, &arguments)) { - bound(exchange->getName(), key, arguments); - if (exchange->isDurable() && isDurable()) { - store->bind(*exchange, *this, key, arguments); - } - return true; - } else { - return false; - } -} - - -const Broker* Queue::getBroker() -{ - return broker; -} - - -Queue::UsageBarrier::UsageBarrier(Queue& q) : parent(q), count(0) {} - -bool Queue::UsageBarrier::acquire() -{ - Monitor::ScopedLock l(parent.messageLock); - if (parent.deleted) { - return false; - } else { - ++count; - return true; - } -} - -void Queue::UsageBarrier::release() -{ - Monitor::ScopedLock l(parent.messageLock); - if (--count == 0) parent.messageLock.notifyAll(); -} - -void Queue::UsageBarrier::destroy() -{ - Monitor::ScopedLock l(parent.messageLock); - parent.deleted = true; - while (count) parent.messageLock.wait(); -} diff --git a/cpp/src/qpid/broker/Queue.h b/cpp/src/qpid/broker/Queue.h deleted file mode 100644 index c4f1bcc07e..0000000000 --- a/cpp/src/qpid/broker/Queue.h +++ /dev/null @@ -1,390 +0,0 @@ -#ifndef _broker_Queue_h -#define _broker_Queue_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/OwnershipToken.h" -#include "qpid/broker/Consumer.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Messages.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/broker/QueuePolicy.h" -#include "qpid/broker/QueueBindings.h" -#include "qpid/broker/QueueListeners.h" -#include "qpid/broker/QueueObserver.h" -#include "qpid/broker/RateTracker.h" - -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Timer.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Queue.h" -#include "qpid/framing/amqp_types.h" - -#include <boost/shared_ptr.hpp> -#include <boost/intrusive_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> - -#include <list> -#include <vector> -#include <memory> -#include <deque> -#include <set> -#include <algorithm> - -namespace qpid { -namespace broker { -class Broker; -class MessageStore; -class QueueEvents; -class QueueRegistry; -class TransactionContext; -class Exchange; - -/** - * The brokers representation of an amqp queue. Messages are - * delivered to a queue from where they can be dispatched to - * registered consumers or be stored until dequeued or until one - * or more consumers registers. - */ -class Queue : public boost::enable_shared_from_this<Queue>, - public PersistableQueue, public management::Manageable { - - struct UsageBarrier - { - Queue& parent; - uint count; - - UsageBarrier(Queue&); - bool acquire(); - void release(); - void destroy(); - }; - - struct ScopedUse - { - UsageBarrier& barrier; - const bool acquired; - ScopedUse(UsageBarrier& b) : barrier(b), acquired(barrier.acquire()) {} - ~ScopedUse() { if (acquired) barrier.release(); } - }; - - typedef std::set< boost::shared_ptr<QueueObserver> > Observers; - enum ConsumeCode {NO_MESSAGES=0, CANT_CONSUME=1, CONSUMED=2}; - - - const std::string name; - const bool autodelete; - MessageStore* store; - const OwnershipToken* owner; - uint32_t consumerCount; - OwnershipToken* exclusive; - bool noLocal; - bool persistLastNode; - bool inLastNodeFailure; - std::string traceId; - std::vector<std::string> traceExclude; - QueueListeners listeners; - std::auto_ptr<Messages> messages; - std::deque<QueuedMessage> pendingDequeues;//used to avoid dequeuing during recovery - mutable qpid::sys::Mutex consumerLock; - mutable qpid::sys::Monitor messageLock; - mutable qpid::sys::Mutex ownershipLock; - mutable uint64_t persistenceId; - framing::FieldTable settings; - std::auto_ptr<QueuePolicy> policy; - bool policyExceeded; - QueueBindings bindings; - std::string alternateExchangeName; - boost::shared_ptr<Exchange> alternateExchange; - framing::SequenceNumber sequence; - qmf::org::apache::qpid::broker::Queue* mgmtObject; - RateTracker dequeueTracker; - int eventMode; - Observers observers; - bool insertSeqNo; - std::string seqNoKey; - Broker* broker; - bool deleted; - UsageBarrier barrier; - int autoDeleteTimeout; - boost::intrusive_ptr<qpid::sys::TimerTask> autoDeleteTask; - - void push(boost::intrusive_ptr<Message>& msg, bool isRecovery=false); - void setPolicy(std::auto_ptr<QueuePolicy> policy); - bool seek(QueuedMessage& msg, Consumer::shared_ptr position); - bool getNextMessage(QueuedMessage& msg, Consumer::shared_ptr c); - ConsumeCode consumeNextMessage(QueuedMessage& msg, Consumer::shared_ptr c); - bool browseNextMessage(QueuedMessage& msg, Consumer::shared_ptr c); - void notifyListener(); - - void removeListener(Consumer::shared_ptr); - - bool isExcluded(boost::intrusive_ptr<Message>& msg); - - void enqueued(const QueuedMessage& msg); - void dequeued(const QueuedMessage& msg); - void pop(); - void popAndDequeue(); - QueuedMessage getFront(); - void forcePersistent(QueuedMessage& msg); - int getEventMode(); - void configureImpl(const qpid::framing::FieldTable& settings); - - inline void mgntEnqStats(const boost::intrusive_ptr<Message>& msg) - { - if (mgmtObject != 0) { - mgmtObject->inc_msgTotalEnqueues (); - mgmtObject->inc_byteTotalEnqueues (msg->contentSize ()); - if (msg->isPersistent ()) { - mgmtObject->inc_msgPersistEnqueues (); - mgmtObject->inc_bytePersistEnqueues (msg->contentSize ()); - } - } - } - inline void mgntDeqStats(const boost::intrusive_ptr<Message>& msg) - { - if (mgmtObject != 0){ - mgmtObject->inc_msgTotalDequeues (); - mgmtObject->inc_byteTotalDequeues (msg->contentSize()); - if (msg->isPersistent ()){ - mgmtObject->inc_msgPersistDequeues (); - mgmtObject->inc_bytePersistDequeues (msg->contentSize()); - } - } - } - - void checkNotDeleted(); - void notifyDeleted(); - - public: - - typedef boost::shared_ptr<Queue> shared_ptr; - - typedef std::vector<shared_ptr> vector; - - QPID_BROKER_EXTERN Queue(const std::string& name, - bool autodelete = false, - MessageStore* const store = 0, - const OwnershipToken* const owner = 0, - management::Manageable* parent = 0, - Broker* broker = 0); - QPID_BROKER_EXTERN ~Queue(); - - QPID_BROKER_EXTERN bool dispatch(Consumer::shared_ptr); - - /** - * Used to configure a new queue and create a persistent record - * for it in store if required. - */ - QPID_BROKER_EXTERN void create(const qpid::framing::FieldTable& settings); - - /** - * Used to reconfigure a recovered queue (does not create - * persistent record in store). - */ - QPID_BROKER_EXTERN void configure(const qpid::framing::FieldTable& settings); - void destroyed(); - QPID_BROKER_EXTERN void bound(const std::string& exchange, - const std::string& key, - const qpid::framing::FieldTable& args); - //TODO: get unbind out of the public interface; only there for purposes of one unit test - QPID_BROKER_EXTERN void unbind(ExchangeRegistry& exchanges); - /** - * Bind self to specified exchange, and record that binding for unbinding on delete. - */ - bool bind(boost::shared_ptr<Exchange> exchange, const std::string& key, - const qpid::framing::FieldTable& arguments=qpid::framing::FieldTable()); - - QPID_BROKER_EXTERN bool acquire(const QueuedMessage& msg); - QPID_BROKER_EXTERN bool acquireMessageAt(const qpid::framing::SequenceNumber& position, QueuedMessage& message); - - /** - * Delivers a message to the queue. Will record it as - * enqueued if persistent then process it. - */ - QPID_BROKER_EXTERN void deliver(boost::intrusive_ptr<Message> msg); - /** - * Dispatches the messages immediately to a consumer if - * one is available or stores it for later if not. - */ - QPID_BROKER_EXTERN void process(boost::intrusive_ptr<Message>& msg); - /** - * Returns a message to the in-memory queue (due to lack - * of acknowledegement from a receiver). If a consumer is - * available it will be dispatched immediately, else it - * will be returned to the front of the queue. - */ - QPID_BROKER_EXTERN void requeue(const QueuedMessage& msg); - /** - * Used during recovery to add stored messages back to the queue - */ - QPID_BROKER_EXTERN void recover(boost::intrusive_ptr<Message>& msg); - - QPID_BROKER_EXTERN void consume(Consumer::shared_ptr c, - bool exclusive = false); - QPID_BROKER_EXTERN void cancel(Consumer::shared_ptr c); - - uint32_t purge(const uint32_t purge_request=0, boost::shared_ptr<Exchange> dest=boost::shared_ptr<Exchange>()); //defaults to all messages - QPID_BROKER_EXTERN void purgeExpired(); - - //move qty # of messages to destination Queue destq - uint32_t move(const Queue::shared_ptr destq, uint32_t qty); - - QPID_BROKER_EXTERN uint32_t getMessageCount() const; - QPID_BROKER_EXTERN uint32_t getEnqueueCompleteMessageCount() const; - QPID_BROKER_EXTERN uint32_t getConsumerCount() const; - inline const std::string& getName() const { return name; } - bool isExclusiveOwner(const OwnershipToken* const o) const; - void releaseExclusiveOwnership(); - bool setExclusiveOwner(const OwnershipToken* const o); - bool hasExclusiveConsumer() const; - bool hasExclusiveOwner() const; - inline bool isDurable() const { return store != 0; } - inline const framing::FieldTable& getSettings() const { return settings; } - inline bool isAutoDelete() const { return autodelete; } - bool canAutoDelete() const; - const QueueBindings& getBindings() const { return bindings; } - - /** - * used to take messages from in memory and flush down to disk. - */ - QPID_BROKER_EXTERN void setLastNodeFailure(); - QPID_BROKER_EXTERN void clearLastNodeFailure(); - - bool enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg, bool suppressPolicyCheck = false); - void enqueueAborted(boost::intrusive_ptr<Message> msg); - /** - * dequeue from store (only done once messages is acknowledged) - */ - QPID_BROKER_EXTERN bool dequeue(TransactionContext* ctxt, const QueuedMessage &msg); - /** - * Inform the queue that a previous transactional dequeue - * committed. - */ - void dequeueCommitted(const QueuedMessage& msg); - - /** - * Inform queue of messages that were enqueued, have since - * been acquired but not yet accepted or released (and - * thus are still logically on the queue) - used in - * clustered broker. - */ - void updateEnqueued(const QueuedMessage& msg); - - /** - * Test whether the specified message (identified by its - * sequence/position), is still enqueued (note this - * doesn't mean it is available for delivery as it may - * have been delievered to a subscriber who has not yet - * accepted it). - */ - bool isEnqueued(const QueuedMessage& msg); - - /** - * Gets the next available message - */ - QPID_BROKER_EXTERN QueuedMessage get(); - - /** Get the message at position pos */ - QPID_BROKER_EXTERN QueuedMessage find(framing::SequenceNumber pos) const; - - const QueuePolicy* getPolicy(); - - void setAlternateExchange(boost::shared_ptr<Exchange> exchange); - boost::shared_ptr<Exchange> getAlternateExchange(); - bool isLocal(boost::intrusive_ptr<Message>& msg); - - //PersistableQueue support: - uint64_t getPersistenceId() const; - void setPersistenceId(uint64_t persistenceId) const; - void encode(framing::Buffer& buffer) const; - uint32_t encodedSize() const; - - /** - * Restores a queue from encoded data (used in recovery) - * - * Note: restored queue will be neither auto-deleted or have an - * exclusive owner - */ - static Queue::shared_ptr restore(QueueRegistry& queues, framing::Buffer& buffer); - static void tryAutoDelete(Broker& broker, Queue::shared_ptr); - - virtual void setExternalQueueStore(ExternalQueueStore* inst); - - // Manageable entry points - management::ManagementObject* GetManagementObject (void) const; - management::Manageable::status_t - ManagementMethod (uint32_t methodId, management::Args& args, std::string& text); - - /** Apply f to each Message on the queue. */ - template <class F> void eachMessage(F f) { - sys::Mutex::ScopedLock l(messageLock); - messages->foreach(f); - } - - /** Apply f to each QueueBinding on the queue */ - template <class F> void eachBinding(F f) { - bindings.eachBinding(f); - } - - /** Apply f to each Observer on the queue */ - template <class F> void eachObserver(F f) { - std::for_each<Observers::iterator, F>(observers.begin(), observers.end(), f); - } - - /** Set the position sequence number for the next message on the queue. - * Must be >= the current sequence number. - * Used by cluster to replicate queues. - */ - QPID_BROKER_EXTERN void setPosition(framing::SequenceNumber pos); - /** return current position sequence number for the next message on the queue. - */ - QPID_BROKER_EXTERN framing::SequenceNumber getPosition(); - void addObserver(boost::shared_ptr<QueueObserver>); - QPID_BROKER_EXTERN void insertSequenceNumbers(const std::string& key); - /** - * Notify queue that recovery has completed. - */ - void recoveryComplete(ExchangeRegistry& exchanges); - - // For cluster update - QueueListeners& getListeners(); - Messages& getMessages(); - const Messages& getMessages() const; - - /** - * Reserve space in policy for an enqueued message that - * has been recovered in the prepared state (dtx only) - */ - void recoverPrepared(boost::intrusive_ptr<Message>& msg); - - void flush(); - - const Broker* getBroker(); -}; -} -} - - -#endif /*!_broker_Queue_h*/ diff --git a/cpp/src/qpid/broker/QueueBindings.cpp b/cpp/src/qpid/broker/QueueBindings.cpp deleted file mode 100644 index 60d315acfe..0000000000 --- a/cpp/src/qpid/broker/QueueBindings.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueBindings.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/framing/reply_exceptions.h" - -using qpid::framing::FieldTable; -using qpid::framing::NotFoundException; -using std::string; -using namespace qpid::broker; - -void QueueBindings::add(const string& exchange, const string& key, const FieldTable& args) -{ - bindings.push_back(QueueBinding(exchange, key, args)); -} - -void QueueBindings::unbind(ExchangeRegistry& exchanges, Queue::shared_ptr queue) -{ - for (Bindings::iterator i = bindings.begin(); i != bindings.end(); i++) { - try { - exchanges.get(i->exchange)->unbind(queue, i->key, &(i->args)); - } catch (const NotFoundException&) {} - } -} - -QueueBinding::QueueBinding(const string& _exchange, const string& _key, const FieldTable& _args) - : exchange(_exchange), key(_key), args(_args) -{} diff --git a/cpp/src/qpid/broker/QueueBindings.h b/cpp/src/qpid/broker/QueueBindings.h deleted file mode 100644 index 1b90ba5540..0000000000 --- a/cpp/src/qpid/broker/QueueBindings.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueueBindings_ -#define _QueueBindings_ - -#include "qpid/framing/FieldTable.h" -#include <boost/ptr_container/ptr_list.hpp> -#include <boost/shared_ptr.hpp> -#include <algorithm> - -namespace qpid { -namespace broker { - -class ExchangeRegistry; -class Queue; - -struct QueueBinding{ - std::string exchange; - std::string key; - qpid::framing::FieldTable args; - QueueBinding(const std::string& exchange, const std::string& key, const qpid::framing::FieldTable& args); -}; - -class QueueBindings -{ - public: - - /** Apply f to each QueueBinding. */ - template <class F> void eachBinding(F f) const { std::for_each(bindings.begin(), bindings.end(), f); } - - void add(const std::string& exchange, const std::string& key, const qpid::framing::FieldTable& args); - void unbind(ExchangeRegistry& exchanges, boost::shared_ptr<Queue> queue); - - private: - typedef std::vector<QueueBinding> Bindings; - Bindings bindings; -}; - - -}} // namespace qpid::broker - - -#endif diff --git a/cpp/src/qpid/broker/QueueCleaner.cpp b/cpp/src/qpid/broker/QueueCleaner.cpp deleted file mode 100644 index 3499ea8a4d..0000000000 --- a/cpp/src/qpid/broker/QueueCleaner.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueCleaner.h" - -#include "qpid/broker/Broker.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace broker { - -QueueCleaner::QueueCleaner(QueueRegistry& q, sys::Timer& t) : queues(q), timer(t) {} - -QueueCleaner::~QueueCleaner() -{ - if (task) task->cancel(); -} - -void QueueCleaner::start(qpid::sys::Duration p) -{ - task = new Task(*this, p); - timer.add(task); -} - -QueueCleaner::Task::Task(QueueCleaner& p, qpid::sys::Duration d) : sys::TimerTask(d,"QueueCleaner"), parent(p) {} - -void QueueCleaner::Task::fire() -{ - parent.fired(); -} - -namespace { -struct CollectQueues -{ - std::vector<Queue::shared_ptr>* queues; - CollectQueues(std::vector<Queue::shared_ptr>* q) : queues(q) {} - void operator()(Queue::shared_ptr q) - { - queues->push_back(q); - } -}; -} - -void QueueCleaner::fired() -{ - //collect copy of list of queues to avoid holding registry lock while we perform purge - std::vector<Queue::shared_ptr> copy; - CollectQueues collect(©); - queues.eachQueue(collect); - std::for_each(copy.begin(), copy.end(), boost::bind(&Queue::purgeExpired, _1)); - task->setupNextFire(); - timer.add(task); -} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/QueueCleaner.h b/cpp/src/qpid/broker/QueueCleaner.h deleted file mode 100644 index 11c2d180ac..0000000000 --- a/cpp/src/qpid/broker/QueueCleaner.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef QPID_BROKER_QUEUECLEANER_H -#define QPID_BROKER_QUEUECLEANER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/sys/Timer.h" - -namespace qpid { -namespace broker { - -class QueueRegistry; -/** - * TimerTask to purge expired messages from queues - */ -class QueueCleaner -{ - public: - QPID_BROKER_EXTERN QueueCleaner(QueueRegistry& queues, sys::Timer& timer); - QPID_BROKER_EXTERN ~QueueCleaner(); - QPID_BROKER_EXTERN void start(qpid::sys::Duration period); - private: - class Task : public sys::TimerTask - { - public: - Task(QueueCleaner& parent, qpid::sys::Duration duration); - void fire(); - private: - QueueCleaner& parent; - }; - - boost::intrusive_ptr<sys::TimerTask> task; - QueueRegistry& queues; - sys::Timer& timer; - - void fired(); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUECLEANER_H*/ diff --git a/cpp/src/qpid/broker/QueueEvents.cpp b/cpp/src/qpid/broker/QueueEvents.cpp deleted file mode 100644 index 2c540ff1ad..0000000000 --- a/cpp/src/qpid/broker/QueueEvents.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueEvents.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueObserver.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -QueueEvents::QueueEvents(const boost::shared_ptr<sys::Poller>& poller, bool isSync) : - eventQueue(boost::bind(&QueueEvents::handle, this, _1), poller), enabled(true), sync(isSync) -{ - if (!sync) eventQueue.start(); -} - -QueueEvents::~QueueEvents() -{ - if (!sync) eventQueue.stop(); -} - -void QueueEvents::enqueued(const QueuedMessage& m) -{ - if (enabled) { - Event enq(ENQUEUE, m); - if (sync) { - for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++) - j->second(enq); - } else { - eventQueue.push(enq); - } - } -} - -void QueueEvents::dequeued(const QueuedMessage& m) -{ - if (enabled) { - Event deq(DEQUEUE, m); - if (sync) { - for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++) - j->second(deq); - } else { - eventQueue.push(Event(DEQUEUE, m)); - } - } -} - -void QueueEvents::registerListener(const std::string& id, const EventListener& listener) -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (listeners.find(id) == listeners.end()) { - listeners[id] = listener; - } else { - throw Exception(QPID_MSG("Event listener already registered for '" << id << "'")); - } -} - -void QueueEvents::unregisterListener(const std::string& id) -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (listeners.find(id) == listeners.end()) { - throw Exception(QPID_MSG("No event listener registered for '" << id << "'")); - } else { - listeners.erase(id); - } -} - -QueueEvents::EventQueue::Batch::const_iterator -QueueEvents::handle(const EventQueue::Batch& events) { - qpid::sys::Mutex::ScopedLock l(lock); - for (EventQueue::Batch::const_iterator i = events.begin(); i != events.end(); ++i) { - for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++) { - j->second(*i); - } - } - return events.end(); -} - -void QueueEvents::shutdown() -{ - if (!sync && !eventQueue.empty() && !listeners.empty()) eventQueue.shutdown(); -} - -void QueueEvents::enable() -{ - enabled = true; - QPID_LOG(debug, "Queue events enabled"); -} - -void QueueEvents::disable() -{ - enabled = false; - QPID_LOG(debug, "Queue events disabled"); -} - -bool QueueEvents::isSync() -{ - return sync; -} - -class EventGenerator : public QueueObserver -{ - public: - EventGenerator(QueueEvents& mgr, bool enqOnly) : manager(mgr), enqueueOnly(enqOnly) {} - void enqueued(const QueuedMessage& m) - { - manager.enqueued(m); - } - void dequeued(const QueuedMessage& m) - { - if (!enqueueOnly) manager.dequeued(m); - } - private: - QueueEvents& manager; - const bool enqueueOnly; -}; - -void QueueEvents::observe(Queue& queue, bool enqueueOnly) -{ - boost::shared_ptr<QueueObserver> observer(new EventGenerator(*this, enqueueOnly)); - queue.addObserver(observer); -} - - -QueueEvents::Event::Event(EventType t, const QueuedMessage& m) : type(t), msg(m) {} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/QueueEvents.h b/cpp/src/qpid/broker/QueueEvents.h deleted file mode 100644 index fcddfe9092..0000000000 --- a/cpp/src/qpid/broker/QueueEvents.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef QPID_BROKER_QUEUEEVENTS_H -#define QPID_BROKER_QUEUEEVENTS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/PollableQueue.h" -#include <map> -#include <string> -#include <boost/function.hpp> - -namespace qpid { -namespace broker { - -/** - * Event manager for queue events. Allows queues to indicate when - * events have occured; allows listeners to register for notification - * of this. The notification happens asynchronously, in a separate - * thread. - */ -class QueueEvents -{ - public: - enum EventType {ENQUEUE, DEQUEUE}; - - struct Event - { - EventType type; - QueuedMessage msg; - - QPID_BROKER_EXTERN Event(EventType, const QueuedMessage&); - }; - - typedef boost::function<void (Event)> EventListener; - - QPID_BROKER_EXTERN QueueEvents(const boost::shared_ptr<sys::Poller>& poller, bool isSync = false); - QPID_BROKER_EXTERN ~QueueEvents(); - QPID_BROKER_EXTERN void enqueued(const QueuedMessage&); - QPID_BROKER_EXTERN void dequeued(const QueuedMessage&); - QPID_BROKER_EXTERN void registerListener(const std::string& id, - const EventListener&); - QPID_BROKER_EXTERN void unregisterListener(const std::string& id); - void enable(); - void disable(); - void observe(Queue&, bool enqueueOnly); - //process all outstanding events - QPID_BROKER_EXTERN void shutdown(); - QPID_BROKER_EXTERN bool isSync(); - private: - typedef qpid::sys::PollableQueue<Event> EventQueue; - typedef std::map<std::string, EventListener> Listeners; - - EventQueue eventQueue; - Listeners listeners; - volatile bool enabled; - qpid::sys::Mutex lock;//protect listeners from concurrent access - bool sync; - - EventQueue::Batch::const_iterator handle(const EventQueue::Batch& e); - -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUEEVENTS_H*/ diff --git a/cpp/src/qpid/broker/QueueFlowLimit.cpp b/cpp/src/qpid/broker/QueueFlowLimit.cpp deleted file mode 100644 index b2e2e54bdf..0000000000 --- a/cpp/src/qpid/broker/QueueFlowLimit.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueFlowLimit.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/Exception.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/SessionState.h" -#include "qpid/sys/ClusterSafe.h" - -#include "qmf/org/apache/qpid/broker/Queue.h" - -#include <sstream> - -using namespace qpid::broker; -using namespace qpid::framing; - -namespace { - /** ensure that the configured flow control stop and resume values are - * valid with respect to the maximum queue capacity, and each other - */ - template <typename T> - void validateFlowConfig(T max, T& stop, T& resume, const std::string& type, const std::string& queue) - { - if (resume > stop) { - throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_resume_" << type - << "=" << resume - << " must be less than qpid.flow_stop_" << type - << "=" << stop)); - } - if (resume == 0) resume = stop; - if (max != 0 && (max < stop)) { - throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_stop_" << type - << "=" << stop - << " must be less than qpid.max_" << type - << "=" << max)); - } - } - - /** extract a capacity value as passed in an argument map - */ - uint64_t getCapacity(const FieldTable& settings, const std::string& key, uint64_t defaultValue) - { - FieldTable::ValuePtr v = settings.get(key); - - int64_t result = 0; - - if (!v) return defaultValue; - if (v->getType() == 0x23) { - QPID_LOG(debug, "Value for " << key << " specified as float: " << v->get<float>()); - } else if (v->getType() == 0x33) { - QPID_LOG(debug, "Value for " << key << " specified as double: " << v->get<double>()); - } else if (v->convertsTo<int64_t>()) { - result = v->get<int64_t>(); - QPID_LOG(debug, "Got integer value for " << key << ": " << result); - if (result >= 0) return result; - } else if (v->convertsTo<string>()) { - string s(v->get<string>()); - QPID_LOG(debug, "Got string value for " << key << ": " << s); - std::istringstream convert(s); - if (convert >> result && result >= 0) return result; - } - - QPID_LOG(warning, "Cannot convert " << key << " to unsigned integer, using default (" << defaultValue << ")"); - return defaultValue; - } -} - - - -QueueFlowLimit::QueueFlowLimit(Queue *_queue, - uint32_t _flowStopCount, uint32_t _flowResumeCount, - uint64_t _flowStopSize, uint64_t _flowResumeSize) - : StatefulQueueObserver(std::string("QueueFlowLimit")), queue(_queue), queueName("<unknown>"), - flowStopCount(_flowStopCount), flowResumeCount(_flowResumeCount), - flowStopSize(_flowStopSize), flowResumeSize(_flowResumeSize), - flowStopped(false), count(0), size(0), queueMgmtObj(0), broker(0) -{ - uint32_t maxCount(0); - uint64_t maxSize(0); - - if (queue) { - queueName = _queue->getName(); - if (queue->getPolicy()) { - maxSize = _queue->getPolicy()->getMaxSize(); - maxCount = _queue->getPolicy()->getMaxCount(); - } - broker = queue->getBroker(); - queueMgmtObj = dynamic_cast<_qmfBroker::Queue*> (queue->GetManagementObject()); - if (queueMgmtObj) { - queueMgmtObj->set_flowStopped(isFlowControlActive()); - } - } - validateFlowConfig( maxCount, flowStopCount, flowResumeCount, "count", queueName ); - validateFlowConfig( maxSize, flowStopSize, flowResumeSize, "size", queueName ); - QPID_LOG(info, "Queue \"" << queueName << "\": Flow limit created: flowStopCount=" << flowStopCount - << ", flowResumeCount=" << flowResumeCount - << ", flowStopSize=" << flowStopSize << ", flowResumeSize=" << flowResumeSize ); -} - - -QueueFlowLimit::~QueueFlowLimit() -{ - sys::Mutex::ScopedLock l(indexLock); - if (!index.empty()) { - // we're gone - release all pending msgs - for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.begin(); - itr != index.end(); ++itr) - if (itr->second) - try { - itr->second->getIngressCompletion().finishCompleter(); - } catch (...) {} // ignore - not safe for a destructor to throw. - index.clear(); - } -} - - -void QueueFlowLimit::enqueued(const QueuedMessage& msg) -{ - sys::Mutex::ScopedLock l(indexLock); - - ++count; - size += msg.payload->contentSize(); - - if (!flowStopped) { - if (flowStopCount && count > flowStopCount) { - flowStopped = true; - QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopCount << " enqueued messages. Producer flow control activated." ); - } else if (flowStopSize && size > flowStopSize) { - flowStopped = true; - QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopSize << " enqueued bytes. Producer flow control activated." ); - } - if (flowStopped && queueMgmtObj) { - queueMgmtObj->set_flowStopped(true); - queueMgmtObj->inc_flowStoppedCount(); - } - } - - if (flowStopped || !index.empty()) { - // ignore flow control if we are populating the queue due to cluster replication: - if (broker && broker->isClusterUpdatee()) { - QPID_LOG(trace, "Queue \"" << queueName << "\": ignoring flow control for msg pos=" << msg.position); - return; - } - QPID_LOG(trace, "Queue \"" << queueName << "\": setting flow control for msg pos=" << msg.position); - msg.payload->getIngressCompletion().startCompleter(); // don't complete until flow resumes - bool unique; - unique = index.insert(std::pair<framing::SequenceNumber, boost::intrusive_ptr<Message> >(msg.position, msg.payload)).second; - assert(unique); - } -} - - - -void QueueFlowLimit::dequeued(const QueuedMessage& msg) -{ - sys::Mutex::ScopedLock l(indexLock); - - if (count > 0) { - --count; - } else { - throw Exception(QPID_MSG("Flow limit count underflow on dequeue. Queue=" << queueName)); - } - - uint64_t _size = msg.payload->contentSize(); - if (_size <= size) { - size -= _size; - } else { - throw Exception(QPID_MSG("Flow limit size underflow on dequeue. Queue=" << queueName)); - } - - if (flowStopped && - (flowResumeSize == 0 || size < flowResumeSize) && - (flowResumeCount == 0 || count < flowResumeCount)) { - flowStopped = false; - if (queueMgmtObj) - queueMgmtObj->set_flowStopped(false); - QPID_LOG(info, "Queue \"" << queueName << "\": has drained below the flow control resume level. Producer flow control deactivated." ); - } - - if (!index.empty()) { - if (!flowStopped) { - // flow enabled - release all pending msgs - for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.begin(); - itr != index.end(); ++itr) - if (itr->second) - itr->second->getIngressCompletion().finishCompleter(); - index.clear(); - } else { - // even if flow controlled, we must release this msg as it is being dequeued - std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.find(msg.position); - if (itr != index.end()) { // this msg is flow controlled, release it: - msg.payload->getIngressCompletion().finishCompleter(); - index.erase(itr); - } - } - } -} - - -void QueueFlowLimit::encode(Buffer& buffer) const -{ - buffer.putLong(flowStopCount); - buffer.putLong(flowResumeCount); - buffer.putLongLong(flowStopSize); - buffer.putLongLong(flowResumeSize); - buffer.putLong(count); - buffer.putLongLong(size); -} - - -void QueueFlowLimit::decode ( Buffer& buffer ) -{ - flowStopCount = buffer.getLong(); - flowResumeCount = buffer.getLong(); - flowStopSize = buffer.getLongLong(); - flowResumeSize = buffer.getLongLong(); - count = buffer.getLong(); - size = buffer.getLongLong(); -} - - -uint32_t QueueFlowLimit::encodedSize() const { - return sizeof(uint32_t) + // flowStopCount - sizeof(uint32_t) + // flowResumecount - sizeof(uint64_t) + // flowStopSize - sizeof(uint64_t) + // flowResumeSize - sizeof(uint32_t) + // count - sizeof(uint64_t); // size -} - - -const std::string QueueFlowLimit::flowStopCountKey("qpid.flow_stop_count"); -const std::string QueueFlowLimit::flowResumeCountKey("qpid.flow_resume_count"); -const std::string QueueFlowLimit::flowStopSizeKey("qpid.flow_stop_size"); -const std::string QueueFlowLimit::flowResumeSizeKey("qpid.flow_resume_size"); -uint64_t QueueFlowLimit::defaultMaxSize; -uint QueueFlowLimit::defaultFlowStopRatio; -uint QueueFlowLimit::defaultFlowResumeRatio; - - -void QueueFlowLimit::setDefaults(uint64_t maxQueueSize, uint flowStopRatio, uint flowResumeRatio) -{ - defaultMaxSize = maxQueueSize; - defaultFlowStopRatio = flowStopRatio; - defaultFlowResumeRatio = flowResumeRatio; - - /** @todo KAG: Verify valid range on Broker::Options instead of here */ - if (flowStopRatio > 100 || flowResumeRatio > 100) - throw InvalidArgumentException(QPID_MSG("Default queue flow ratios must be between 0 and 100, inclusive:" - << " flowStopRatio=" << flowStopRatio - << " flowResumeRatio=" << flowResumeRatio)); - if (flowResumeRatio > flowStopRatio) - throw InvalidArgumentException(QPID_MSG("Default queue flow stop ratio must be >= flow resume ratio:" - << " flowStopRatio=" << flowStopRatio - << " flowResumeRatio=" << flowResumeRatio)); -} - - -void QueueFlowLimit::observe(Queue& queue, const qpid::framing::FieldTable& settings) -{ - QueueFlowLimit *ptr = createLimit( &queue, settings ); - if (ptr) { - boost::shared_ptr<QueueFlowLimit> observer(ptr); - queue.addObserver(observer); - } -} - -/** returns ptr to a QueueFlowLimit, else 0 if no limit */ -QueueFlowLimit *QueueFlowLimit::createLimit(Queue *queue, const qpid::framing::FieldTable& settings) -{ - std::string type(QueuePolicy::getType(settings)); - - if (type == QueuePolicy::RING || type == QueuePolicy::RING_STRICT) { - // The size of a RING queue is limited by design - no need for flow control. - return 0; - } - - if (settings.get(flowStopCountKey) || settings.get(flowStopSizeKey) || - settings.get(flowResumeCountKey) || settings.get(flowResumeSizeKey)) { - // user provided (some) flow settings manually... - uint32_t flowStopCount = getCapacity(settings, flowStopCountKey, 0); - uint32_t flowResumeCount = getCapacity(settings, flowResumeCountKey, 0); - uint64_t flowStopSize = getCapacity(settings, flowStopSizeKey, 0); - uint64_t flowResumeSize = getCapacity(settings, flowResumeSizeKey, 0); - if (flowStopCount == 0 && flowStopSize == 0) { // disable flow control - return 0; - } - return new QueueFlowLimit(queue, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize); - } - - if (defaultFlowStopRatio) { // broker has a default ratio setup... - uint64_t maxByteCount = getCapacity(settings, QueuePolicy::maxSizeKey, defaultMaxSize); - uint64_t flowStopSize = (uint64_t)(maxByteCount * (defaultFlowStopRatio/100.0) + 0.5); - uint64_t flowResumeSize = (uint64_t)(maxByteCount * (defaultFlowResumeRatio/100.0)); - uint32_t maxMsgCount = getCapacity(settings, QueuePolicy::maxCountKey, 0); // no size by default - uint32_t flowStopCount = (uint32_t)(maxMsgCount * (defaultFlowStopRatio/100.0) + 0.5); - uint32_t flowResumeCount = (uint32_t)(maxMsgCount * (defaultFlowResumeRatio/100.0)); - - return new QueueFlowLimit(queue, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize); - } - return 0; -} - -/* Cluster replication */ - -namespace { - /** pack a set of sequence number ranges into a framing::Array */ - void buildSeqRangeArray(qpid::framing::Array *seqs, - const qpid::framing::SequenceNumber& first, - const qpid::framing::SequenceNumber& last) - { - seqs->push_back(qpid::framing::Array::ValuePtr(new Unsigned32Value(first))); - seqs->push_back(qpid::framing::Array::ValuePtr(new Unsigned32Value(last))); - } -} - -/** Runs on UPDATER to snapshot current state */ -void QueueFlowLimit::getState(qpid::framing::FieldTable& state ) const -{ - sys::Mutex::ScopedLock l(indexLock); - state.clear(); - - framing::SequenceSet ss; - if (!index.empty()) { - /* replicate the set of messages pending flow control */ - for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::const_iterator itr = index.begin(); - itr != index.end(); ++itr) { - ss.add(itr->first); - } - framing::Array seqs(TYPE_CODE_UINT32); - typedef boost::function<void(framing::SequenceNumber, framing::SequenceNumber)> arrayBuilder; - ss.for_each((arrayBuilder)boost::bind(&buildSeqRangeArray, &seqs, _1, _2)); - state.setArray("pendingMsgSeqs", seqs); - } - QPID_LOG(debug, "Queue \"" << queueName << "\": flow limit replicating pending msgs, range=" << ss); -} - - -/** called on UPDATEE to set state from snapshot */ -void QueueFlowLimit::setState(const qpid::framing::FieldTable& state) -{ - sys::Mutex::ScopedLock l(indexLock); - index.clear(); - - framing::SequenceSet fcmsg; - framing::Array seqArray(TYPE_CODE_UINT32); - if (state.getArray("pendingMsgSeqs", seqArray)) { - assert((seqArray.count() & 0x01) == 0); // must be even since they are sequence ranges - framing::Array::const_iterator i = seqArray.begin(); - while (i != seqArray.end()) { - framing::SequenceNumber first((*i)->getIntegerValue<uint32_t, 4>()); - ++i; - framing::SequenceNumber last((*i)->getIntegerValue<uint32_t, 4>()); - ++i; - fcmsg.add(first, last); - for (SequenceNumber seq = first; seq <= last; ++seq) { - QueuedMessage msg(queue->find(seq)); // fyi: msg.payload may be null if msg is delivered & unacked - bool unique; - unique = index.insert(std::pair<framing::SequenceNumber, boost::intrusive_ptr<Message> >(seq, msg.payload)).second; - assert(unique); - } - } - } - - flowStopped = index.size() != 0; - if (queueMgmtObj) { - queueMgmtObj->set_flowStopped(isFlowControlActive()); - } - QPID_LOG(debug, "Queue \"" << queueName << "\": flow limit replicated the pending msgs, range=" << fcmsg) -} - - -namespace qpid { - namespace broker { - -std::ostream& operator<<(std::ostream& out, const QueueFlowLimit& f) -{ - out << "; flowStopCount=" << f.flowStopCount << ", flowResumeCount=" << f.flowResumeCount; - out << "; flowStopSize=" << f.flowStopSize << ", flowResumeSize=" << f.flowResumeSize; - return out; -} - - } -} - diff --git a/cpp/src/qpid/broker/QueueFlowLimit.h b/cpp/src/qpid/broker/QueueFlowLimit.h deleted file mode 100644 index c02e479976..0000000000 --- a/cpp/src/qpid/broker/QueueFlowLimit.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueueFlowLimit_ -#define _QueueFlowLimit_ - -#include <list> -#include <set> -#include <iostream> -#include <memory> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/broker/StatefulQueueObserver.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" - -namespace qmf { -namespace org { -namespace apache { -namespace qpid { -namespace broker { - class Queue; -}}}}} -namespace _qmfBroker = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -class Broker; - -/** - * Producer flow control: when level is > flowStop*, flow control is ON. - * then level is < flowResume*, flow control is OFF. If == 0, flow control - * is not used. If both byte and msg count thresholds are set, then - * passing _either_ level may turn flow control ON, but _both_ must be - * below level before flow control will be turned OFF. - */ - class QueueFlowLimit : public StatefulQueueObserver -{ - static uint64_t defaultMaxSize; - static uint defaultFlowStopRatio; - static uint defaultFlowResumeRatio; - - Queue *queue; - std::string queueName; - - uint32_t flowStopCount; - uint32_t flowResumeCount; - uint64_t flowStopSize; - uint64_t flowResumeSize; - bool flowStopped; // true = producers held in flow control - - // current queue utilization - uint32_t count; - uint64_t size; - - public: - static QPID_BROKER_EXTERN const std::string flowStopCountKey; - static QPID_BROKER_EXTERN const std::string flowResumeCountKey; - static QPID_BROKER_EXTERN const std::string flowStopSizeKey; - static QPID_BROKER_EXTERN const std::string flowResumeSizeKey; - - QPID_BROKER_EXTERN virtual ~QueueFlowLimit(); - - /** the queue has added QueuedMessage. Returns true if flow state changes */ - QPID_BROKER_EXTERN void enqueued(const QueuedMessage&); - /** the queue has removed QueuedMessage. Returns true if flow state changes */ - QPID_BROKER_EXTERN void dequeued(const QueuedMessage&); - - /** for clustering: */ - QPID_BROKER_EXTERN void getState(qpid::framing::FieldTable&) const; - QPID_BROKER_EXTERN void setState(const qpid::framing::FieldTable&); - - uint32_t getFlowStopCount() const { return flowStopCount; } - uint32_t getFlowResumeCount() const { return flowResumeCount; } - uint64_t getFlowStopSize() const { return flowStopSize; } - uint64_t getFlowResumeSize() const { return flowResumeSize; } - - uint32_t getFlowCount() const { return count; } - uint64_t getFlowSize() const { return size; } - bool isFlowControlActive() const { return flowStopped; } - bool monitorFlowControl() const { return flowStopCount || flowStopSize; } - - void encode(framing::Buffer& buffer) const; - void decode(framing::Buffer& buffer); - uint32_t encodedSize() const; - - static QPID_BROKER_EXTERN void observe(Queue& queue, const qpid::framing::FieldTable& settings); - static QPID_BROKER_EXTERN void setDefaults(uint64_t defaultMaxSize, uint defaultFlowStopRatio, uint defaultFlowResumeRatio); - - friend QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream&, const QueueFlowLimit&); - - protected: - // msgs waiting for flow to become available. - std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> > index; - mutable qpid::sys::Mutex indexLock; - - _qmfBroker::Queue *queueMgmtObj; - - const Broker *broker; - - QPID_BROKER_EXTERN QueueFlowLimit(Queue *queue, - uint32_t flowStopCount, uint32_t flowResumeCount, - uint64_t flowStopSize, uint64_t flowResumeSize); - static QPID_BROKER_EXTERN QueueFlowLimit *createLimit(Queue *queue, const qpid::framing::FieldTable& settings); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/QueueListeners.cpp b/cpp/src/qpid/broker/QueueListeners.cpp deleted file mode 100644 index 591f4443bb..0000000000 --- a/cpp/src/qpid/broker/QueueListeners.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueListeners.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace broker { - -void QueueListeners::addListener(Consumer::shared_ptr c) -{ - if (!c->inListeners) { - if (c->acquires) { - add(consumers, c); - } else { - add(browsers, c); - } - c->inListeners = true; - } -} - -void QueueListeners::removeListener(Consumer::shared_ptr c) -{ - if (c->inListeners) { - if (c->acquires) { - remove(consumers, c); - } else { - remove(browsers, c); - } - c->inListeners = false; - } -} - -void QueueListeners::populate(NotificationSet& set) -{ - if (consumers.size()) { - set.consumer = consumers.front(); - consumers.pop_front(); - set.consumer->inListeners = false; - } else { - // Don't swap the deques, hang on to the memory allocated. - set.browsers = browsers; - browsers.clear(); - for (Listeners::iterator i = set.browsers.begin(); i != set.browsers.end(); i++) - (*i)->inListeners = false; - } -} - -void QueueListeners::add(Listeners& listeners, Consumer::shared_ptr c) -{ - listeners.push_back(c); -} - -void QueueListeners::remove(Listeners& listeners, Consumer::shared_ptr c) -{ - Listeners::iterator i = std::find(listeners.begin(), listeners.end(), c); - if (i != listeners.end()) listeners.erase(i); -} - -void QueueListeners::NotificationSet::notify() -{ - if (consumer) consumer->notify(); - else std::for_each(browsers.begin(), browsers.end(), boost::mem_fn(&Consumer::notify)); -} - -bool QueueListeners::contains(Consumer::shared_ptr c) const { - return c->inListeners; -} - -void QueueListeners::ListenerSet::notifyAll() -{ - std::for_each(listeners.begin(), listeners.end(), boost::mem_fn(&Consumer::notify)); -} - -void QueueListeners::snapshot(ListenerSet& set) -{ - set.listeners.insert(set.listeners.end(), consumers.begin(), consumers.end()); - set.listeners.insert(set.listeners.end(), browsers.begin(), browsers.end()); -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/QueueListeners.h b/cpp/src/qpid/broker/QueueListeners.h deleted file mode 100644 index 0659499253..0000000000 --- a/cpp/src/qpid/broker/QueueListeners.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef QPID_BROKER_QUEUELISTENERS_H -#define QPID_BROKER_QUEUELISTENERS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Consumer.h" -#include <deque> - -namespace qpid { -namespace broker { - -/** - * Track and notify components that wish to be notified of messages - * that become available on a queue. - * - * None of the methods defined here are protected by locking. However - * the populate method allows a 'snapshot' to be taken of the - * listeners to be notified. NotificationSet::notify() may then be - * called outside of any lock that protects the QueueListeners - * instance from concurrent access. - */ -class QueueListeners -{ - public: - typedef std::deque<Consumer::shared_ptr> Listeners; - - class NotificationSet - { - public: - void notify(); - private: - Listeners browsers; - Consumer::shared_ptr consumer; - friend class QueueListeners; - }; - - class ListenerSet - { - public: - void notifyAll(); - private: - Listeners listeners; - friend class QueueListeners; - }; - - void addListener(Consumer::shared_ptr); - void removeListener(Consumer::shared_ptr); - void populate(NotificationSet&); - void snapshot(ListenerSet&); - bool contains(Consumer::shared_ptr c) const; - void notifyAll(); - - template <class F> void eachListener(F f) { - std::for_each(browsers.begin(), browsers.end(), f); - std::for_each(consumers.begin(), consumers.end(), f); - } - - private: - Listeners consumers; - Listeners browsers; - - void add(Listeners&, Consumer::shared_ptr); - void remove(Listeners&, Consumer::shared_ptr); - -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUELISTENERS_H*/ diff --git a/cpp/src/qpid/broker/QueueObserver.h b/cpp/src/qpid/broker/QueueObserver.h deleted file mode 100644 index 3ca01c051e..0000000000 --- a/cpp/src/qpid/broker/QueueObserver.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_BROKER_QUEUEOBSERVER_H -#define QPID_BROKER_QUEUEOBSERVER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -namespace qpid { -namespace broker { - -struct QueuedMessage; -/** - * Interface for notifying classes who want to act as 'observers' of a - * queue of particular events. - */ -class QueueObserver -{ - public: - virtual ~QueueObserver() {} - virtual void enqueued(const QueuedMessage&) = 0; - virtual void dequeued(const QueuedMessage&) = 0; - private: -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUEOBSERVER_H*/ diff --git a/cpp/src/qpid/broker/QueuePolicy.cpp b/cpp/src/qpid/broker/QueuePolicy.cpp deleted file mode 100644 index a93a6332fd..0000000000 --- a/cpp/src/qpid/broker/QueuePolicy.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueuePolicy.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/PriorityQueue.h" -#include "qpid/Exception.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include <sstream> - -using namespace qpid::broker; -using namespace qpid::framing; - -QueuePolicy::QueuePolicy(const std::string& _name, uint32_t _maxCount, uint64_t _maxSize, const std::string& _type) : - maxCount(_maxCount), maxSize(_maxSize), type(_type), count(0), size(0), policyExceeded(false), name(_name) { - QPID_LOG(info, "Queue \"" << name << "\": Policy created: type=" << type << "; maxCount=" << maxCount << "; maxSize=" << maxSize); -} - -void QueuePolicy::enqueued(uint64_t _size) -{ - if (maxCount) ++count; - if (maxSize) size += _size; -} - -void QueuePolicy::dequeued(uint64_t _size) -{ - if (maxCount) { - if (count > 0) { - --count; - } else { - throw Exception(QPID_MSG("Attempted count underflow on dequeue(" << _size << "): " << *this)); - } - } - if (maxSize) { - if (_size > size) { - throw Exception(QPID_MSG("Attempted size underflow on dequeue(" << _size << "): " << *this)); - } else { - size -= _size; - } - } -} - -bool QueuePolicy::checkLimit(boost::intrusive_ptr<Message> m) -{ - bool sizeExceeded = maxSize && (size + m->contentSize()) > maxSize; - bool countExceeded = maxCount && (count + 1) > maxCount; - bool exceeded = sizeExceeded || countExceeded; - if (exceeded) { - if (!policyExceeded) { - policyExceeded = true; - if (sizeExceeded) QPID_LOG(info, "Queue cumulative message size exceeded policy for " << name); - if (countExceeded) QPID_LOG(info, "Queue message count exceeded policy for " << name); - } - } else { - if (policyExceeded) { - policyExceeded = false; - QPID_LOG(info, "Queue cumulative message size and message count within policy for " << name); - } - } - return !exceeded; -} - -void QueuePolicy::tryEnqueue(boost::intrusive_ptr<Message> m) -{ - if (checkLimit(m)) { - enqueued(m->contentSize()); - } else { - throw ResourceLimitExceededException(QPID_MSG("Policy exceeded on " << name << ", policy: " << *this)); - } -} - -void QueuePolicy::recoverEnqueued(boost::intrusive_ptr<Message> m) -{ - tryEnqueue(m); -} - -void QueuePolicy::enqueueAborted(boost::intrusive_ptr<Message> m) -{ - dequeued(m->contentSize()); -} - -void QueuePolicy::enqueued(const QueuedMessage&) {} - -void QueuePolicy::dequeued(const QueuedMessage& m) -{ - dequeued(m.payload->contentSize()); -} - -bool QueuePolicy::isEnqueued(const QueuedMessage&) -{ - return true; -} - -void QueuePolicy::update(FieldTable& settings) -{ - if (maxCount) settings.setInt(maxCountKey, maxCount); - if (maxSize) settings.setInt(maxSizeKey, maxSize); - settings.setString(typeKey, type); -} - -uint32_t QueuePolicy::getCapacity(const FieldTable& settings, const std::string& key, uint32_t defaultValue) -{ - FieldTable::ValuePtr v = settings.get(key); - - int32_t result = 0; - - if (!v) return defaultValue; - if (v->getType() == 0x23) { - QPID_LOG(debug, "Value for " << key << " specified as float: " << v->get<float>()); - } else if (v->getType() == 0x33) { - QPID_LOG(debug, "Value for " << key << " specified as double: " << v->get<double>()); - } else if (v->convertsTo<int>()) { - result = v->get<int>(); - QPID_LOG(debug, "Got integer value for " << key << ": " << result); - if (result >= 0) return result; - } else if (v->convertsTo<string>()) { - string s(v->get<string>()); - QPID_LOG(debug, "Got string value for " << key << ": " << s); - std::istringstream convert(s); - if (convert >> result && result >= 0 && convert.eof()) return result; - } - - throw IllegalArgumentException(QPID_MSG("Cannot convert " << key << " to unsigned integer: " << *v)); -} - -std::string QueuePolicy::getType(const FieldTable& settings) -{ - FieldTable::ValuePtr v = settings.get(typeKey); - if (v && v->convertsTo<std::string>()) { - std::string t = v->get<std::string>(); - std::transform(t.begin(), t.end(), t.begin(), tolower); - if (t == REJECT || t == FLOW_TO_DISK || t == RING || t == RING_STRICT) return t; - } - return REJECT; -} - -void QueuePolicy::setDefaultMaxSize(uint64_t s) -{ - defaultMaxSize = s; -} - -void QueuePolicy::getPendingDequeues(Messages&) {} - - - - -void QueuePolicy::encode(Buffer& buffer) const -{ - buffer.putLong(maxCount); - buffer.putLongLong(maxSize); - buffer.putLong(count); - buffer.putLongLong(size); -} - -void QueuePolicy::decode ( Buffer& buffer ) -{ - maxCount = buffer.getLong(); - maxSize = buffer.getLongLong(); - count = buffer.getLong(); - size = buffer.getLongLong(); -} - - -uint32_t QueuePolicy::encodedSize() const { - return sizeof(uint32_t) + // maxCount - sizeof(uint64_t) + // maxSize - sizeof(uint32_t) + // count - sizeof(uint64_t); // size -} - - - -const std::string QueuePolicy::maxCountKey("qpid.max_count"); -const std::string QueuePolicy::maxSizeKey("qpid.max_size"); -const std::string QueuePolicy::typeKey("qpid.policy_type"); -const std::string QueuePolicy::REJECT("reject"); -const std::string QueuePolicy::FLOW_TO_DISK("flow_to_disk"); -const std::string QueuePolicy::RING("ring"); -const std::string QueuePolicy::RING_STRICT("ring_strict"); -uint64_t QueuePolicy::defaultMaxSize(0); - -FlowToDiskPolicy::FlowToDiskPolicy(const std::string& _name, uint32_t _maxCount, uint64_t _maxSize) : - QueuePolicy(_name, _maxCount, _maxSize, FLOW_TO_DISK) {} - -bool FlowToDiskPolicy::checkLimit(boost::intrusive_ptr<Message> m) -{ - if (!QueuePolicy::checkLimit(m)) m->requestContentRelease(); - return true; -} - -RingQueuePolicy::RingQueuePolicy(const std::string& _name, - uint32_t _maxCount, uint64_t _maxSize, const std::string& _type) : - QueuePolicy(_name, _maxCount, _maxSize, _type), strict(_type == RING_STRICT) {} - -bool before(const QueuedMessage& a, const QueuedMessage& b) -{ - int priorityA = PriorityQueue::getPriority(a); - int priorityB = PriorityQueue::getPriority(b); - if (priorityA == priorityB) return a.position < b.position; - else return priorityA < priorityB; -} - -void RingQueuePolicy::enqueued(const QueuedMessage& m) -{ - //need to insert in correct location based on position - queue.insert(lower_bound(queue.begin(), queue.end(), m, before), m); -} - -void RingQueuePolicy::dequeued(const QueuedMessage& m) -{ - //find and remove m from queue - if (find(m, pendingDequeues, true) || find(m, queue, true)) { - //now update count and size - QueuePolicy::dequeued(m); - } -} - -bool RingQueuePolicy::isEnqueued(const QueuedMessage& m) -{ - //for non-strict ring policy, a message can be replaced (and - //therefore dequeued) before it is accepted or released by - //subscriber; need to detect this - return find(m, pendingDequeues, false) || find(m, queue, false); -} - -bool RingQueuePolicy::checkLimit(boost::intrusive_ptr<Message> m) -{ - - // If the message is bigger than the queue size, give up - if (getMaxSize() && m->contentSize() > getMaxSize()) { - QPID_LOG(debug, "Message too large for ring queue " << name - << " [" << *this << "] " - << ": message size = " << m->contentSize() << " bytes" - << ": max queue size = " << getMaxSize() << " bytes"); - return false; - } - - // if within limits, ok to accept - if (QueuePolicy::checkLimit(m)) return true; - - // At this point, we've exceeded maxSize, maxCount, or both. - // - // If we've exceeded maxCount, we've exceeded it by 1, so - // replacing the first message is sufficient. If we've exceeded - // maxSize, we need to pop enough messages to get the space we - // need. - - unsigned int haveSpace = getMaxSize() - getCurrentQueueSize(); - - do { - QueuedMessage oldest = queue.front(); - - if (oldest.queue->acquire(oldest) || !strict) { - queue.pop_front(); - pendingDequeues.push_back(oldest); - QPID_LOG(debug, "Ring policy triggered in " << name - << ": removed message " << oldest.position << " to make way for new message"); - - haveSpace += oldest.payload->contentSize(); - - } else { - //in strict mode, if oldest message has been delivered (hence - //cannot be acquired) but not yet acked, it should not be - //removed and the attempted enqueue should fail - QPID_LOG(debug, "Ring policy could not be triggered in " << name - << ": oldest message (seq-no=" << oldest.position << ") has been delivered but not yet acknowledged or requeued"); - return false; - } - } while (haveSpace < m->contentSize()); - - - return true; -} - -void RingQueuePolicy::getPendingDequeues(Messages& result) -{ - result = pendingDequeues; -} - -bool RingQueuePolicy::find(const QueuedMessage& m, Messages& q, bool remove) -{ - for (Messages::iterator i = q.begin(); i != q.end(); i++) { - if (i->payload == m.payload) { - if (remove) q.erase(i); - return true; - } - } - return false; -} - -std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(uint32_t maxCount, uint64_t maxSize, const std::string& type) -{ - return createQueuePolicy("<unspecified>", maxCount, maxSize, type); -} - -std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const qpid::framing::FieldTable& settings) -{ - return createQueuePolicy("<unspecified>", settings); -} - -std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const std::string& name, const qpid::framing::FieldTable& settings) -{ - uint32_t maxCount = getCapacity(settings, maxCountKey, 0); - uint32_t maxSize = getCapacity(settings, maxSizeKey, defaultMaxSize); - if (maxCount || maxSize) { - return createQueuePolicy(name, maxCount, maxSize, getType(settings)); - } else { - return std::auto_ptr<QueuePolicy>(); - } -} - -std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const std::string& name, - uint32_t maxCount, uint64_t maxSize, const std::string& type) -{ - if (type == RING || type == RING_STRICT) { - return std::auto_ptr<QueuePolicy>(new RingQueuePolicy(name, maxCount, maxSize, type)); - } else if (type == FLOW_TO_DISK) { - return std::auto_ptr<QueuePolicy>(new FlowToDiskPolicy(name, maxCount, maxSize)); - } else { - return std::auto_ptr<QueuePolicy>(new QueuePolicy(name, maxCount, maxSize, type)); - } - -} - -namespace qpid { - namespace broker { - -std::ostream& operator<<(std::ostream& out, const QueuePolicy& p) -{ - if (p.maxSize) out << "size: max=" << p.maxSize << ", current=" << p.size; - else out << "size: unlimited"; - out << "; "; - if (p.maxCount) out << "count: max=" << p.maxCount << ", current=" << p.count; - else out << "count: unlimited"; - out << "; type=" << p.type; - return out; -} - - } -} - diff --git a/cpp/src/qpid/broker/QueuePolicy.h b/cpp/src/qpid/broker/QueuePolicy.h deleted file mode 100644 index 3cdd63784d..0000000000 --- a/cpp/src/qpid/broker/QueuePolicy.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueuePolicy_ -#define _QueuePolicy_ - -#include <deque> -#include <iostream> -#include <memory> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace broker { - -class QueuePolicy -{ - static uint64_t defaultMaxSize; - - uint32_t maxCount; - uint64_t maxSize; - const std::string type; - uint32_t count; - uint64_t size; - bool policyExceeded; - - static uint32_t getCapacity(const qpid::framing::FieldTable& settings, const std::string& key, uint32_t defaultValue); - - protected: - uint64_t getCurrentQueueSize() const { return size; } - - public: - typedef std::deque<QueuedMessage> Messages; - static QPID_BROKER_EXTERN const std::string maxCountKey; - static QPID_BROKER_EXTERN const std::string maxSizeKey; - static QPID_BROKER_EXTERN const std::string typeKey; - static QPID_BROKER_EXTERN const std::string REJECT; - static QPID_BROKER_EXTERN const std::string FLOW_TO_DISK; - static QPID_BROKER_EXTERN const std::string RING; - static QPID_BROKER_EXTERN const std::string RING_STRICT; - - virtual ~QueuePolicy() {} - QPID_BROKER_EXTERN void tryEnqueue(boost::intrusive_ptr<Message> msg); - QPID_BROKER_EXTERN void recoverEnqueued(boost::intrusive_ptr<Message> msg); - QPID_BROKER_EXTERN void enqueueAborted(boost::intrusive_ptr<Message> msg); - virtual void enqueued(const QueuedMessage&); - virtual void dequeued(const QueuedMessage&); - virtual bool isEnqueued(const QueuedMessage&); - QPID_BROKER_EXTERN void update(qpid::framing::FieldTable& settings); - uint32_t getMaxCount() const { return maxCount; } - uint64_t getMaxSize() const { return maxSize; } - void encode(framing::Buffer& buffer) const; - void decode ( framing::Buffer& buffer ); - uint32_t encodedSize() const; - virtual void getPendingDequeues(Messages& result); - - static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(const std::string& name, const qpid::framing::FieldTable& settings); - static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT); - static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(const qpid::framing::FieldTable& settings); - static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT); - static std::string getType(const qpid::framing::FieldTable& settings); - static void setDefaultMaxSize(uint64_t); - friend QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream&, - const QueuePolicy&); - protected: - const std::string name; - - QueuePolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT); - - virtual bool checkLimit(boost::intrusive_ptr<Message> msg); - void enqueued(uint64_t size); - void dequeued(uint64_t size); -}; - - -class FlowToDiskPolicy : public QueuePolicy -{ - public: - FlowToDiskPolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize); - bool checkLimit(boost::intrusive_ptr<Message> msg); -}; - -class RingQueuePolicy : public QueuePolicy -{ - public: - RingQueuePolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize, const std::string& type = RING); - void enqueued(const QueuedMessage&); - void dequeued(const QueuedMessage&); - bool isEnqueued(const QueuedMessage&); - bool checkLimit(boost::intrusive_ptr<Message> msg); - void getPendingDequeues(Messages& result); - private: - Messages pendingDequeues; - Messages queue; - const bool strict; - - bool find(const QueuedMessage&, Messages&, bool remove); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/QueueRegistry.cpp b/cpp/src/qpid/broker/QueueRegistry.cpp deleted file mode 100644 index 135a3543d9..0000000000 --- a/cpp/src/qpid/broker/QueueRegistry.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/QueueEvents.h" -#include "qpid/broker/Exchange.h" -#include "qpid/log/Statement.h" -#include <sstream> -#include <assert.h> - -using namespace qpid::broker; -using namespace qpid::sys; -using std::string; - -QueueRegistry::QueueRegistry(Broker* b) : - counter(1), store(0), events(0), parent(0), lastNode(false), broker(b) {} - -QueueRegistry::~QueueRegistry(){} - -std::pair<Queue::shared_ptr, bool> -QueueRegistry::declare(const string& declareName, bool durable, - bool autoDelete, const OwnershipToken* owner, - boost::shared_ptr<Exchange> alternate, - const qpid::framing::FieldTable& arguments, - bool recovering/*true if this declare is a - result of recovering queue - definition from persistente - record*/) -{ - RWlock::ScopedWlock locker(lock); - string name = declareName.empty() ? generateName() : declareName; - assert(!name.empty()); - QueueMap::iterator i = queues.find(name); - - if (i == queues.end()) { - Queue::shared_ptr queue(new Queue(name, autoDelete, durable ? store : 0, owner, parent, broker)); - if (alternate) { - queue->setAlternateExchange(alternate);//need to do this *before* create - alternate->incAlternateUsers(); - } - if (!recovering) { - //apply settings & create persistent record if required - queue->create(arguments); - } else { - //i.e. recovering a queue for which we already have a persistent record - queue->configure(arguments); - } - queues[name] = queue; - if (lastNode) queue->setLastNodeFailure(); - - return std::pair<Queue::shared_ptr, bool>(queue, true); - } else { - return std::pair<Queue::shared_ptr, bool>(i->second, false); - } -} - -void QueueRegistry::destroyLH (const string& name){ - queues.erase(name); -} - -void QueueRegistry::destroy (const string& name){ - RWlock::ScopedWlock locker(lock); - destroyLH (name); -} - -Queue::shared_ptr QueueRegistry::find(const string& name){ - RWlock::ScopedRlock locker(lock); - QueueMap::iterator i = queues.find(name); - - if (i == queues.end()) { - return Queue::shared_ptr(); - } else { - return i->second; - } -} - -string QueueRegistry::generateName(){ - string name; - do { - std::stringstream ss; - ss << "tmp_" << counter++; - name = ss.str(); - // Thread safety: Private function, only called with lock held - // so this is OK. - } while(queues.find(name) != queues.end()); - return name; -} - -void QueueRegistry::setStore (MessageStore* _store) -{ - store = _store; -} - -MessageStore* QueueRegistry::getStore() const { - return store; -} - -void QueueRegistry::updateQueueClusterState(bool _lastNode) -{ - RWlock::ScopedRlock locker(lock); - for (QueueMap::iterator i = queues.begin(); i != queues.end(); i++) { - if (_lastNode){ - i->second->setLastNodeFailure(); - } else { - i->second->clearLastNodeFailure(); - } - } - lastNode = _lastNode; -} diff --git a/cpp/src/qpid/broker/QueueRegistry.h b/cpp/src/qpid/broker/QueueRegistry.h deleted file mode 100644 index 8a32a64f05..0000000000 --- a/cpp/src/qpid/broker/QueueRegistry.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueueRegistry_ -#define _QueueRegistry_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/sys/Mutex.h" -#include "qpid/management/Manageable.h" -#include "qpid/framing/FieldTable.h" -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <algorithm> -#include <map> - -namespace qpid { -namespace broker { - -class Queue; -class QueueEvents; -class Exchange; -class OwnershipToken; -class Broker; -class MessageStore; - -/** - * A registry of queues indexed by queue name. - * - * Queues are reference counted using shared_ptr to ensure that they - * are deleted when and only when they are no longer in use. - * - */ -class QueueRegistry { - public: - QPID_BROKER_EXTERN QueueRegistry(Broker* b = 0); - QPID_BROKER_EXTERN ~QueueRegistry(); - - /** - * Declare a queue. - * - * @return The queue and a boolean flag which is true if the queue - * was created by this declare call false if it already existed. - */ - QPID_BROKER_EXTERN std::pair<boost::shared_ptr<Queue>, bool> declare( - const std::string& name, - bool durable = false, - bool autodelete = false, - const OwnershipToken* owner = 0, - boost::shared_ptr<Exchange> alternateExchange = boost::shared_ptr<Exchange>(), - const qpid::framing::FieldTable& args = framing::FieldTable(), - bool recovering = false); - - /** - * Destroy the named queue. - * - * Note: if the queue is in use it is not actually destroyed until - * all shared_ptrs to it are destroyed. During that time it is - * possible that a new queue with the same name may be - * created. This should not create any problems as the new and - * old queues exist independently. The registry has - * forgotten the old queue so there can be no confusion for - * subsequent calls to find or declare with the same name. - * - */ - QPID_BROKER_EXTERN void destroy(const std::string& name); - template <class Test> bool destroyIf(const std::string& name, Test test) - { - qpid::sys::RWlock::ScopedWlock locker(lock); - if (test()) { - destroyLH (name); - return true; - } else { - return false; - } - } - - /** - * Find the named queue. Return 0 if not found. - */ - QPID_BROKER_EXTERN boost::shared_ptr<Queue> find(const std::string& name); - - /** - * Generate unique queue name. - */ - std::string generateName(); - - /** - * Set the store to use. May only be called once. - */ - void setStore (MessageStore*); - - /** - * Return the message store used. - */ - MessageStore* getStore() const; - - /** - * Register the manageable parent for declared queues - */ - void setParent (management::Manageable* _parent) { parent = _parent; } - - /** Call f for each queue in the registry. */ - template <class F> void eachQueue(F f) const { - qpid::sys::RWlock::ScopedRlock l(lock); - for (QueueMap::const_iterator i = queues.begin(); i != queues.end(); ++i) - f(i->second); - } - - /** - * Change queue mode when cluster size drops to 1 node, expands again - * in practice allows flow queue to disk when last name to be exectuted - */ - void updateQueueClusterState(bool lastNode); - -private: - typedef std::map<std::string, boost::shared_ptr<Queue> > QueueMap; - QueueMap queues; - mutable qpid::sys::RWlock lock; - int counter; - MessageStore* store; - QueueEvents* events; - management::Manageable* parent; - bool lastNode; //used to set mode on queue declare - Broker* broker; - - //destroy impl that assumes lock is already held: - void destroyLH (const std::string& name); -}; - - -}} // namespace qpid::broker - - -#endif diff --git a/cpp/src/qpid/broker/QueuedMessage.h b/cpp/src/qpid/broker/QueuedMessage.h deleted file mode 100644 index 35e48b11f3..0000000000 --- a/cpp/src/qpid/broker/QueuedMessage.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueuedMessage_ -#define _QueuedMessage_ - -#include "qpid/broker/Message.h" - -namespace qpid { -namespace broker { - -class Queue; - -struct QueuedMessage -{ - boost::intrusive_ptr<Message> payload; - framing::SequenceNumber position; - Queue* queue; - - QueuedMessage() : queue(0) {} - QueuedMessage(Queue* q, boost::intrusive_ptr<Message> msg, framing::SequenceNumber sn) : - payload(msg), position(sn), queue(q) {} - QueuedMessage(Queue* q) : queue(q) {} - -}; - inline bool operator<(const QueuedMessage& a, const QueuedMessage& b) { return a.position < b.position; } - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RateFlowcontrol.h b/cpp/src/qpid/broker/RateFlowcontrol.h deleted file mode 100644 index 99f9d2c0c4..0000000000 --- a/cpp/src/qpid/broker/RateFlowcontrol.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef broker_RateFlowcontrol_h -#define broker_RateFlowcontrol_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Time.h" -#include "qpid/sys/IntegerTypes.h" - -#include <algorithm> - -namespace qpid { -namespace broker { - -// Class to keep track of issuing flow control to make sure that the peer doesn't exceed -// a given message rate -// -// Create the object with the target rate -// Then call sendCredit() whenever credit is issued to the peer -// Call receivedMessage() whenever a message is received, it returns the credit to issue. -// -// sentCredit() be sensibly called with a 0 parameter to indicate -// that we sent credit but treat it as if the value was 0 (we may do this at the start of the connection -// to allow our peer to send messages) -// -// receivedMessage() can be called with 0 to indicate that we've not received a message, but -// tell me what credit I can send. -class RateFlowcontrol { - uint32_t rate; // messages per second - uint32_t maxCredit; // max credit issued to client (issued at start) - uint32_t requestedCredit; - qpid::sys::AbsTime creditSent; - -public: - RateFlowcontrol(uint32_t r) : - rate(r), - maxCredit(0), - requestedCredit(0), - creditSent(qpid::sys::FAR_FUTURE) - {} - - uint32_t getRate() const { - return rate; - } - void sentCredit(const qpid::sys::AbsTime& t, uint32_t credit); - uint32_t receivedMessage(const qpid::sys::AbsTime& t, uint32_t msgs); - uint32_t availableCredit(const qpid::sys::AbsTime& t); - bool flowStopped() const; -}; - -inline void RateFlowcontrol::sentCredit(const qpid::sys::AbsTime& t, uint32_t credit) { - // If the client isn't currently requesting credit (ie it's not sent us anything yet) then - // this credit goes to the max credit held by the client (it can't go to reduce credit - // less than 0) - int32_t nextRequestedCredit = requestedCredit - credit; - if ( nextRequestedCredit<0 ) { - requestedCredit = 0; - maxCredit -= nextRequestedCredit; - } else { - requestedCredit = nextRequestedCredit; - } - creditSent = t; -} - -inline uint32_t RateFlowcontrol::availableCredit(const qpid::sys::AbsTime& t) { - qpid::sys::Duration d(creditSent, t); - // Could be -ve before first sentCredit - int64_t toSend = std::min(rate * d / qpid::sys::TIME_SEC, static_cast<int64_t>(requestedCredit)); - return toSend > 0 ? toSend : 0; -} - -inline uint32_t RateFlowcontrol::receivedMessage(const qpid::sys::AbsTime& t, uint32_t msgs) { - requestedCredit +=msgs; - // Don't send credit for every message, only send if more than 0.5s since last credit or - // we've got less than .25 of the max left (heuristic) - return requestedCredit*4 >= maxCredit*3 || qpid::sys::Duration(creditSent, t) >= 500*qpid::sys::TIME_MSEC - ? availableCredit(t) - : 0; -} - -inline bool RateFlowcontrol::flowStopped() const { - return requestedCredit >= maxCredit; -} - -}} - -#endif // broker_RateFlowcontrol_h diff --git a/cpp/src/qpid/broker/RateTracker.cpp b/cpp/src/qpid/broker/RateTracker.cpp deleted file mode 100644 index 048349b658..0000000000 --- a/cpp/src/qpid/broker/RateTracker.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/RateTracker.h" - -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::sys::TIME_SEC; - -namespace qpid { -namespace broker { - -RateTracker::RateTracker() : currentCount(0), lastCount(0), lastTime(AbsTime::now()) {} - -RateTracker& RateTracker::operator++() -{ - ++currentCount; - return *this; -} - -double RateTracker::sampleRatePerSecond() -{ - int32_t increment = currentCount - lastCount; - AbsTime now = AbsTime::now(); - Duration interval(lastTime, now); - lastCount = currentCount; - lastTime = now; - //if sampling at higher frequency than supported, will just return the number of increments - if (interval < TIME_SEC) return increment; - else if (increment == 0) return 0; - else return increment / (interval / TIME_SEC); -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/RateTracker.h b/cpp/src/qpid/broker/RateTracker.h deleted file mode 100644 index 0c20b37312..0000000000 --- a/cpp/src/qpid/broker/RateTracker.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QPID_BROKER_RATETRACKER_H -#define QPID_BROKER_RATETRACKER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Time.h" - -namespace qpid { -namespace broker { - -/** - * Simple rate tracker: represents some value that can be incremented, - * then can periodcially sample the rate of increments. - */ -class RateTracker -{ - public: - RateTracker(); - /** - * Increments the count being tracked. Can be called concurrently - * with other calls to this operator as well as with calls to - * sampleRatePerSecond(). - */ - RateTracker& operator++(); - /** - * Returns the rate of increments per second since last - * called. Calls to this method should be serialised, but can be - * called concurrently with the increment operator - */ - double sampleRatePerSecond(); - private: - volatile int32_t currentCount; - int32_t lastCount; - qpid::sys::AbsTime lastTime; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_RATETRACKER_H*/ diff --git a/cpp/src/qpid/broker/RecoverableConfig.h b/cpp/src/qpid/broker/RecoverableConfig.h deleted file mode 100644 index 838a8582dc..0000000000 --- a/cpp/src/qpid/broker/RecoverableConfig.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _broker_RecoverableConfig_h -#define _broker_RecoverableConfig_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * The interface through which configurations are recovered. - */ -class RecoverableConfig -{ -public: - typedef boost::shared_ptr<RecoverableConfig> shared_ptr; - - virtual void setPersistenceId(uint64_t id) = 0; - virtual ~RecoverableConfig() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoverableExchange.h b/cpp/src/qpid/broker/RecoverableExchange.h deleted file mode 100644 index ca6cc1541e..0000000000 --- a/cpp/src/qpid/broker/RecoverableExchange.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _broker_RecoverableExchange_h -#define _broker_RecoverableExchange_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include "qpid/framing/FieldTable.h" - -namespace qpid { -namespace broker { - -/** - * The interface through which bindings are recovered. - */ -class RecoverableExchange -{ -public: - typedef boost::shared_ptr<RecoverableExchange> shared_ptr; - - virtual void setPersistenceId(uint64_t id) = 0; - /** - * Recover binding. Nb: queue must have been recovered earlier. - */ - virtual void bind(const std::string& queue, - const std::string& routingKey, - qpid::framing::FieldTable& args) = 0; - virtual ~RecoverableExchange() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoverableMessage.h b/cpp/src/qpid/broker/RecoverableMessage.h deleted file mode 100644 index c98857ceb0..0000000000 --- a/cpp/src/qpid/broker/RecoverableMessage.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _broker_RecoverableMessage_h -#define _broker_RecoverableMessage_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" - -namespace qpid { -namespace broker { - -/** - * The interface through which messages are reloaded on recovery. - */ -class RecoverableMessage -{ -public: - typedef boost::shared_ptr<RecoverableMessage> shared_ptr; - virtual void setPersistenceId(uint64_t id) = 0; - virtual void setRedelivered() = 0; - /** - * Used by store to determine whether to load content on recovery - * or let message load its own content as and when it requires it. - * - * @returns true if the content of the message should be loaded - */ - virtual bool loadContent(uint64_t available) = 0; - /** - * Loads the content held in the supplied buffer (may do checking - * of length as necessary) - */ - virtual void decodeContent(framing::Buffer& buffer) = 0; - virtual ~RecoverableMessage() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoverableQueue.h b/cpp/src/qpid/broker/RecoverableQueue.h deleted file mode 100644 index 49f05f97a1..0000000000 --- a/cpp/src/qpid/broker/RecoverableQueue.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _broker_RecoverableQueue_h -#define _broker_RecoverableQueue_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/RecoverableMessage.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -class ExternalQueueStore; - -/** - * The interface through which messages are added back to queues on - * recovery. - */ -class RecoverableQueue -{ -public: - typedef boost::shared_ptr<RecoverableQueue> shared_ptr; - - virtual void setPersistenceId(uint64_t id) = 0; - virtual uint64_t getPersistenceId() const = 0; - /** - * Used during recovery to add stored messages back to the queue - */ - virtual void recover(RecoverableMessage::shared_ptr msg) = 0; - virtual ~RecoverableQueue() {}; - - virtual const std::string& getName() const = 0; - virtual void setExternalQueueStore(ExternalQueueStore* inst) = 0; - virtual ExternalQueueStore* getExternalQueueStore() const = 0; - -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoverableTransaction.h b/cpp/src/qpid/broker/RecoverableTransaction.h deleted file mode 100644 index 1b7d94bd1a..0000000000 --- a/cpp/src/qpid/broker/RecoverableTransaction.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _broker_RecoverableTransaction_h -#define _broker_RecoverableTransaction_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> - -#include "qpid/broker/RecoverableMessage.h" -#include "qpid/broker/RecoverableQueue.h" - -namespace qpid { -namespace broker { - -/** - * The interface through which prepared 2pc transactions are - * recovered. - */ -class RecoverableTransaction -{ -public: - typedef boost::shared_ptr<RecoverableTransaction> shared_ptr; - virtual void enqueue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) = 0; - virtual void dequeue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) = 0; - virtual ~RecoverableTransaction() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoveredDequeue.cpp b/cpp/src/qpid/broker/RecoveredDequeue.cpp deleted file mode 100644 index cd6735328f..0000000000 --- a/cpp/src/qpid/broker/RecoveredDequeue.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Queue.h" -#include "qpid/broker/RecoveredDequeue.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; - -RecoveredDequeue::RecoveredDequeue(Queue::shared_ptr _queue, intrusive_ptr<Message> _msg) : queue(_queue), msg(_msg) -{ - queue->recoverPrepared(msg); -} - -bool RecoveredDequeue::prepare(TransactionContext*) throw() -{ - //should never be called; transaction has already prepared if an enqueue is recovered - return false; -} - -void RecoveredDequeue::commit() throw() -{ - queue->enqueueAborted(msg); -} - -void RecoveredDequeue::rollback() throw() -{ - queue->process(msg); -} - diff --git a/cpp/src/qpid/broker/RecoveredDequeue.h b/cpp/src/qpid/broker/RecoveredDequeue.h deleted file mode 100644 index 66e66f1d5f..0000000000 --- a/cpp/src/qpid/broker/RecoveredDequeue.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveredDequeue_ -#define _RecoveredDequeue_ - -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/TxOp.h" - -#include <boost/intrusive_ptr.hpp> - -#include <algorithm> -#include <functional> -#include <list> - -namespace qpid { - namespace broker { - class RecoveredDequeue : public TxOp{ - boost::shared_ptr<Queue> queue; - boost::intrusive_ptr<Message> msg; - - public: - RecoveredDequeue(boost::shared_ptr<Queue> queue, boost::intrusive_ptr<Message> msg); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~RecoveredDequeue(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - - boost::shared_ptr<Queue> getQueue() const { return queue; } - boost::intrusive_ptr<Message> getMessage() const { return msg; } - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/RecoveredEnqueue.cpp b/cpp/src/qpid/broker/RecoveredEnqueue.cpp deleted file mode 100644 index 6d2eaee6c4..0000000000 --- a/cpp/src/qpid/broker/RecoveredEnqueue.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Queue.h" -#include "qpid/broker/RecoveredEnqueue.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; - -RecoveredEnqueue::RecoveredEnqueue(Queue::shared_ptr _queue, intrusive_ptr<Message> _msg) : queue(_queue), msg(_msg) -{ - queue->recoverPrepared(msg); -} - -bool RecoveredEnqueue::prepare(TransactionContext*) throw(){ - //should never be called; transaction has already prepared if an enqueue is recovered - return false; -} - -void RecoveredEnqueue::commit() throw(){ - queue->process(msg); -} - -void RecoveredEnqueue::rollback() throw(){ - queue->enqueueAborted(msg); -} - diff --git a/cpp/src/qpid/broker/RecoveredEnqueue.h b/cpp/src/qpid/broker/RecoveredEnqueue.h deleted file mode 100644 index 5f718001d5..0000000000 --- a/cpp/src/qpid/broker/RecoveredEnqueue.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveredEnqueue_ -#define _RecoveredEnqueue_ - -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/TxOp.h" - -#include <boost/intrusive_ptr.hpp> - -#include <algorithm> -#include <functional> -#include <list> - -namespace qpid { -namespace broker { -class RecoveredEnqueue : public TxOp{ - boost::shared_ptr<Queue> queue; - boost::intrusive_ptr<Message> msg; - - public: - RecoveredEnqueue(boost::shared_ptr<Queue> queue, boost::intrusive_ptr<Message> msg); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~RecoveredEnqueue(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - - boost::shared_ptr<Queue> getQueue() const { return queue; } - boost::intrusive_ptr<Message> getMessage() const { return msg; } - -}; -} -} - - -#endif diff --git a/cpp/src/qpid/broker/RecoveryManager.h b/cpp/src/qpid/broker/RecoveryManager.h deleted file mode 100644 index 2929e92250..0000000000 --- a/cpp/src/qpid/broker/RecoveryManager.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveryManager_ -#define _RecoveryManager_ - -#include "qpid/broker/RecoverableExchange.h" -#include "qpid/broker/RecoverableQueue.h" -#include "qpid/broker/RecoverableMessage.h" -#include "qpid/broker/RecoverableTransaction.h" -#include "qpid/broker/RecoverableConfig.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/framing/Buffer.h" - -namespace qpid { -namespace broker { - -class RecoveryManager{ - public: - virtual ~RecoveryManager(){} - virtual RecoverableExchange::shared_ptr recoverExchange(framing::Buffer& buffer) = 0; - virtual RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer) = 0; - virtual RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer) = 0; - virtual RecoverableTransaction::shared_ptr recoverTransaction(const std::string& xid, - std::auto_ptr<TPCTransactionContext> txn) = 0; - virtual RecoverableConfig::shared_ptr recoverConfig(framing::Buffer& buffer) = 0; - - virtual void recoveryComplete() = 0; -}; - -class Recoverable { - public: - virtual ~Recoverable() {} - - /** - * Request recovery of queue and message state. - */ - virtual void recover(RecoveryManager& recoverer) = 0; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp b/cpp/src/qpid/broker/RecoveryManagerImpl.cpp deleted file mode 100644 index d08409695e..0000000000 --- a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/RecoveryManagerImpl.h" - -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/RecoveredEnqueue.h" -#include "qpid/broker/RecoveredDequeue.h" -#include "qpid/framing/reply_exceptions.h" - -using boost::dynamic_pointer_cast; -using boost::intrusive_ptr; -using std::string; - -namespace qpid { -namespace broker { - -RecoveryManagerImpl::RecoveryManagerImpl(QueueRegistry& _queues, ExchangeRegistry& _exchanges, LinkRegistry& _links, - DtxManager& _dtxMgr) - : queues(_queues), exchanges(_exchanges), links(_links), dtxMgr(_dtxMgr) {} - -RecoveryManagerImpl::~RecoveryManagerImpl() {} - -class RecoverableMessageImpl : public RecoverableMessage -{ - intrusive_ptr<Message> msg; -public: - RecoverableMessageImpl(const intrusive_ptr<Message>& _msg); - ~RecoverableMessageImpl() {}; - void setPersistenceId(uint64_t id); - void setRedelivered(); - bool loadContent(uint64_t available); - void decodeContent(framing::Buffer& buffer); - void recover(Queue::shared_ptr queue); - void enqueue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue); - void dequeue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue); -}; - -class RecoverableQueueImpl : public RecoverableQueue -{ - Queue::shared_ptr queue; -public: - RecoverableQueueImpl(const boost::shared_ptr<Queue>& _queue) : queue(_queue) {} - ~RecoverableQueueImpl() {}; - void setPersistenceId(uint64_t id); - uint64_t getPersistenceId() const; - const std::string& getName() const; - void setExternalQueueStore(ExternalQueueStore* inst); - ExternalQueueStore* getExternalQueueStore() const; - void recover(RecoverableMessage::shared_ptr msg); - void enqueue(DtxBuffer::shared_ptr buffer, RecoverableMessage::shared_ptr msg); - void dequeue(DtxBuffer::shared_ptr buffer, RecoverableMessage::shared_ptr msg); -}; - -class RecoverableExchangeImpl : public RecoverableExchange -{ - Exchange::shared_ptr exchange; - QueueRegistry& queues; -public: - RecoverableExchangeImpl(Exchange::shared_ptr _exchange, QueueRegistry& _queues) : exchange(_exchange), queues(_queues) {} - void setPersistenceId(uint64_t id); - void bind(const std::string& queue, const std::string& routingKey, qpid::framing::FieldTable& args); -}; - -class RecoverableConfigImpl : public RecoverableConfig -{ - Link::shared_ptr link; - Bridge::shared_ptr bridge; -public: - RecoverableConfigImpl(Link::shared_ptr _link) : link(_link) {} - RecoverableConfigImpl(Bridge::shared_ptr _bridge) : bridge(_bridge) {} - void setPersistenceId(uint64_t id); -}; - -class RecoverableTransactionImpl : public RecoverableTransaction -{ - DtxBuffer::shared_ptr buffer; -public: - RecoverableTransactionImpl(DtxBuffer::shared_ptr _buffer) : buffer(_buffer) {} - void enqueue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message); - void dequeue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message); -}; - -RecoverableExchange::shared_ptr RecoveryManagerImpl::recoverExchange(framing::Buffer& buffer) -{ - Exchange::shared_ptr e = Exchange::decode(exchanges, buffer); - if (e) { - return RecoverableExchange::shared_ptr(new RecoverableExchangeImpl(e, queues)); - } else { - return RecoverableExchange::shared_ptr(); - } -} - -RecoverableQueue::shared_ptr RecoveryManagerImpl::recoverQueue(framing::Buffer& buffer) -{ - Queue::shared_ptr queue = Queue::restore(queues, buffer); - try { - Exchange::shared_ptr exchange = exchanges.getDefault(); - if (exchange) { - exchange->bind(queue, queue->getName(), 0); - queue->bound(exchange->getName(), queue->getName(), framing::FieldTable()); - } - } catch (const framing::NotFoundException& /*e*/) { - //assume no default exchange has been declared - } - return RecoverableQueue::shared_ptr(new RecoverableQueueImpl(queue)); -} - -RecoverableMessage::shared_ptr RecoveryManagerImpl::recoverMessage(framing::Buffer& buffer) -{ - boost::intrusive_ptr<Message> message(new Message()); - message->decodeHeader(buffer); - return RecoverableMessage::shared_ptr(new RecoverableMessageImpl(message)); -} - -RecoverableTransaction::shared_ptr RecoveryManagerImpl::recoverTransaction(const std::string& xid, - std::auto_ptr<TPCTransactionContext> txn) -{ - DtxBuffer::shared_ptr buffer(new DtxBuffer()); - dtxMgr.recover(xid, txn, buffer); - return RecoverableTransaction::shared_ptr(new RecoverableTransactionImpl(buffer)); -} - -RecoverableConfig::shared_ptr RecoveryManagerImpl::recoverConfig(framing::Buffer& buffer) -{ - string kind; - - buffer.getShortString (kind); - if (kind == "link") - return RecoverableConfig::shared_ptr(new RecoverableConfigImpl(Link::decode (links, buffer))); - else if (kind == "bridge") - return RecoverableConfig::shared_ptr(new RecoverableConfigImpl(Bridge::decode (links, buffer))); - - return RecoverableConfig::shared_ptr(); // TODO: raise an exception instead -} - -void RecoveryManagerImpl::recoveryComplete() -{ - //notify all queues and exchanges - queues.eachQueue(boost::bind(&Queue::recoveryComplete, _1, boost::ref(exchanges))); - exchanges.eachExchange(boost::bind(&Exchange::recoveryComplete, _1, boost::ref(exchanges))); -} - -RecoverableMessageImpl:: RecoverableMessageImpl(const intrusive_ptr<Message>& _msg) : msg(_msg) -{ - if (!msg->isPersistent()) { - msg->forcePersistent(); // set so that message will get dequeued from store. - } -} - -bool RecoverableMessageImpl::loadContent(uint64_t /*available*/) -{ - return true; -} - -void RecoverableMessageImpl::decodeContent(framing::Buffer& buffer) -{ - msg->decodeContent(buffer); -} - -void RecoverableMessageImpl::recover(Queue::shared_ptr queue) -{ - queue->recover(msg); -} - -void RecoverableMessageImpl::setPersistenceId(uint64_t id) -{ - msg->setPersistenceId(id); -} - -void RecoverableMessageImpl::setRedelivered() -{ - msg->redeliver(); -} - -void RecoverableQueueImpl::recover(RecoverableMessage::shared_ptr msg) -{ - dynamic_pointer_cast<RecoverableMessageImpl>(msg)->recover(queue); -} - -void RecoverableQueueImpl::setPersistenceId(uint64_t id) -{ - queue->setPersistenceId(id); -} - -uint64_t RecoverableQueueImpl::getPersistenceId() const -{ - return queue->getPersistenceId(); -} - -const std::string& RecoverableQueueImpl::getName() const -{ - return queue->getName(); -} - -void RecoverableQueueImpl::setExternalQueueStore(ExternalQueueStore* inst) -{ - queue->setExternalQueueStore(inst); -} - -ExternalQueueStore* RecoverableQueueImpl::getExternalQueueStore() const -{ - return queue->getExternalQueueStore(); -} - -void RecoverableExchangeImpl::setPersistenceId(uint64_t id) -{ - exchange->setPersistenceId(id); -} - -void RecoverableConfigImpl::setPersistenceId(uint64_t id) -{ - if (link.get()) - link->setPersistenceId(id); - else if (bridge.get()) - bridge->setPersistenceId(id); -} - -void RecoverableExchangeImpl::bind(const string& queueName, - const string& key, - framing::FieldTable& args) -{ - Queue::shared_ptr queue = queues.find(queueName); - exchange->bind(queue, key, &args); - queue->bound(exchange->getName(), key, args); -} - -void RecoverableMessageImpl::dequeue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue) -{ - buffer->enlist(TxOp::shared_ptr(new RecoveredDequeue(queue, msg))); -} - -void RecoverableMessageImpl::enqueue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue) -{ - buffer->enlist(TxOp::shared_ptr(new RecoveredEnqueue(queue, msg))); -} - -void RecoverableQueueImpl::dequeue(DtxBuffer::shared_ptr buffer, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast<RecoverableMessageImpl>(message)->dequeue(buffer, queue); -} - -void RecoverableQueueImpl::enqueue(DtxBuffer::shared_ptr buffer, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast<RecoverableMessageImpl>(message)->enqueue(buffer, queue); -} - -void RecoverableTransactionImpl::dequeue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast<RecoverableQueueImpl>(queue)->dequeue(buffer, message); -} - -void RecoverableTransactionImpl::enqueue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast<RecoverableQueueImpl>(queue)->enqueue(buffer, message); -} - -}} diff --git a/cpp/src/qpid/broker/RecoveryManagerImpl.h b/cpp/src/qpid/broker/RecoveryManagerImpl.h deleted file mode 100644 index 1ad7892b13..0000000000 --- a/cpp/src/qpid/broker/RecoveryManagerImpl.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveryManagerImpl_ -#define _RecoveryManagerImpl_ - -#include <list> -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/RecoveryManager.h" - -namespace qpid { -namespace broker { - - class RecoveryManagerImpl : public RecoveryManager{ - QueueRegistry& queues; - ExchangeRegistry& exchanges; - LinkRegistry& links; - DtxManager& dtxMgr; - public: - RecoveryManagerImpl(QueueRegistry& queues, ExchangeRegistry& exchanges, LinkRegistry& links, - DtxManager& dtxMgr); - ~RecoveryManagerImpl(); - - RecoverableExchange::shared_ptr recoverExchange(framing::Buffer& buffer); - RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer); - RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer); - RecoverableTransaction::shared_ptr recoverTransaction(const std::string& xid, - std::auto_ptr<TPCTransactionContext> txn); - RecoverableConfig::shared_ptr recoverConfig(framing::Buffer& buffer); - void recoveryComplete(); - }; - - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/RetryList.cpp b/cpp/src/qpid/broker/RetryList.cpp deleted file mode 100644 index b0477dd0f7..0000000000 --- a/cpp/src/qpid/broker/RetryList.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/RetryList.h" - -namespace qpid { -namespace broker { - -RetryList::RetryList() : urlIndex(0), addressIndex(0) {} - -void RetryList::reset(const std::vector<Url>& u) -{ - urls = u; - urlIndex = addressIndex = 0;//reset indices -} - -bool RetryList::next(Address& address) -{ - while (urlIndex < urls.size()) { - if (addressIndex < urls[urlIndex].size()) { - address = urls[urlIndex][addressIndex++]; - return true; - } - urlIndex++; - addressIndex = 0; - } - urlIndex = addressIndex = 0;//reset indices - return false; -} - -std::ostream& operator<<(std::ostream& os, const RetryList& l) -{ - for (size_t i = 0; i < l.urls.size(); i++) { - os << l.urls[i] << " "; - } - return os; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/RetryList.h b/cpp/src/qpid/broker/RetryList.h deleted file mode 100644 index 242a7d2122..0000000000 --- a/cpp/src/qpid/broker/RetryList.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_BROKER_RETRYLIST_H -#define QPID_BROKER_RETRYLIST_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/Address.h" -#include "qpid/Url.h" - -namespace qpid { -namespace broker { - -/** - * Simple utility for managing a list of urls to try on reconnecting a - * link. Currently only supports TCP urls. - */ -class RetryList -{ - public: - QPID_BROKER_EXTERN RetryList(); - QPID_BROKER_EXTERN void reset(const std::vector<Url>& urls); - QPID_BROKER_EXTERN bool next(Address& address); - private: - std::vector<Url> urls; - size_t urlIndex; - size_t addressIndex; - - friend std::ostream& operator<<(std::ostream& os, const RetryList& l); -}; - -std::ostream& operator<<(std::ostream& os, const RetryList& l); - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_RETRYLIST_H*/ diff --git a/cpp/src/qpid/broker/SaslAuthenticator.cpp b/cpp/src/qpid/broker/SaslAuthenticator.cpp deleted file mode 100644 index acdb4934d4..0000000000 --- a/cpp/src/qpid/broker/SaslAuthenticator.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/SecuritySettings.h" -#include <boost/format.hpp> - -#if HAVE_SASL -#include <sasl/sasl.h> -#include "qpid/sys/cyrus/CyrusSecurityLayer.h" -using qpid::sys::cyrus::CyrusSecurityLayer; -#endif - -using namespace qpid::framing; -using qpid::sys::SecurityLayer; -using qpid::sys::SecuritySettings; -using boost::format; -using boost::str; - - -namespace qpid { -namespace broker { - - - -class NullAuthenticator : public SaslAuthenticator -{ - Connection& connection; - framing::AMQP_ClientProxy::Connection client; - std::string realm; - const bool encrypt; -public: - NullAuthenticator(Connection& connection, bool encrypt); - ~NullAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string&) {} - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); -}; - -#if HAVE_SASL - - - -class CyrusAuthenticator : public SaslAuthenticator -{ - sasl_conn_t *sasl_conn; - Connection& connection; - framing::AMQP_ClientProxy::Connection client; - const bool encrypt; - - void processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len); - bool getUsername(std::string& uid); - -public: - CyrusAuthenticator(Connection& connection, bool encrypt); - ~CyrusAuthenticator(); - void init(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string& response); - void getError(std::string& error); - void getUid(std::string& uid) { getUsername(uid); } - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); -}; - -bool SaslAuthenticator::available(void) { - return true; -} - -// Initialize the SASL mechanism; throw if it fails. -void SaslAuthenticator::init(const std::string& saslName, std::string const & saslConfigPath ) -{ - // Check if we have a version of SASL that supports sasl_set_path() -#if (SASL_VERSION_FULL >= ((2<<16)|(1<<8)|22)) - // If we are not given a sasl path, do nothing and allow the default to be used. - if ( ! saslConfigPath.empty() ) { - int code = sasl_set_path(SASL_PATH_TYPE_CONFIG, - const_cast<char *>(saslConfigPath.c_str())); - if(SASL_OK != code) - throw Exception(QPID_MSG("SASL: sasl_set_path failed [" << code << "] " )); - QPID_LOG(info, "SASL: config path set to " << saslConfigPath ); - } -#endif - - int code = sasl_server_init(NULL, saslName.c_str()); - if (code != SASL_OK) { - // TODO: Figure out who owns the char* returned by - // sasl_errstring, though it probably does not matter much - throw Exception(sasl_errstring(code, NULL, NULL)); - } -} - -void SaslAuthenticator::fini(void) -{ - sasl_done(); -} - -#else - -typedef NullAuthenticator CyrusAuthenticator; - -bool SaslAuthenticator::available(void) { - return false; -} - -void SaslAuthenticator::init(const std::string& /*saslName*/, std::string const & /*saslConfigPath*/ ) -{ - throw Exception("Requested authentication but SASL unavailable"); -} - -void SaslAuthenticator::fini(void) -{ - return; -} - -#endif - -std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connection& c, bool isShadow ) -{ - if (c.getBroker().getOptions().auth) { - if ( isShadow ) - return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); - else - return std::auto_ptr<SaslAuthenticator>(new CyrusAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); - } else { - QPID_LOG(debug, "SASL: No Authentication Performed"); - return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); - } -} - - -NullAuthenticator::NullAuthenticator(Connection& c, bool e) : connection(c), client(c.getOutput()), - realm(c.getBroker().getOptions().realm), encrypt(e) {} -NullAuthenticator::~NullAuthenticator() {} - -void NullAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("ANONYMOUS"))); - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("PLAIN")));//useful for testing -} - -void NullAuthenticator::start(const string& mechanism, const string& response) -{ - if (encrypt) { -#if HAVE_SASL - // encryption required - check to see if we are running over an - // encrypted SSL connection. - SecuritySettings external = connection.getExternalSecuritySettings(); - sasl_ssf_t external_ssf = (sasl_ssf_t) external.ssf; - if (external_ssf < 1) // < 1 == unencrypted -#endif - { - QPID_LOG(error, "Rejected un-encrypted connection."); - throw ConnectionForcedException("Connection must be encrypted."); - } - } - if (mechanism == "PLAIN") { // Old behavior - if (response.size() > 0) { - string uid; - string::size_type i = response.find((char)0); - if (i == 0 && response.size() > 1) { - //no authorization id; use authentication id - i = response.find((char)0, 1); - if (i != string::npos) uid = response.substr(1, i-1); - } else if (i != string::npos) { - //authorization id is first null delimited field - uid = response.substr(0, i); - }//else not a valid SASL PLAIN response, throw error? - if (!uid.empty()) { - //append realm if it has not already been added - i = uid.find(realm); - if (i == string::npos || realm.size() + i < uid.size()) { - uid = str(format("%1%@%2%") % uid % realm); - } - connection.setUserId(uid); - } - } - } else { - connection.setUserId("anonymous"); - } - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, connection.getHeartbeatMax()); -} - - -std::auto_ptr<SecurityLayer> NullAuthenticator::getSecurityLayer(uint16_t) -{ - std::auto_ptr<SecurityLayer> securityLayer; - return securityLayer; -} - - -#if HAVE_SASL - -CyrusAuthenticator::CyrusAuthenticator(Connection& c, bool _encrypt) : - sasl_conn(0), connection(c), client(c.getOutput()), encrypt(_encrypt) -{ - init(); -} - -void CyrusAuthenticator::init() -{ - /* Next to the service name, which specifies the - * /etc/sasl2/<service name>.conf file to read, the realm is - * currently the most important argument below. When - * performing authentication the user that is authenticating - * will be looked up in a specific realm. If none is given - * then the realm defaults to the hostname, which can cause - * confusion when the daemon is run on different hosts that - * may be logically sharing a realm (aka a user domain). This - * is especially important for SASL PLAIN authentication, - * which cannot specify a realm for the user that is - * authenticating. - */ - int code; - - const char *realm = connection.getBroker().getOptions().realm.c_str(); - code = sasl_server_new(BROKER_SASL_NAME, /* Service name */ - NULL, /* Server FQDN, gethostname() */ - realm, /* Authentication realm */ - NULL, /* Local IP, needed for some mechanism */ - NULL, /* Remote IP, needed for some mechanism */ - NULL, /* Callbacks */ - 0, /* Connection flags */ - &sasl_conn); - - if (SASL_OK != code) { - QPID_LOG(error, "SASL: Connection creation failed: [" << code << "] " << sasl_errdetail(sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw ConnectionForcedException("Unable to perform authentication"); - } - - sasl_security_properties_t secprops; - - //TODO: should the actual SSF values be configurable here? - secprops.min_ssf = encrypt ? 10: 0; - secprops.max_ssf = 256; - - // If the transport provides encryption, notify the SASL library of - // the key length and set the ssf range to prevent double encryption. - SecuritySettings external = connection.getExternalSecuritySettings(); - QPID_LOG(debug, "External ssf=" << external.ssf << " and auth=" << external.authid); - sasl_ssf_t external_ssf = (sasl_ssf_t) external.ssf; - if (external_ssf) { - int result = sasl_setprop(sasl_conn, SASL_SSF_EXTERNAL, &external_ssf); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external SSF: " << result)); - } - - secprops.max_ssf = secprops.min_ssf = 0; - } - - QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << - ", max_ssf: " << secprops.max_ssf << - ", external_ssf: " << external_ssf ); - - if (!external.authid.empty()) { - const char* external_authid = external.authid.c_str(); - int result = sasl_setprop(sasl_conn, SASL_AUTH_EXTERNAL, external_authid); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external auth: " << result)); - } - - QPID_LOG(debug, "external auth detected and set to " << external_authid); - } - - secprops.maxbufsize = 65535; - secprops.property_names = 0; - secprops.property_values = 0; - secprops.security_flags = 0; /* or SASL_SEC_NOANONYMOUS etc as appropriate */ - /* - * The nodict flag restricts SASL authentication mechanisms - * to those that are not susceptible to dictionary attacks. - * They are: - * SRP - * PASSDSS-3DES-1 - * EXTERNAL - */ - if (external.nodict) secprops.security_flags |= SASL_SEC_NODICTIONARY; - int result = sasl_setprop(sasl_conn, SASL_SEC_PROPS, &secprops); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << result)); - } -} - -CyrusAuthenticator::~CyrusAuthenticator() -{ - if (sasl_conn) { - sasl_dispose(&sasl_conn); - sasl_conn = 0; - } -} - -void CyrusAuthenticator::getError(string& error) -{ - error = string(sasl_errdetail(sasl_conn)); -} - -bool CyrusAuthenticator::getUsername(string& uid) -{ - const void* ptr; - - int code = sasl_getprop(sasl_conn, SASL_USERNAME, &ptr); - if (SASL_OK == code) { - uid = string(const_cast<char*>(static_cast<const char*>(ptr))); - return true; - } else { - QPID_LOG(warning, "Failed to retrieve sasl username"); - return false; - } -} - -void CyrusAuthenticator::getMechanisms(Array& mechanisms) -{ - const char *separator = " "; - const char *list; - unsigned int list_len; - int count; - - int code = sasl_listmech(sasl_conn, NULL, - "", separator, "", - &list, &list_len, - &count); - - if (SASL_OK != code) { - QPID_LOG(info, "SASL: Mechanism listing failed: " << sasl_errdetail(sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw ConnectionForcedException("Mechanism listing failed"); - } else { - string mechanism; - unsigned int start; - unsigned int end; - - QPID_LOG(info, "SASL: Mechanism list: " << list); - - end = 0; - do { - start = end; - - // Seek to end of next mechanism - while (end < list_len && separator[0] != list[end]) - end++; - - // Record the mechanism - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value(string(list, start, end - start)))); - end++; - } while (end < list_len); - } -} - -void CyrusAuthenticator::start(const string& mechanism, const string& response) -{ - const char *challenge; - unsigned int challenge_len; - - QPID_LOG(debug, "SASL: Starting authentication with mechanism: " << mechanism); - int code = sasl_server_start(sasl_conn, - mechanism.c_str(), - response.c_str(), response.length(), - &challenge, &challenge_len); - - processAuthenticationStep(code, challenge, challenge_len); -} - -void CyrusAuthenticator::step(const string& response) -{ - const char *challenge; - unsigned int challenge_len; - - int code = sasl_server_step(sasl_conn, - response.c_str(), response.length(), - &challenge, &challenge_len); - - processAuthenticationStep(code, challenge, challenge_len); -} - -void CyrusAuthenticator::processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len) -{ - if (SASL_OK == code) { - std::string uid; - if (!getUsername(uid)) { - // TODO: Change this to an exception signaling - // authentication failure, when one is available - throw ConnectionForcedException("Authenticated username unavailable"); - } - QPID_LOG(info, connection.getMgmtId() << " SASL: Authentication succeeded for: " << uid); - - connection.setUserId(uid); - - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, connection.getHeartbeatMax()); - } else if (SASL_CONTINUE == code) { - string challenge_str(challenge, challenge_len); - - QPID_LOG(debug, "SASL: sending challenge to client"); - - client.secure(challenge_str); - } else { - std::string uid; - if (!getUsername(uid)) { - QPID_LOG(info, "SASL: Authentication failed (no username available):" << sasl_errdetail(sasl_conn)); - } else { - QPID_LOG(info, "SASL: Authentication failed for " << uid << ":" << sasl_errdetail(sasl_conn)); - } - - // TODO: Change to more specific exceptions, when they are - // available - switch (code) { - case SASL_NOMECH: - throw ConnectionForcedException("Unsupported mechanism"); - break; - case SASL_TRYAGAIN: - throw ConnectionForcedException("Transient failure, try again"); - break; - default: - throw ConnectionForcedException("Authentication failed"); - break; - } - } -} - -std::auto_ptr<SecurityLayer> CyrusAuthenticator::getSecurityLayer(uint16_t maxFrameSize) -{ - - const void* value(0); - int result = sasl_getprop(sasl_conn, SASL_SSF, &value); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(sasl_conn))); - } - uint ssf = *(reinterpret_cast<const unsigned*>(value)); - std::auto_ptr<SecurityLayer> securityLayer; - if (ssf) { - securityLayer = std::auto_ptr<SecurityLayer>(new CyrusSecurityLayer(sasl_conn, maxFrameSize)); - } - return securityLayer; -} - -#endif - -}} diff --git a/cpp/src/qpid/broker/SaslAuthenticator.h b/cpp/src/qpid/broker/SaslAuthenticator.h deleted file mode 100644 index cfbe1a0cd1..0000000000 --- a/cpp/src/qpid/broker/SaslAuthenticator.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _SaslAuthenticator_ -#define _SaslAuthenticator_ - - -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/Exception.h" -#include "qpid/sys/SecurityLayer.h" -#include <memory> -#include <vector> -#include <boost/bind.hpp> -#include <boost/function.hpp> - -namespace qpid { -namespace broker { - -class Connection; - -class SaslAuthenticator -{ -public: - virtual ~SaslAuthenticator() {} - virtual void getMechanisms(framing::Array& mechanisms) = 0; - virtual void start(const std::string& mechanism, const std::string& response) = 0; - virtual void step(const std::string& response) = 0; - virtual void getUid(std::string&) {} - virtual bool getUsername(std::string&) { return false; }; - virtual void getError(std::string&) {} - virtual std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(uint16_t maxFrameSize) = 0; - - static bool available(void); - - // Initialize the SASL mechanism; throw if it fails. - static void init(const std::string& saslName, std::string const & saslConfigPath ); - static void fini(void); - - static std::auto_ptr<SaslAuthenticator> createAuthenticator(Connection& connection, bool isShadow); - - virtual void callUserIdCallbacks() { } -}; - -}} - -#endif diff --git a/cpp/src/qpid/broker/SecureConnection.cpp b/cpp/src/qpid/broker/SecureConnection.cpp deleted file mode 100644 index 5c1ebf3e8b..0000000000 --- a/cpp/src/qpid/broker/SecureConnection.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/SecureConnection.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/framing/reply_exceptions.h" - -namespace qpid { -namespace broker { - -using qpid::sys::SecurityLayer; - -SecureConnection::SecureConnection() : secured(false) {} - -size_t SecureConnection::decode(const char* buffer, size_t size) -{ - if (!secured && securityLayer.get()) { - //security layer comes into effect on first read after its - //activated - secured = true; - } - if (secured) { - return securityLayer->decode(buffer, size); - } else { - return codec->decode(buffer, size); - } -} - -size_t SecureConnection::encode(const char* buffer, size_t size) -{ - if (secured) { - return securityLayer->encode(buffer, size); - } else { - return codec->encode(buffer, size); - } -} - -bool SecureConnection::canEncode() -{ - if (secured) return securityLayer->canEncode(); - else return codec->canEncode(); -} - -void SecureConnection::closed() -{ - codec->closed(); -} - -bool SecureConnection::isClosed() const -{ - return codec->isClosed(); -} - -framing::ProtocolVersion SecureConnection::getVersion() const -{ - return codec->getVersion(); -} - -void SecureConnection:: setCodec(std::auto_ptr<ConnectionCodec> c) -{ - codec = c; -} - -void SecureConnection::activateSecurityLayer(std::auto_ptr<SecurityLayer> sl, bool secureImmediately) -{ - securityLayer = sl; - securityLayer->init(codec.get()); - - if ( secureImmediately ) - secured = true; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SecureConnection.h b/cpp/src/qpid/broker/SecureConnection.h deleted file mode 100644 index 1547faae1e..0000000000 --- a/cpp/src/qpid/broker/SecureConnection.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_BROKER_SECURECONNECTION_H -#define QPID_BROKER_SECURECONNECTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ConnectionCodec.h" -#include <memory> - -namespace qpid { - -namespace sys { -class SecurityLayer; -} - -namespace broker { - -/** - * A ConnectionCodec 'wrapper' that allows a connection to be - * 'secured' e.g. encrypted based on settings negotiatiated at the - * time of establishment. - */ -class SecureConnection : public qpid::sys::ConnectionCodec -{ - public: - SecureConnection(); - size_t decode(const char* buffer, size_t size); - size_t encode(const char* buffer, size_t size); - bool canEncode(); - void closed(); - bool isClosed() const; - framing::ProtocolVersion getVersion() const; - void setCodec(std::auto_ptr<ConnectionCodec>); - void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>, bool secureImmediately=false); - private: - std::auto_ptr<ConnectionCodec> codec; - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; - bool secured; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SECURECONNECTION_H*/ diff --git a/cpp/src/qpid/broker/SecureConnectionFactory.cpp b/cpp/src/qpid/broker/SecureConnectionFactory.cpp deleted file mode 100644 index 754b443c22..0000000000 --- a/cpp/src/qpid/broker/SecureConnectionFactory.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/SecureConnectionFactory.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/amqp_0_10/Connection.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/SecureConnection.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -using framing::ProtocolVersion; -using qpid::sys::SecuritySettings; -typedef std::auto_ptr<amqp_0_10::Connection> CodecPtr; -typedef std::auto_ptr<SecureConnection> SecureConnectionPtr; -typedef std::auto_ptr<Connection> ConnectionPtr; -typedef std::auto_ptr<sys::ConnectionInputHandler> InputPtr; - -SecureConnectionFactory::SecureConnectionFactory(Broker& b) : broker(b) {} - -sys::ConnectionCodec* -SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - if (broker.getConnectionCounter().allowConnection()) - { - QPID_LOG(error, "Client max connection count limit exceeded: " << broker.getOptions().maxConnections << " connection refused"); - return 0; - } - if (v == ProtocolVersion(0, 10)) { - SecureConnectionPtr sc(new SecureConnection()); - CodecPtr c(new amqp_0_10::Connection(out, id, false)); - ConnectionPtr i(new broker::Connection(c.get(), broker, id, external, false)); - i->setSecureConnection(sc.get()); - c->setInputHandler(InputPtr(i.release())); - sc->setCodec(std::auto_ptr<sys::ConnectionCodec>(c)); - return sc.release(); - } - return 0; -} - -sys::ConnectionCodec* -SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - // used to create connections from one broker to another - SecureConnectionPtr sc(new SecureConnection()); - CodecPtr c(new amqp_0_10::Connection(out, id, true)); - ConnectionPtr i(new broker::Connection(c.get(), broker, id, external, true )); - i->setSecureConnection(sc.get()); - c->setInputHandler(InputPtr(i.release())); - sc->setCodec(std::auto_ptr<sys::ConnectionCodec>(c)); - return sc.release(); -} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SecureConnectionFactory.h b/cpp/src/qpid/broker/SecureConnectionFactory.h deleted file mode 100644 index 8a04dfcb15..0000000000 --- a/cpp/src/qpid/broker/SecureConnectionFactory.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _SecureConnectionFactory_ -#define _SecureConnectionFactory_ - -#include "qpid/sys/ConnectionCodec.h" - -namespace qpid { -namespace broker { -class Broker; - -class SecureConnectionFactory : public sys::ConnectionCodec::Factory -{ - public: - SecureConnectionFactory(Broker& b); - - sys::ConnectionCodec* - create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id, - const qpid::sys::SecuritySettings&); - - sys::ConnectionCodec* - create(sys::OutputControl&, const std::string& id, const qpid::sys::SecuritySettings&); - - private: - Broker& broker; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/SemanticState.cpp b/cpp/src/qpid/broker/SemanticState.cpp deleted file mode 100644 index ce86253f4a..0000000000 --- a/cpp/src/qpid/broker/SemanticState.cpp +++ /dev/null @@ -1,823 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/SessionState.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/DtxAck.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/SessionContext.h" -#include "qpid/broker/SessionOutputException.h" -#include "qpid/broker/TxAccept.h" -#include "qpid/broker/TxPublish.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/IsInSequenceSet.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/ClusterSafe.h" -#include "qpid/ptr_map.h" -#include "qpid/broker/AclModule.h" - -#include <boost/bind.hpp> -#include <boost/format.hpp> - -#include <iostream> -#include <sstream> -#include <algorithm> -#include <functional> - -#include <assert.h> - -namespace qpid { -namespace broker { - -using namespace std; -using boost::intrusive_ptr; -using boost::bind; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -using qpid::ptr_map_ptr; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::broker; - -SemanticState::SemanticState(DeliveryAdapter& da, SessionContext& ss) - : session(ss), - deliveryAdapter(da), - tagGenerator("sgen"), - dtxSelected(false), - authMsg(getSession().getBroker().getOptions().auth && !getSession().getConnection().isFederationLink()), - userID(getSession().getConnection().getUserId()), - userName(getSession().getConnection().getUserId().substr(0,getSession().getConnection().getUserId().find('@'))), - isDefaultRealm(userID.find('@') != std::string::npos && getSession().getBroker().getOptions().realm == userID.substr(userID.find('@')+1,userID.size())), - closeComplete(false) -{ - acl = getSession().getBroker().getAcl(); -} - -SemanticState::~SemanticState() { - closed(); -} - -void SemanticState::closed() { - if (!closeComplete) { - //prevent requeued messages being redelivered to consumers - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - disable(i->second); - } - if (dtxBuffer.get()) { - dtxBuffer->fail(); - } - recover(true); - - //now unsubscribe, which may trigger queue deletion and thus - //needs to occur after the requeueing of unacked messages - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - unsubscribe(i->second); - } - closeComplete = true; - } -} - -bool SemanticState::exists(const string& consumerTag){ - return consumers.find(consumerTag) != consumers.end(); -} - -void SemanticState::consume(const string& tag, - Queue::shared_ptr queue, bool ackRequired, bool acquire, - bool exclusive, const string& resumeId, uint64_t resumeTtl, const FieldTable& arguments) -{ - ConsumerImpl::shared_ptr c(new ConsumerImpl(this, tag, queue, ackRequired, acquire, exclusive, resumeId, resumeTtl, arguments)); - queue->consume(c, exclusive);//may throw exception - consumers[tag] = c; -} - -bool SemanticState::cancel(const string& tag) -{ - ConsumerImplMap::iterator i = consumers.find(tag); - if (i != consumers.end()) { - cancel(i->second); - consumers.erase(i); - //should cancel all unacked messages for this consumer so that - //they are not redelivered on recovery - for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::cancel, _1, tag)); - return true; - } else { - return false; - } -} - - -void SemanticState::startTx() -{ - txBuffer = TxBuffer::shared_ptr(new TxBuffer()); -} - -void SemanticState::commit(MessageStore* const store) -{ - if (!txBuffer) throw - CommandInvalidException(QPID_MSG("Session has not been selected for use with transactions")); - - TxOp::shared_ptr txAck(static_cast<TxOp*>(new TxAccept(accumulatedAck, unacked))); - txBuffer->enlist(txAck); - if (txBuffer->commitLocal(store)) { - accumulatedAck.clear(); - } else { - throw InternalErrorException(QPID_MSG("Commit failed")); - } -} - -void SemanticState::rollback() -{ - if (!txBuffer) - throw CommandInvalidException(QPID_MSG("Session has not been selected for use with transactions")); - - txBuffer->rollback(); - accumulatedAck.clear(); -} - -void SemanticState::selectDtx() -{ - dtxSelected = true; -} - -void SemanticState::startDtx(const std::string& xid, DtxManager& mgr, bool join) -{ - if (!dtxSelected) { - throw CommandInvalidException(QPID_MSG("Session has not been selected for use with dtx")); - } - dtxBuffer = DtxBuffer::shared_ptr(new DtxBuffer(xid)); - txBuffer = boost::static_pointer_cast<TxBuffer>(dtxBuffer); - if (join) { - mgr.join(xid, dtxBuffer); - } else { - mgr.start(xid, dtxBuffer); - } -} - -void SemanticState::endDtx(const std::string& xid, bool fail) -{ - if (!dtxBuffer) { - throw IllegalStateException(QPID_MSG("xid " << xid << " not associated with this session")); - } - if (dtxBuffer->getXid() != xid) { - throw CommandInvalidException( - QPID_MSG("xid specified on start was " << dtxBuffer->getXid() << ", but " << xid << " specified on end")); - - } - - txBuffer.reset();//ops on this session no longer transactional - - checkDtxTimeout(); - if (fail) { - dtxBuffer->fail(); - } else { - dtxBuffer->markEnded(); - } - dtxBuffer.reset(); -} - -void SemanticState::suspendDtx(const std::string& xid) -{ - if (dtxBuffer->getXid() != xid) { - throw CommandInvalidException( - QPID_MSG("xid specified on start was " << dtxBuffer->getXid() << ", but " << xid << " specified on suspend")); - } - txBuffer.reset();//ops on this session no longer transactional - - checkDtxTimeout(); - dtxBuffer->setSuspended(true); - suspendedXids[xid] = dtxBuffer; - dtxBuffer.reset(); -} - -void SemanticState::resumeDtx(const std::string& xid) -{ - if (!dtxSelected) { - throw CommandInvalidException(QPID_MSG("Session has not been selected for use with dtx")); - } - - dtxBuffer = suspendedXids[xid]; - if (!dtxBuffer) { - throw CommandInvalidException(QPID_MSG("xid " << xid << " not attached")); - } else { - suspendedXids.erase(xid); - } - - if (dtxBuffer->getXid() != xid) { - throw CommandInvalidException( - QPID_MSG("xid specified on start was " << dtxBuffer->getXid() << ", but " << xid << " specified on resume")); - - } - if (!dtxBuffer->isSuspended()) { - throw CommandInvalidException(QPID_MSG("xid " << xid << " not suspended")); - } - - checkDtxTimeout(); - dtxBuffer->setSuspended(false); - txBuffer = boost::static_pointer_cast<TxBuffer>(dtxBuffer); -} - -void SemanticState::checkDtxTimeout() -{ - if (dtxBuffer->isExpired()) { - dtxBuffer.reset(); - throw DtxTimeoutException(); - } -} - -void SemanticState::record(const DeliveryRecord& delivery) -{ - unacked.push_back(delivery); -} - -const std::string QPID_SYNC_FREQUENCY("qpid.sync_frequency"); - -SemanticState::ConsumerImpl::ConsumerImpl(SemanticState* _parent, - const string& _name, - Queue::shared_ptr _queue, - bool ack, - bool _acquire, - bool _exclusive, - const string& _resumeId, - uint64_t _resumeTtl, - const framing::FieldTable& _arguments - - -) : - Consumer(_acquire), - parent(_parent), - name(_name), - queue(_queue), - ackExpected(ack), - acquire(_acquire), - blocked(true), - windowing(true), - exclusive(_exclusive), - resumeId(_resumeId), - resumeTtl(_resumeTtl), - arguments(_arguments), - msgCredit(0), - byteCredit(0), - notifyEnabled(true), - syncFrequency(_arguments.getAsInt(QPID_SYNC_FREQUENCY)), - deliveryCount(0), - mgmtObject(0) -{ - if (parent != 0 && queue.get() != 0 && queue->GetManagementObject() !=0) - { - ManagementAgent* agent = parent->session.getBroker().getManagementAgent(); - qpid::management::Manageable* ms = dynamic_cast<qpid::management::Manageable*> (&(parent->session)); - - if (agent != 0) - { - mgmtObject = new _qmf::Subscription(agent, this, ms , queue->GetManagementObject()->getObjectId() ,name, - !acquire, ackExpected, exclusive, ManagementAgent::toMap(arguments)); - agent->addObject (mgmtObject); - mgmtObject->set_creditMode("WINDOW"); - } - } -} - -ManagementObject* SemanticState::ConsumerImpl::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t SemanticState::ConsumerImpl::ManagementMethod (uint32_t methodId, Args&, string&) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - QPID_LOG (debug, "Queue::ManagementMethod [id=" << methodId << "]"); - - return status; -} - - -OwnershipToken* SemanticState::ConsumerImpl::getSession() -{ - return &(parent->session); -} - -bool SemanticState::ConsumerImpl::deliver(QueuedMessage& msg) -{ - assertClusterSafe(); - allocateCredit(msg.payload); - DeliveryRecord record(msg, queue, name, acquire, !ackExpected, windowing); - bool sync = syncFrequency && ++deliveryCount >= syncFrequency; - if (sync) deliveryCount = 0;//reset - parent->deliver(record, sync); - if (!ackExpected && acquire) record.setEnded();//allows message to be released now its been delivered - if (windowing || ackExpected || !acquire) { - parent->record(record); - } - if (acquire && !ackExpected) { - queue->dequeue(0, msg); - } - if (mgmtObject) { mgmtObject->inc_delivered(); } - return true; -} - -bool SemanticState::ConsumerImpl::filter(intrusive_ptr<Message>) -{ - return true; -} - -bool SemanticState::ConsumerImpl::accept(intrusive_ptr<Message> msg) -{ - assertClusterSafe(); - // FIXME aconway 2009-06-08: if we have byte & message credit but - // checkCredit fails because the message is to big, we should - // remain on queue's listener list for possible smaller messages - // in future. - // - blocked = !(filter(msg) && checkCredit(msg)); - return !blocked; -} - -namespace { -struct ConsumerName { - const SemanticState::ConsumerImpl& consumer; - ConsumerName(const SemanticState::ConsumerImpl& ci) : consumer(ci) {} -}; - -ostream& operator<<(ostream& o, const ConsumerName& pc) { - return o << pc.consumer.getName() << " on " - << pc.consumer.getParent().getSession().getSessionId(); -} -} - -void SemanticState::ConsumerImpl::allocateCredit(intrusive_ptr<Message>& msg) -{ - assertClusterSafe(); - uint32_t originalMsgCredit = msgCredit; - uint32_t originalByteCredit = byteCredit; - if (msgCredit != 0xFFFFFFFF) { - msgCredit--; - } - if (byteCredit != 0xFFFFFFFF) { - byteCredit -= msg->getRequiredCredit(); - } - QPID_LOG(debug, "Credit allocated for " << ConsumerName(*this) - << ", was " << " bytes: " << originalByteCredit << " msgs: " << originalMsgCredit - << " now bytes: " << byteCredit << " msgs: " << msgCredit); - -} - -bool SemanticState::ConsumerImpl::checkCredit(intrusive_ptr<Message>& msg) -{ - bool enoughCredit = msgCredit > 0 && - (byteCredit == 0xFFFFFFFF || byteCredit >= msg->getRequiredCredit()); - QPID_LOG(debug, (enoughCredit ? "Sufficient credit for " : "Insufficient credit for ") - << ConsumerName(*this) - << ", have bytes: " << byteCredit << " msgs: " << msgCredit - << ", need " << msg->getRequiredCredit() << " bytes"); - return enoughCredit; -} - -SemanticState::ConsumerImpl::~ConsumerImpl() -{ - if (mgmtObject != 0) - mgmtObject->resourceDestroy (); -} - -void SemanticState::disable(ConsumerImpl::shared_ptr c) -{ - c->disableNotify(); - if (session.isAttached()) - session.getConnection().outputTasks.removeOutputTask(c.get()); -} - -void SemanticState::unsubscribe(ConsumerImpl::shared_ptr c) -{ - Queue::shared_ptr queue = c->getQueue(); - if(queue) { - queue->cancel(c); - if (queue->canAutoDelete() && !queue->hasExclusiveOwner()) { - Queue::tryAutoDelete(session.getBroker(), queue); - } - } -} - -void SemanticState::cancel(ConsumerImpl::shared_ptr c) -{ - disable(c); - unsubscribe(c); -} - -void SemanticState::handle(intrusive_ptr<Message> msg) { - if (txBuffer.get()) { - TxPublish* deliverable(new TxPublish(msg)); - TxOp::shared_ptr op(deliverable); - route(msg, *deliverable); - txBuffer->enlist(op); - } else { - DeliverableMessage deliverable(msg); - route(msg, deliverable); - if (msg->isContentReleaseRequested()) { - // NOTE: The log messages in this section are used for flow-to-disk testing (which checks the log for the - // presence of these messages). Do not change these without also checking these tests. - if (msg->isContentReleaseBlocked()) { - QPID_LOG(debug, "Message id=\"" << msg->getProperties<MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content release blocked"); - } else { - msg->releaseContent(); - QPID_LOG(debug, "Message id=\"" << msg->getProperties<MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content released"); - } - } - } -} - -namespace -{ -const std::string nullstring; -} - -void SemanticState::route(intrusive_ptr<Message> msg, Deliverable& strategy) { - msg->setTimestamp(getSession().getBroker().getExpiryPolicy()); - - std::string exchangeName = msg->getExchangeName(); - if (!cacheExchange || cacheExchange->getName() != exchangeName || cacheExchange->isDestroyed()) - cacheExchange = session.getBroker().getExchanges().get(exchangeName); - cacheExchange->setProperties(msg); - - /* verify the userid if specified: */ - std::string id = - msg->hasProperties<MessageProperties>() ? msg->getProperties<MessageProperties>()->getUserId() : nullstring; - - if (authMsg && !id.empty() && !(id == userID || (isDefaultRealm && id == userName))) - { - QPID_LOG(debug, "authorised user id : " << userID << " but user id in message declared as " << id); - throw UnauthorizedAccessException(QPID_MSG("authorised user id : " << userID << " but user id in message declared as " << id)); - } - - if (acl && acl->doTransferAcl()) - { - if (!acl->authorise(getSession().getConnection().getUserId(),acl::ACT_PUBLISH,acl::OBJ_EXCHANGE,exchangeName, msg->getRoutingKey() )) - throw UnauthorizedAccessException(QPID_MSG(userID << " cannot publish to " << - exchangeName << " with routing-key " << msg->getRoutingKey())); - } - - cacheExchange->route(strategy, msg->getRoutingKey(), msg->getApplicationHeaders()); - - if (!strategy.delivered) { - //TODO:if discard-unroutable, just drop it - //TODO:else if accept-mode is explicit, reject it - //else route it to alternate exchange - if (cacheExchange->getAlternate()) { - cacheExchange->getAlternate()->route(strategy, msg->getRoutingKey(), msg->getApplicationHeaders()); - } - if (!strategy.delivered) { - msg->destroy(); - } - } - -} - -void SemanticState::requestDispatch() -{ - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) - i->second->requestDispatch(); -} - -void SemanticState::ConsumerImpl::requestDispatch() -{ - assertClusterSafe(); - if (blocked) { - parent->session.getConnection().outputTasks.addOutputTask(this); - parent->session.getConnection().outputTasks.activateOutput(); - blocked = false; - } -} - -bool SemanticState::complete(DeliveryRecord& delivery) -{ - ConsumerImplMap::iterator i = consumers.find(delivery.getTag()); - if (i != consumers.end()) { - i->second->complete(delivery); - } - return delivery.isRedundant(); -} - -void SemanticState::ConsumerImpl::complete(DeliveryRecord& delivery) -{ - if (!delivery.isComplete()) { - delivery.complete(); - if (windowing) { - if (msgCredit != 0xFFFFFFFF) msgCredit++; - if (byteCredit != 0xFFFFFFFF) byteCredit += delivery.getCredit(); - } - } -} - -void SemanticState::recover(bool requeue) -{ - if(requeue){ - //take copy and clear unacked as requeue may result in redelivery to this session - //which will in turn result in additions to unacked - DeliveryRecords copy = unacked; - unacked.clear(); - for_each(copy.rbegin(), copy.rend(), mem_fun_ref(&DeliveryRecord::requeue)); - }else{ - for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::redeliver, _1, this)); - //unconfirmed messages re redelivered and therefore have their - //id adjusted, confirmed messages are not and so the ordering - //w.r.t id is lost - sort(unacked.begin(), unacked.end()); - } -} - -void SemanticState::deliver(DeliveryRecord& msg, bool sync) -{ - return deliveryAdapter.deliver(msg, sync); -} - -SemanticState::ConsumerImpl& SemanticState::find(const std::string& destination) -{ - ConsumerImplMap::iterator i = consumers.find(destination); - if (i == consumers.end()) { - throw NotFoundException(QPID_MSG("Unknown destination " << destination)); - } else { - return *(i->second); - } -} - -void SemanticState::setWindowMode(const std::string& destination) -{ - find(destination).setWindowMode(); -} - -void SemanticState::setCreditMode(const std::string& destination) -{ - find(destination).setCreditMode(); -} - -void SemanticState::addByteCredit(const std::string& destination, uint32_t value) -{ - ConsumerImpl& c = find(destination); - c.addByteCredit(value); - c.requestDispatch(); -} - - -void SemanticState::addMessageCredit(const std::string& destination, uint32_t value) -{ - ConsumerImpl& c = find(destination); - c.addMessageCredit(value); - c.requestDispatch(); -} - -void SemanticState::flush(const std::string& destination) -{ - find(destination).flush(); -} - - -void SemanticState::stop(const std::string& destination) -{ - find(destination).stop(); -} - -void SemanticState::ConsumerImpl::setWindowMode() -{ - assertClusterSafe(); - windowing = true; - if (mgmtObject){ - mgmtObject->set_creditMode("WINDOW"); - } -} - -void SemanticState::ConsumerImpl::setCreditMode() -{ - assertClusterSafe(); - windowing = false; - if (mgmtObject){ - mgmtObject->set_creditMode("CREDIT"); - } -} - -void SemanticState::ConsumerImpl::addByteCredit(uint32_t value) -{ - assertClusterSafe(); - if (byteCredit != 0xFFFFFFFF) { - if (value == 0xFFFFFFFF) byteCredit = value; - else byteCredit += value; - } -} - -void SemanticState::ConsumerImpl::addMessageCredit(uint32_t value) -{ - assertClusterSafe(); - if (msgCredit != 0xFFFFFFFF) { - if (value == 0xFFFFFFFF) msgCredit = value; - else msgCredit += value; - } -} - -bool SemanticState::ConsumerImpl::haveCredit() -{ - if (msgCredit && byteCredit) { - return true; - } else { - blocked = true; - return false; - } -} - -void SemanticState::ConsumerImpl::flush() -{ - while(haveCredit() && queue->dispatch(shared_from_this())) - ; - stop(); -} - -void SemanticState::ConsumerImpl::stop() -{ - assertClusterSafe(); - msgCredit = 0; - byteCredit = 0; -} - -Queue::shared_ptr SemanticState::getQueue(const string& name) const { - Queue::shared_ptr queue; - if (name.empty()) { - throw NotAllowedException(QPID_MSG("No queue name specified.")); - } else { - queue = session.getBroker().getQueues().find(name); - if (!queue) - throw NotFoundException(QPID_MSG("Queue not found: "<<name)); - } - return queue; -} - -AckRange SemanticState::findRange(DeliveryId first, DeliveryId last) -{ - return DeliveryRecord::findRange(unacked, first, last); -} - -void SemanticState::acquire(DeliveryId first, DeliveryId last, DeliveryIds& acquired) -{ - AckRange range = findRange(first, last); - for_each(range.start, range.end, AcquireFunctor(acquired)); -} - -void SemanticState::release(DeliveryId first, DeliveryId last, bool setRedelivered) -{ - AckRange range = findRange(first, last); - //release results in the message being added to the head so want - //to release in reverse order to keep the original transfer order - DeliveryRecords::reverse_iterator start(range.end); - DeliveryRecords::reverse_iterator end(range.start); - for_each(start, end, boost::bind(&DeliveryRecord::release, _1, setRedelivered)); -} - -void SemanticState::reject(DeliveryId first, DeliveryId last) -{ - AckRange range = findRange(first, last); - for_each(range.start, range.end, mem_fun_ref(&DeliveryRecord::reject)); - //may need to remove the delivery records as well - for (DeliveryRecords::iterator i = range.start; i != unacked.end() && i->getId() <= last; ) { - if (i->isRedundant()) i = unacked.erase(i); - else i++; - } -} - -bool SemanticState::ConsumerImpl::doOutput() -{ - try { - return haveCredit() && queue->dispatch(shared_from_this()); - } catch (const SessionException& e) { - throw SessionOutputException(e, parent->session.getChannel()); - } -} - -void SemanticState::ConsumerImpl::enableNotify() -{ - Mutex::ScopedLock l(lock); - assertClusterSafe(); - notifyEnabled = true; -} - -void SemanticState::ConsumerImpl::disableNotify() -{ - Mutex::ScopedLock l(lock); - notifyEnabled = false; -} - -bool SemanticState::ConsumerImpl::isNotifyEnabled() const { - Mutex::ScopedLock l(lock); - return notifyEnabled; -} - -void SemanticState::ConsumerImpl::notify() -{ - Mutex::ScopedLock l(lock); - assertClusterSafe(); - if (notifyEnabled) { - parent->session.getConnection().outputTasks.addOutputTask(this); - parent->session.getConnection().outputTasks.activateOutput(); - } -} - - -// Test that a DeliveryRecord's ID is in a sequence set and some other -// predicate on DeliveryRecord holds. -template <class Predicate> struct IsInSequenceSetAnd { - IsInSequenceSet isInSet; - Predicate predicate; - IsInSequenceSetAnd(const SequenceSet& s, Predicate p) : isInSet(s), predicate(p) {} - bool operator()(DeliveryRecord& dr) { - return isInSet(dr.getId()) && predicate(dr); - } -}; - -template<class Predicate> IsInSequenceSetAnd<Predicate> -isInSequenceSetAnd(const SequenceSet& s, Predicate p) { - return IsInSequenceSetAnd<Predicate>(s,p); -} - -void SemanticState::accepted(const SequenceSet& commands) { - assertClusterSafe(); - if (txBuffer.get()) { - //in transactional mode, don't dequeue or remove, just - //maintain set of acknowledged messages: - accumulatedAck.add(commands); - - if (dtxBuffer.get()) { - //if enlisted in a dtx, copy the relevant slice from - //unacked and record it against that transaction - TxOp::shared_ptr txAck(new DtxAck(accumulatedAck, unacked)); - accumulatedAck.clear(); - dtxBuffer->enlist(txAck); - - //mark the relevant messages as 'ended' in unacked - //if the messages are already completed, they can be - //removed from the record - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), - isInSequenceSetAnd(commands, - bind(&DeliveryRecord::setEnded, _1))); - unacked.erase(removed, unacked.end()); - } - } else { - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), - isInSequenceSetAnd(commands, - bind(&DeliveryRecord::accept, _1, - (TransactionContext*) 0))); - unacked.erase(removed, unacked.end()); - } -} - -void SemanticState::completed(const SequenceSet& commands) { - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), - isInSequenceSetAnd(commands, - bind(&SemanticState::complete, this, _1))); - unacked.erase(removed, unacked.end()); - requestDispatch(); -} - -void SemanticState::attached() -{ - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - i->second->enableNotify(); - session.getConnection().outputTasks.addOutputTask(i->second.get()); - } - session.getConnection().outputTasks.activateOutput(); -} - -void SemanticState::detached() -{ - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - i->second->disableNotify(); - session.getConnection().outputTasks.removeOutputTask(i->second.get()); - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SemanticState.h b/cpp/src/qpid/broker/SemanticState.h deleted file mode 100644 index 8c69d6b89b..0000000000 --- a/cpp/src/qpid/broker/SemanticState.h +++ /dev/null @@ -1,257 +0,0 @@ -#ifndef QPID_BROKER_SEMANTICSTATE_H -#define QPID_BROKER_SEMANTICSTATE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Consumer.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/DeliveryAdapter.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/DtxBuffer.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/NameGenerator.h" -#include "qpid/broker/TxBuffer.h" - -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/AggregateOutput.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/broker/AclModule.h" -#include "qmf/org/apache/qpid/broker/Subscription.h" - -#include <list> -#include <map> -#include <vector> - -#include <boost/enable_shared_from_this.hpp> -#include <boost/intrusive_ptr.hpp> -#include <boost/cast.hpp> - -namespace qpid { -namespace broker { - -class SessionContext; - -/** - * - * SemanticState implements the behavior of a Session, especially the - * state of consumers subscribed to queues. The code for ConsumerImpl - * is also in SemanticState.cpp - * - * SemanticState holds the AMQP Execution and Model state of an open - * session, whether attached to a channel or suspended. It is not - * dependent on any specific AMQP version. - * - * Message delivery is driven by ConsumerImpl::doOutput(), which is - * called when a client's socket is ready to write data. - * - */ -class SemanticState : private boost::noncopyable { - public: - class ConsumerImpl : public Consumer, public sys::OutputTask, - public boost::enable_shared_from_this<ConsumerImpl>, - public management::Manageable - { - mutable qpid::sys::Mutex lock; - SemanticState* const parent; - const std::string name; - const boost::shared_ptr<Queue> queue; - const bool ackExpected; - const bool acquire; - bool blocked; - bool windowing; - bool exclusive; - std::string resumeId; - uint64_t resumeTtl; - framing::FieldTable arguments; - uint32_t msgCredit; - uint32_t byteCredit; - bool notifyEnabled; - const int syncFrequency; - int deliveryCount; - qmf::org::apache::qpid::broker::Subscription* mgmtObject; - - bool checkCredit(boost::intrusive_ptr<Message>& msg); - void allocateCredit(boost::intrusive_ptr<Message>& msg); - bool haveCredit(); - - public: - typedef boost::shared_ptr<ConsumerImpl> shared_ptr; - - ConsumerImpl(SemanticState* parent, - const std::string& name, boost::shared_ptr<Queue> queue, - bool ack, bool acquire, bool exclusive, - const std::string& resumeId, uint64_t resumeTtl, const framing::FieldTable& arguments); - ~ConsumerImpl(); - OwnershipToken* getSession(); - bool deliver(QueuedMessage& msg); - bool filter(boost::intrusive_ptr<Message> msg); - bool accept(boost::intrusive_ptr<Message> msg); - - void disableNotify(); - void enableNotify(); - void notify(); - bool isNotifyEnabled() const; - - void requestDispatch(); - - void setWindowMode(); - void setCreditMode(); - void addByteCredit(uint32_t value); - void addMessageCredit(uint32_t value); - void flush(); - void stop(); - void complete(DeliveryRecord&); - boost::shared_ptr<Queue> getQueue() const { return queue; } - bool isBlocked() const { return blocked; } - bool setBlocked(bool set) { std::swap(set, blocked); return set; } - - bool doOutput(); - - std::string getName() const { return name; } - - bool isAckExpected() const { return ackExpected; } - bool isAcquire() const { return acquire; } - bool isWindowing() const { return windowing; } - bool isExclusive() const { return exclusive; } - uint32_t getMsgCredit() const { return msgCredit; } - uint32_t getByteCredit() const { return byteCredit; } - std::string getResumeId() const { return resumeId; }; - uint64_t getResumeTtl() const { return resumeTtl; } - const framing::FieldTable& getArguments() const { return arguments; } - - SemanticState& getParent() { return *parent; } - const SemanticState& getParent() const { return *parent; } - // Manageable entry points - management::ManagementObject* GetManagementObject (void) const; - management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args, std::string& text); - }; - - private: - typedef std::map<std::string, ConsumerImpl::shared_ptr> ConsumerImplMap; - typedef std::map<std::string, DtxBuffer::shared_ptr> DtxBufferMap; - - SessionContext& session; - DeliveryAdapter& deliveryAdapter; - ConsumerImplMap consumers; - NameGenerator tagGenerator; - DeliveryRecords unacked; - TxBuffer::shared_ptr txBuffer; - DtxBuffer::shared_ptr dtxBuffer; - bool dtxSelected; - DtxBufferMap suspendedXids; - framing::SequenceSet accumulatedAck; - boost::shared_ptr<Exchange> cacheExchange; - AclModule* acl; - const bool authMsg; - const std::string userID; - const std::string userName; - const bool isDefaultRealm; - bool closeComplete; - - void route(boost::intrusive_ptr<Message> msg, Deliverable& strategy); - void checkDtxTimeout(); - - bool complete(DeliveryRecord&); - AckRange findRange(DeliveryId first, DeliveryId last); - void requestDispatch(); - void cancel(ConsumerImpl::shared_ptr); - void unsubscribe(ConsumerImpl::shared_ptr); - void disable(ConsumerImpl::shared_ptr); - - public: - SemanticState(DeliveryAdapter&, SessionContext&); - ~SemanticState(); - - SessionContext& getSession() { return session; } - const SessionContext& getSession() const { return session; } - - ConsumerImpl& find(const std::string& destination); - - /** - * Get named queue, never returns 0. - * @return: named queue - * @exception: ChannelException if no queue of that name is found. - * @exception: ConnectionException if name="" and session has no default. - */ - boost::shared_ptr<Queue> getQueue(const std::string& name) const; - - bool exists(const std::string& consumerTag); - - void consume(const std::string& destination, - boost::shared_ptr<Queue> queue, - bool ackRequired, bool acquire, bool exclusive, - const std::string& resumeId=std::string(), uint64_t resumeTtl=0, - const framing::FieldTable& = framing::FieldTable()); - - bool cancel(const std::string& tag); - - void setWindowMode(const std::string& destination); - void setCreditMode(const std::string& destination); - void addByteCredit(const std::string& destination, uint32_t value); - void addMessageCredit(const std::string& destination, uint32_t value); - void flush(const std::string& destination); - void stop(const std::string& destination); - - void startTx(); - void commit(MessageStore* const store); - void rollback(); - void selectDtx(); - void startDtx(const std::string& xid, DtxManager& mgr, bool join); - void endDtx(const std::string& xid, bool fail); - void suspendDtx(const std::string& xid); - void resumeDtx(const std::string& xid); - void recover(bool requeue); - void deliver(DeliveryRecord& message, bool sync); - void acquire(DeliveryId first, DeliveryId last, DeliveryIds& acquired); - void release(DeliveryId first, DeliveryId last, bool setRedelivered); - void reject(DeliveryId first, DeliveryId last); - void handle(boost::intrusive_ptr<Message> msg); - - void completed(const framing::SequenceSet& commands); - void accepted(const framing::SequenceSet& commands); - - void attached(); - void detached(); - void closed(); - - // Used by cluster to re-create sessions - template <class F> void eachConsumer(F f) { - for(ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); ++i) - f(i->second); - } - DeliveryRecords& getUnacked() { return unacked; } - framing::SequenceSet getAccumulatedAck() const { return accumulatedAck; } - TxBuffer::shared_ptr getTxBuffer() const { return txBuffer; } - void setTxBuffer(const TxBuffer::shared_ptr& txb) { txBuffer = txb; } - void setAccumulatedAck(const framing::SequenceSet& s) { accumulatedAck = s; } - void record(const DeliveryRecord& delivery); -}; - -}} // namespace qpid::broker - - - - -#endif /*!QPID_BROKER_SEMANTICSTATE_H*/ diff --git a/cpp/src/qpid/broker/SessionAdapter.cpp b/cpp/src/qpid/broker/SessionAdapter.cpp deleted file mode 100644 index 63c4b660b2..0000000000 --- a/cpp/src/qpid/broker/SessionAdapter.cpp +++ /dev/null @@ -1,693 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "qpid/broker/SessionAdapter.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/Queue.h" -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/broker/SessionState.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h" -#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h" -#include "qmf/org/apache/qpid/broker/EventQueueDelete.h" -#include "qmf/org/apache/qpid/broker/EventBind.h" -#include "qmf/org/apache/qpid/broker/EventUnbind.h" -#include "qmf/org/apache/qpid/broker/EventSubscribe.h" -#include "qmf/org/apache/qpid/broker/EventUnsubscribe.h" -#include <boost/format.hpp> -#include <boost/cast.hpp> -#include <boost/bind.hpp> - -namespace qpid { -namespace broker { - -using namespace qpid; -using namespace qpid::framing; -using namespace qpid::framing::dtx; -using namespace qpid::management; -namespace _qmf = qmf::org::apache::qpid::broker; - -typedef std::vector<Queue::shared_ptr> QueueVector; - -SessionAdapter::SessionAdapter(SemanticState& s) : - HandlerImpl(s), - exchangeImpl(s), - queueImpl(s), - messageImpl(s), - executionImpl(s), - txImpl(s), - dtxImpl(s) -{} - -static const std::string _TRUE("true"); -static const std::string _FALSE("false"); - -void SessionAdapter::ExchangeHandlerImpl::declare(const string& exchange, const string& type, - const string& alternateExchange, - bool passive, bool durable, bool /*autoDelete*/, const FieldTable& args){ - - //TODO: implement autoDelete - Exchange::shared_ptr alternate; - if (!alternateExchange.empty()) { - alternate = getBroker().getExchanges().get(alternateExchange); - } - if(passive){ - AclModule* acl = getBroker().getAcl(); - if (acl) { - //TODO: why does a passive declare require create - //permission? The purpose of the passive flag is to state - //that the exchange should *not* created. For - //authorisation a passive declare is similar to - //exchange-query. - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_TYPE, type)); - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_PASSIVE, _TRUE)); - params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE)); - if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_EXCHANGE,exchange,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange create request from " << getConnection().getUserId())); - } - Exchange::shared_ptr actual(getBroker().getExchanges().get(exchange)); - checkType(actual, type); - checkAlternate(actual, alternate); - }else{ - if(exchange.find("amq.") == 0 || exchange.find("qpid.") == 0) { - throw framing::NotAllowedException(QPID_MSG("Exchange names beginning with \"amq.\" or \"qpid.\" are reserved. (exchange=\"" << exchange << "\")")); - } - try{ - std::pair<Exchange::shared_ptr, bool> response = - getBroker().createExchange(exchange, type, durable, alternateExchange, args, - getConnection().getUserId(), getConnection().getUrl()); - if (!response.second) { - //exchange already there, not created - checkType(response.first, type); - checkAlternate(response.first, alternate); - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent) - agent->raiseEvent(_qmf::EventExchangeDeclare(getConnection().getUrl(), - getConnection().getUserId(), - exchange, - type, - alternateExchange, - durable, - false, - ManagementAgent::toMap(args), - "existing")); - } - }catch(UnknownExchangeTypeException& /*e*/){ - throw NotFoundException(QPID_MSG("Exchange type not implemented: " << type)); - } - } -} - -void SessionAdapter::ExchangeHandlerImpl::checkType(Exchange::shared_ptr exchange, const std::string& type) -{ - if (!type.empty() && exchange->getType() != type) { - throw NotAllowedException(QPID_MSG("Exchange declared to be of type " << exchange->getType() << ", requested " << type)); - } -} - -void SessionAdapter::ExchangeHandlerImpl::checkAlternate(Exchange::shared_ptr exchange, Exchange::shared_ptr alternate) -{ - if (alternate && ((exchange->getAlternate() && alternate != exchange->getAlternate()) - || !exchange->getAlternate())) - throw NotAllowedException(QPID_MSG("Exchange declared with alternate-exchange " - << (exchange->getAlternate() ? exchange->getAlternate()->getName() : "<nonexistent>") - << ", requested " - << alternate->getName())); -} - -void SessionAdapter::ExchangeHandlerImpl::delete_(const string& name, bool /*ifUnused*/) -{ - //TODO: implement if-unused - getBroker().deleteExchange(name, getConnection().getUserId(), getConnection().getUrl()); -} - -ExchangeQueryResult SessionAdapter::ExchangeHandlerImpl::query(const string& name) -{ - AclModule* acl = getBroker().getAcl(); - if (acl) { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_EXCHANGE,name,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange query request from " << getConnection().getUserId())); - } - - try { - Exchange::shared_ptr exchange(getBroker().getExchanges().get(name)); - return ExchangeQueryResult(exchange->getType(), exchange->isDurable(), false, exchange->getArgs()); - } catch (const NotFoundException& /*e*/) { - return ExchangeQueryResult("", false, true, FieldTable()); - } -} - -void SessionAdapter::ExchangeHandlerImpl::bind(const string& queueName, - const string& exchangeName, const string& routingKey, - const FieldTable& arguments) -{ - getBroker().bind(queueName, exchangeName, routingKey, arguments, - getConnection().getUserId(), getConnection().getUrl()); -} - -void SessionAdapter::ExchangeHandlerImpl::unbind(const string& queueName, - const string& exchangeName, - const string& routingKey) -{ - getBroker().unbind(queueName, exchangeName, routingKey, - getConnection().getUserId(), getConnection().getUrl()); -} - -ExchangeBoundResult SessionAdapter::ExchangeHandlerImpl::bound(const std::string& exchangeName, - const std::string& queueName, - const std::string& key, - const framing::FieldTable& args) -{ - AclModule* acl = getBroker().getAcl(); - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_QUEUENAME, queueName)); - params.insert(make_pair(acl::PROP_ROUTINGKEY, key)); - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_EXCHANGE,exchangeName,¶ms) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange bound request from " << getConnection().getUserId())); - } - - Exchange::shared_ptr exchange; - try { - exchange = getBroker().getExchanges().get(exchangeName); - } catch (const NotFoundException&) {} - - Queue::shared_ptr queue; - if (!queueName.empty()) { - queue = getBroker().getQueues().find(queueName); - } - - if (!exchange) { - return ExchangeBoundResult(true, (!queueName.empty() && !queue), false, false, false); - } else if (!queueName.empty() && !queue) { - return ExchangeBoundResult(false, true, false, false, false); - } else if (exchange->isBound(queue, key.empty() ? 0 : &key, args.count() > 0 ? &args : &args)) { - return ExchangeBoundResult(false, false, false, false, false); - } else { - //need to test each specified option individually - bool queueMatched = queueName.empty() || exchange->isBound(queue, 0, 0); - bool keyMatched = key.empty() || exchange->isBound(Queue::shared_ptr(), &key, 0); - bool argsMatched = args.count() == 0 || exchange->isBound(Queue::shared_ptr(), 0, &args); - - return ExchangeBoundResult(false, false, !queueMatched, !keyMatched, !argsMatched); - } -} - -SessionAdapter::QueueHandlerImpl::QueueHandlerImpl(SemanticState& session) : HandlerHelper(session), broker(getBroker()) -{} - - -SessionAdapter::QueueHandlerImpl::~QueueHandlerImpl() -{ - try { - destroyExclusiveQueues(); - } catch (std::exception& e) { - QPID_LOG(error, e.what()); - } -} - -void SessionAdapter::QueueHandlerImpl::destroyExclusiveQueues() -{ - while (!exclusiveQueues.empty()) { - Queue::shared_ptr q(exclusiveQueues.front()); - q->releaseExclusiveOwnership(); - if (q->canAutoDelete()) { - Queue::tryAutoDelete(broker, q); - } - exclusiveQueues.erase(exclusiveQueues.begin()); - } -} - -bool SessionAdapter::QueueHandlerImpl::isLocal(const ConnectionToken* t) const -{ - return session.isLocal(t); -} - - -QueueQueryResult SessionAdapter::QueueHandlerImpl::query(const string& name) -{ - AclModule* acl = getBroker().getAcl(); - if (acl) { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_QUEUE,name,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied queue query request from " << getConnection().getUserId())); - } - - Queue::shared_ptr queue = session.getBroker().getQueues().find(name); - if (queue) { - - Exchange::shared_ptr alternateExchange = queue->getAlternateExchange(); - - return QueueQueryResult(queue->getName(), - alternateExchange ? alternateExchange->getName() : "", - queue->isDurable(), - queue->hasExclusiveOwner(), - queue->isAutoDelete(), - queue->getSettings(), - queue->getMessageCount(), - queue->getConsumerCount()); - } else { - return QueueQueryResult(); - } -} - -void SessionAdapter::QueueHandlerImpl::declare(const string& name, const string& alternateExchange, - bool passive, bool durable, bool exclusive, - bool autoDelete, const qpid::framing::FieldTable& arguments) -{ - Queue::shared_ptr queue; - if (passive && !name.empty()) { - AclModule* acl = getBroker().getAcl(); - if (acl) { - //TODO: why does a passive declare require create - //permission? The purpose of the passive flag is to state - //that the queue should *not* created. For - //authorisation a passive declare is similar to - //queue-query (or indeed a qmf query). - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_PASSIVE, _TRUE)); - params.insert(make_pair(acl::PROP_DURABLE, std::string(durable ? _TRUE : _FALSE))); - params.insert(make_pair(acl::PROP_EXCLUSIVE, std::string(exclusive ? _TRUE : _FALSE))); - params.insert(make_pair(acl::PROP_AUTODELETE, std::string(autoDelete ? _TRUE : _FALSE))); - params.insert(make_pair(acl::PROP_POLICYTYPE, arguments.getAsString("qpid.policy_type"))); - params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast<string>(arguments.getAsInt("qpid.max_count")))); - params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast<string>(arguments.getAsInt64("qpid.max_size")))); - if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_QUEUE,name,¶ms) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << getConnection().getUserId())); - } - queue = getQueue(name); - //TODO: check alternate-exchange is as expected - } else { - std::pair<Queue::shared_ptr, bool> queue_created = - getBroker().createQueue(name, durable, - autoDelete, - exclusive ? &session : 0, - alternateExchange, - arguments, - getConnection().getUserId(), - getConnection().getUrl()); - queue = queue_created.first; - assert(queue); - if (queue_created.second) { // This is a new queue - //handle automatic cleanup: - if (exclusive) { - exclusiveQueues.push_back(queue); - } - } else { - if (exclusive && queue->setExclusiveOwner(&session)) { - exclusiveQueues.push_back(queue); - } - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent) - agent->raiseEvent(_qmf::EventQueueDeclare(getConnection().getUrl(), getConnection().getUserId(), - name, durable, exclusive, autoDelete, ManagementAgent::toMap(arguments), - "existing")); - } - - } - - if (exclusive && !queue->isExclusiveOwner(&session)) - throw ResourceLockedException(QPID_MSG("Cannot grant exclusive access to queue " - << queue->getName())); -} - -void SessionAdapter::QueueHandlerImpl::purge(const string& queue){ - AclModule* acl = getBroker().getAcl(); - if (acl) - { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_PURGE,acl::OBJ_QUEUE,queue,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied queue purge request from " << getConnection().getUserId())); - } - getQueue(queue)->purge(); -} - -void SessionAdapter::QueueHandlerImpl::checkDelete(Queue::shared_ptr queue, bool ifUnused, bool ifEmpty) -{ - if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(&session)) { - throw ResourceLockedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; it is exclusive to another session")); - } else if(ifEmpty && queue->getMessageCount() > 0) { - throw PreconditionFailedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; queue not empty")); - } else if(ifUnused && queue->getConsumerCount() > 0) { - throw PreconditionFailedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; queue in use")); - } else if (queue->isExclusiveOwner(&session)) { - //remove the queue from the list of exclusive queues if necessary - QueueVector::iterator i = std::find(exclusiveQueues.begin(), - exclusiveQueues.end(), - queue); - if (i < exclusiveQueues.end()) exclusiveQueues.erase(i); - } -} - -void SessionAdapter::QueueHandlerImpl::delete_(const string& queue, bool ifUnused, bool ifEmpty) -{ - getBroker().deleteQueue(queue, getConnection().getUserId(), getConnection().getUrl(), - boost::bind(&SessionAdapter::QueueHandlerImpl::checkDelete, this, _1, ifUnused, ifEmpty)); -} - -SessionAdapter::MessageHandlerImpl::MessageHandlerImpl(SemanticState& s) : - HandlerHelper(s), - releaseRedeliveredOp(boost::bind(&SemanticState::release, &state, _1, _2, true)), - releaseOp(boost::bind(&SemanticState::release, &state, _1, _2, false)), - rejectOp(boost::bind(&SemanticState::reject, &state, _1, _2)) - {} - -// -// Message class method handlers -// - -void SessionAdapter::MessageHandlerImpl::transfer(const string& /*destination*/, - uint8_t /*acceptMode*/, - uint8_t /*acquireMode*/) -{ - //not yet used (content containing assemblies treated differently at present - std::cout << "SessionAdapter::MessageHandlerImpl::transfer() called" << std::endl; -} - -void SessionAdapter::MessageHandlerImpl::release(const SequenceSet& transfers, bool setRedelivered) -{ - transfers.for_each(setRedelivered ? releaseRedeliveredOp : releaseOp); -} - -void -SessionAdapter::MessageHandlerImpl::subscribe(const string& queueName, - const string& destination, - uint8_t acceptMode, - uint8_t acquireMode, - bool exclusive, - const string& resumeId, - uint64_t resumeTtl, - const FieldTable& arguments) -{ - - AclModule* acl = getBroker().getAcl(); - if (acl) - { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_CONSUME,acl::OBJ_QUEUE,queueName,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied Queue subscribe request from " << getConnection().getUserId())); - } - - Queue::shared_ptr queue = getQueue(queueName); - if(!destination.empty() && state.exists(destination)) - throw NotAllowedException(QPID_MSG("Consumer tags must be unique")); - - if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(&session) && acquireMode == 0) - throw ResourceLockedException(QPID_MSG("Cannot subscribe to exclusive queue " - << queue->getName())); - - state.consume(destination, queue, - acceptMode == 0, acquireMode == 0, exclusive, - resumeId, resumeTtl, arguments); - - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent) - agent->raiseEvent(_qmf::EventSubscribe(getConnection().getUrl(), getConnection().getUserId(), - queueName, destination, exclusive, ManagementAgent::toMap(arguments))); -} - -void -SessionAdapter::MessageHandlerImpl::cancel(const string& destination ) -{ - if (!state.cancel(destination)) { - throw NotFoundException(QPID_MSG("No such subscription: " << destination)); - } - - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent) - agent->raiseEvent(_qmf::EventUnsubscribe(getConnection().getUrl(), getConnection().getUserId(), destination)); -} - -void -SessionAdapter::MessageHandlerImpl::reject(const SequenceSet& transfers, uint16_t /*code*/, const string& /*text*/ ) -{ - transfers.for_each(rejectOp); -} - -void SessionAdapter::MessageHandlerImpl::flow(const std::string& destination, uint8_t unit, uint32_t value) -{ - if (unit == 0) { - //message - state.addMessageCredit(destination, value); - } else if (unit == 1) { - //bytes - state.addByteCredit(destination, value); - } else { - //unknown - throw InvalidArgumentException(QPID_MSG("Invalid value for unit " << unit)); - } - -} - -void SessionAdapter::MessageHandlerImpl::setFlowMode(const std::string& destination, uint8_t mode) -{ - if (mode == 0) { - //credit - state.setCreditMode(destination); - } else if (mode == 1) { - //window - state.setWindowMode(destination); - } else{ - throw InvalidArgumentException(QPID_MSG("Invalid value for mode " << mode)); - } -} - -void SessionAdapter::MessageHandlerImpl::flush(const std::string& destination) -{ - state.flush(destination); -} - -void SessionAdapter::MessageHandlerImpl::stop(const std::string& destination) -{ - state.stop(destination); -} - -void SessionAdapter::MessageHandlerImpl::accept(const framing::SequenceSet& commands) -{ - state.accepted(commands); -} - -framing::MessageAcquireResult SessionAdapter::MessageHandlerImpl::acquire(const framing::SequenceSet& transfers) -{ - // FIXME aconway 2008-05-12: create SequenceSet directly, no need for intermediate results vector. - SequenceNumberSet results; - RangedOperation f = boost::bind(&SemanticState::acquire, &state, _1, _2, boost::ref(results)); - transfers.for_each(f); - - results = results.condense(); - SequenceSet acquisitions; - RangedOperation g = boost::bind(&SequenceSet::add, &acquisitions, _1, _2); - results.processRanges(g); - - return MessageAcquireResult(acquisitions); -} - -framing::MessageResumeResult SessionAdapter::MessageHandlerImpl::resume(const std::string& /*destination*/, - const std::string& /*resumeId*/) -{ - throw NotImplementedException("resuming transfers not yet supported"); -} - - - -void SessionAdapter::ExecutionHandlerImpl::sync() -{ - session.addPendingExecutionSync(); - /** @todo KAG - need a generic mechanism to allow a command to returning "not completed" status back to SessionState */ - -} - -void SessionAdapter::ExecutionHandlerImpl::result(const SequenceNumber& /*commandId*/, const string& /*value*/) -{ - //TODO: but currently never used client->server -} - -void SessionAdapter::ExecutionHandlerImpl::exception(uint16_t /*errorCode*/, - const SequenceNumber& /*commandId*/, - uint8_t /*classCode*/, - uint8_t /*commandCode*/, - uint8_t /*fieldIndex*/, - const std::string& /*description*/, - const framing::FieldTable& /*errorInfo*/) -{ - //TODO: again, not really used client->server but may be important - //for inter-broker links -} - - - -void SessionAdapter::TxHandlerImpl::select() -{ - state.startTx(); -} - -void SessionAdapter::TxHandlerImpl::commit() -{ - state.commit(&getBroker().getStore()); -} - -void SessionAdapter::TxHandlerImpl::rollback() -{ - state.rollback(); -} - -std::string SessionAdapter::DtxHandlerImpl::convert(const framing::Xid& xid) -{ - std::string encoded; - encode(xid, encoded); - return encoded; -} - -void SessionAdapter::DtxHandlerImpl::select() -{ - state.selectDtx(); -} - -XaResult SessionAdapter::DtxHandlerImpl::end(const Xid& xid, - bool fail, - bool suspend) -{ - try { - if (fail) { - state.endDtx(convert(xid), true); - if (suspend) { - throw CommandInvalidException(QPID_MSG("End and suspend cannot both be set.")); - } else { - return XaResult(XA_STATUS_XA_RBROLLBACK); - } - } else { - if (suspend) { - state.suspendDtx(convert(xid)); - } else { - state.endDtx(convert(xid), false); - } - return XaResult(XA_STATUS_XA_OK); - } - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -XaResult SessionAdapter::DtxHandlerImpl::start(const Xid& xid, - bool join, - bool resume) -{ - if (join && resume) { - throw CommandInvalidException(QPID_MSG("Join and resume cannot both be set.")); - } - try { - if (resume) { - state.resumeDtx(convert(xid)); - } else { - state.startDtx(convert(xid), getBroker().getDtxManager(), join); - } - return XaResult(XA_STATUS_XA_OK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -XaResult SessionAdapter::DtxHandlerImpl::prepare(const Xid& xid) -{ - try { - bool ok = getBroker().getDtxManager().prepare(convert(xid)); - return XaResult(ok ? XA_STATUS_XA_OK : XA_STATUS_XA_RBROLLBACK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -XaResult SessionAdapter::DtxHandlerImpl::commit(const Xid& xid, - bool onePhase) -{ - try { - bool ok = getBroker().getDtxManager().commit(convert(xid), onePhase); - return XaResult(ok ? XA_STATUS_XA_OK : XA_STATUS_XA_RBROLLBACK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - - -XaResult SessionAdapter::DtxHandlerImpl::rollback(const Xid& xid) -{ - try { - getBroker().getDtxManager().rollback(convert(xid)); - return XaResult(XA_STATUS_XA_OK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -DtxRecoverResult SessionAdapter::DtxHandlerImpl::recover() -{ - std::set<std::string> xids; - getBroker().getStore().collectPreparedXids(xids); - /* - * create array of long structs - */ - Array indoubt(0xAB); - for (std::set<std::string>::iterator i = xids.begin(); i != xids.end(); i++) { - boost::shared_ptr<FieldValue> xid(new Struct32Value(*i)); - indoubt.add(xid); - } - return DtxRecoverResult(indoubt); -} - -void SessionAdapter::DtxHandlerImpl::forget(const Xid& xid) -{ - //Currently no heuristic completion is supported, so this should never be used. - throw NotImplementedException(QPID_MSG("Forget not implemented. Branch with xid " << xid << " not heuristically completed!")); -} - -DtxGetTimeoutResult SessionAdapter::DtxHandlerImpl::getTimeout(const Xid& xid) -{ - uint32_t timeout = getBroker().getDtxManager().getTimeout(convert(xid)); - return DtxGetTimeoutResult(timeout); -} - - -void SessionAdapter::DtxHandlerImpl::setTimeout(const Xid& xid, - uint32_t timeout) -{ - getBroker().getDtxManager().setTimeout(convert(xid), timeout); -} - - -Queue::shared_ptr SessionAdapter::HandlerHelper::getQueue(const string& name) const { - Queue::shared_ptr queue; - if (name.empty()) { - throw framing::IllegalArgumentException(QPID_MSG("No queue name specified.")); - } else { - queue = session.getBroker().getQueues().find(name); - if (!queue) - throw framing::NotFoundException(QPID_MSG("Queue not found: "<<name)); - } - return queue; -} - -}} // namespace qpid::broker - - diff --git a/cpp/src/qpid/broker/SessionAdapter.h b/cpp/src/qpid/broker/SessionAdapter.h deleted file mode 100644 index 8987c4812f..0000000000 --- a/cpp/src/qpid/broker/SessionAdapter.h +++ /dev/null @@ -1,273 +0,0 @@ -#ifndef _broker_SessionAdapter_h -#define _broker_SessionAdapter_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/broker/HandlerImpl.h" - -#include "qpid/broker/ConnectionToken.h" -#include "qpid/broker/OwnershipToken.h" -#include "qpid/Exception.h" -#include "qpid/framing/AMQP_ServerOperations.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/StructHelper.h" - -#include <algorithm> -#include <vector> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -class Channel; -class Connection; -class Broker; -class Queue; - -/** - * SessionAdapter translates protocol-specific AMQP commands for one - * specific version of AMQP into calls on the core broker objects. It - * is a container for a collection of adapters. - * - * Each adapter class provides a client proxy to send methods to the - * peer broker or client. - * - */ - - class SessionAdapter : public HandlerImpl, public framing::AMQP_ServerOperations -{ - public: - SessionAdapter(SemanticState& session); - - framing::ProtocolVersion getVersion() const { return session.getConnection().getVersion();} - - MessageHandler* getMessageHandler(){ return &messageImpl; } - ExchangeHandler* getExchangeHandler(){ return &exchangeImpl; } - QueueHandler* getQueueHandler(){ return &queueImpl; } - ExecutionHandler* getExecutionHandler(){ return &executionImpl; } - TxHandler* getTxHandler(){ return &txImpl; } - DtxHandler* getDtxHandler(){ return &dtxImpl; } - - ConnectionHandler* getConnectionHandler() { throw framing::NotImplementedException("Class not implemented"); } - SessionHandler* getSessionHandler() { throw framing::NotImplementedException("Class not implemented"); } - FileHandler* getFileHandler() { throw framing::NotImplementedException("Class not implemented"); } - StreamHandler* getStreamHandler() { throw framing::NotImplementedException("Class not implemented"); } - - template <class F> void eachExclusiveQueue(F f) - { - queueImpl.eachExclusiveQueue(f); - } - - - private: - //common base for utility methods etc that are specific to this adapter - struct HandlerHelper : public HandlerImpl - { - HandlerHelper(SemanticState& s) : HandlerImpl(s) {} - - boost::shared_ptr<Queue> getQueue(const std::string& name) const; - }; - - - class ExchangeHandlerImpl : - public ExchangeHandler, - public HandlerHelper - { - public: - ExchangeHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void declare(const std::string& exchange, const std::string& type, - const std::string& alternateExchange, - bool passive, bool durable, bool autoDelete, - const qpid::framing::FieldTable& arguments); - void delete_(const std::string& exchange, bool ifUnused); - framing::ExchangeQueryResult query(const std::string& name); - void bind(const std::string& queue, - const std::string& exchange, const std::string& routingKey, - const qpid::framing::FieldTable& arguments); - void unbind(const std::string& queue, - const std::string& exchange, - const std::string& routingKey); - framing::ExchangeBoundResult bound(const std::string& exchange, - const std::string& queue, - const std::string& routingKey, - const framing::FieldTable& arguments); - private: - void checkType(boost::shared_ptr<Exchange> exchange, const std::string& type); - - void checkAlternate(boost::shared_ptr<Exchange> exchange, - boost::shared_ptr<Exchange> alternate); - }; - - class QueueHandlerImpl : public QueueHandler, - public HandlerHelper - { - Broker& broker; - std::vector< boost::shared_ptr<Queue> > exclusiveQueues; - - public: - QueueHandlerImpl(SemanticState& session); - ~QueueHandlerImpl(); - - void declare(const std::string& queue, - const std::string& alternateExchange, - bool passive, bool durable, bool exclusive, - bool autoDelete, - const qpid::framing::FieldTable& arguments); - void delete_(const std::string& queue, - bool ifUnused, bool ifEmpty); - void purge(const std::string& queue); - framing::QueueQueryResult query(const std::string& queue); - bool isLocal(const ConnectionToken* t) const; - - void destroyExclusiveQueues(); - void checkDelete(boost::shared_ptr<Queue> queue, bool ifUnused, bool ifEmpty); - template <class F> void eachExclusiveQueue(F f) - { - std::for_each(exclusiveQueues.begin(), exclusiveQueues.end(), f); - } - }; - - class MessageHandlerImpl : - public MessageHandler, - public HandlerHelper - { - typedef boost::function<void(DeliveryId, DeliveryId)> RangedOperation; - RangedOperation releaseRedeliveredOp; - RangedOperation releaseOp; - RangedOperation rejectOp; - RangedOperation acceptOp; - - public: - MessageHandlerImpl(SemanticState& session); - void transfer(const std::string& destination, - uint8_t acceptMode, - uint8_t acquireMode); - - void accept(const framing::SequenceSet& commands); - - void reject(const framing::SequenceSet& commands, - uint16_t code, - const std::string& text); - - void release(const framing::SequenceSet& commands, - bool setRedelivered); - - framing::MessageAcquireResult acquire(const framing::SequenceSet&); - - void subscribe(const std::string& queue, - const std::string& destination, - uint8_t acceptMode, - uint8_t acquireMode, - bool exclusive, - const std::string& resumeId, - uint64_t resumeTtl, - const framing::FieldTable& arguments); - - void cancel(const std::string& destination); - - void setFlowMode(const std::string& destination, - uint8_t flowMode); - - void flow(const std::string& destination, - uint8_t unit, - uint32_t value); - - void flush(const std::string& destination); - - void stop(const std::string& destination); - - framing::MessageResumeResult resume(const std::string& destination, - const std::string& resumeId); - - }; - - class ExecutionHandlerImpl : public ExecutionHandler, public HandlerHelper - { - public: - ExecutionHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void sync(); - void result(const framing::SequenceNumber& commandId, const std::string& value); - void exception(uint16_t errorCode, - const framing::SequenceNumber& commandId, - uint8_t classCode, - uint8_t commandCode, - uint8_t fieldIndex, - const std::string& description, - const framing::FieldTable& errorInfo); - - }; - - class TxHandlerImpl : public TxHandler, public HandlerHelper - { - public: - TxHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void select(); - void commit(); - void rollback(); - }; - - class DtxHandlerImpl : public DtxHandler, public HandlerHelper, private framing::StructHelper - { - std::string convert(const framing::Xid& xid); - - public: - DtxHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void select(); - - framing::XaResult start(const framing::Xid& xid, - bool join, - bool resume); - - framing::XaResult end(const framing::Xid& xid, - bool fail, - bool suspend); - - framing::XaResult commit(const framing::Xid& xid, - bool onePhase); - - void forget(const framing::Xid& xid); - - framing::DtxGetTimeoutResult getTimeout(const framing::Xid& xid); - - framing::XaResult prepare(const framing::Xid& xid); - - framing::DtxRecoverResult recover(); - - framing::XaResult rollback(const framing::Xid& xid); - - void setTimeout(const framing::Xid& xid, uint32_t timeout); - }; - - ExchangeHandlerImpl exchangeImpl; - QueueHandlerImpl queueImpl; - MessageHandlerImpl messageImpl; - ExecutionHandlerImpl executionImpl; - TxHandlerImpl txImpl; - DtxHandlerImpl dtxImpl; -}; -}} // namespace qpid::broker - - - -#endif /*!_broker_SessionAdapter_h*/ diff --git a/cpp/src/qpid/broker/SessionContext.h b/cpp/src/qpid/broker/SessionContext.h deleted file mode 100644 index 253ce8dcf2..0000000000 --- a/cpp/src/qpid/broker/SessionContext.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef QPID_BROKER_SESSIONCONTEXT_H -#define QPID_BROKER_SESSIONCONTEXT_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/OwnershipToken.h" -#include "qpid/SessionId.h" - -#include <boost/noncopyable.hpp> - -namespace qpid { -namespace broker { - -class SessionContext : public OwnershipToken, public sys::OutputControl -{ - public: - virtual ~SessionContext(){} - virtual bool isLocal(const ConnectionToken* t) const = 0; - virtual bool isAttached() const = 0; - virtual ConnectionState& getConnection() = 0; - virtual framing::AMQP_ClientProxy& getProxy() = 0; - virtual Broker& getBroker() = 0; - virtual uint16_t getChannel() const = 0; - virtual const SessionId& getSessionId() const = 0; - virtual void addPendingExecutionSync() = 0; -}; - -}} // namespace qpid::broker - - - -#endif /*!QPID_BROKER_SESSIONCONTEXT_H*/ diff --git a/cpp/src/qpid/broker/SessionHandler.cpp b/cpp/src/qpid/broker/SessionHandler.cpp deleted file mode 100644 index 752fa55535..0000000000 --- a/cpp/src/qpid/broker/SessionHandler.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/SessionHandler.h" -#include "qpid/broker/SessionState.h" -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" - -#include <boost/bind.hpp> - -namespace qpid { -namespace broker { -using namespace framing; -using namespace std; -using namespace qpid::sys; - -SessionHandler::SessionHandler(Connection& c, ChannelId ch) - : amqp_0_10::SessionHandler(&c.getOutput(), ch), - connection(c), - proxy(out), - clusterOrderProxy(c.getClusterOrderOutput() ? new SetChannelProxy(ch, c.getClusterOrderOutput()) : 0) -{} - -SessionHandler::~SessionHandler() {} - -void SessionHandler::connectionException(framing::connection::CloseCode code, const std::string& msg) { - // NOTE: must tell the error listener _before_ calling connection.close() - if (connection.getErrorListener()) connection.getErrorListener()->connectionError(msg); - connection.close(code, msg); -} - -void SessionHandler::channelException(framing::session::DetachCode, const std::string& msg) { - if (connection.getErrorListener()) connection.getErrorListener()->sessionError(getChannel(), msg); -} - -void SessionHandler::executionException(framing::execution::ErrorCode, const std::string& msg) { - if (connection.getErrorListener()) connection.getErrorListener()->sessionError(getChannel(), msg); -} - -ConnectionState& SessionHandler::getConnection() { return connection; } - -const ConnectionState& SessionHandler::getConnection() const { return connection; } - -void SessionHandler::handleDetach() { - amqp_0_10::SessionHandler::handleDetach(); - assert(&connection.getChannel(channel.get()) == this); - if (session.get()) - connection.getBroker().getSessionManager().detach(session); - assert(!session.get()); - connection.closeChannel(channel.get()); -} - -void SessionHandler::setState(const std::string& name, bool force) { - assert(!session.get()); - SessionId id(connection.getUserId(), name); - session = connection.broker.getSessionManager().attach(*this, id, force); -} - -void SessionHandler::detaching() -{ - assert(session.get()); - session->disableOutput(); -} - -FrameHandler* SessionHandler::getInHandler() { return session.get() ? &session->in : 0; } -qpid::SessionState* SessionHandler::getState() { return session.get(); } - -void SessionHandler::readyToSend() { - if (session.get()) session->readyToSend(); -} - -/** - * Used by inter-broker bridges to set up session id and attach - */ -void SessionHandler::attachAs(const std::string& name) -{ - SessionId id(connection.getUserId(), name); - SessionState::Configuration config = connection.broker.getSessionManager().getSessionConfig(); - // Delay creating management object till attached(). In a cluster, - // only the active link broker calls attachAs but all brokers - // receive the subsequent attached() call. - session.reset(new SessionState(connection.getBroker(), *this, id, config, true)); - sendAttach(false); -} - -/** - * TODO: this is a little ugly, fix it; its currently still relied on - * for 'push' bridges - */ -void SessionHandler::attached(const std::string& name) -{ - if (session.get()) { - session->addManagementObject(); // Delayed from attachAs() - amqp_0_10::SessionHandler::attached(name); - } else { - SessionId id(connection.getUserId(), name); - SessionState::Configuration config = connection.broker.getSessionManager().getSessionConfig(); - session.reset(new SessionState(connection.getBroker(), *this, id, config)); - markReadyToSend(); - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SessionHandler.h b/cpp/src/qpid/broker/SessionHandler.h deleted file mode 100644 index ca6d6bb193..0000000000 --- a/cpp/src/qpid/broker/SessionHandler.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef QPID_BROKER_SESSIONHANDLER_H -#define QPID_BROKER_SESSIONHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/SessionHandler.h" -#include "qpid/framing/AMQP_ClientProxy.h" - -namespace qpid { -class SessionState; - -namespace broker { - -class Connection; -class ConnectionState; -class SessionState; - -/** - * A SessionHandler is associated with each active channel. It - * receives incoming frames, handles session controls and manages the - * association between the channel and a session. - */ -class SessionHandler : public amqp_0_10::SessionHandler { - public: - SessionHandler(Connection&, framing::ChannelId); - ~SessionHandler(); - - /** Get broker::SessionState */ - SessionState* getSession() { return session.get(); } - const SessionState* getSession() const { return session.get(); } - - ConnectionState& getConnection(); - const ConnectionState& getConnection() const; - - framing::AMQP_ClientProxy& getProxy() { return proxy; } - const framing::AMQP_ClientProxy& getProxy() const { return proxy; } - - /** - * If commands are sent based on the local time (e.g. in timers), they don't have - * a well-defined ordering across cluster nodes. - * This proxy is for sending such commands. In a clustered broker it will take steps - * to synchronize command order across the cluster. In a stand-alone broker - * it is just a synonym for getProxy() - */ - framing::AMQP_ClientProxy& getClusterOrderProxy() { - return clusterOrderProxy.get() ? *clusterOrderProxy : proxy; - } - - virtual void handleDetach(); - void attached(const std::string& name);//used by 'pushing' inter-broker bridges - void attachAs(const std::string& name);//used by 'pulling' inter-broker bridges - - protected: - virtual void setState(const std::string& sessionName, bool force); - virtual qpid::SessionState* getState(); - virtual framing::FrameHandler* getInHandler(); - virtual void connectionException(framing::connection::CloseCode code, const std::string& msg); - virtual void channelException(framing::session::DetachCode, const std::string& msg); - virtual void executionException(framing::execution::ErrorCode, const std::string& msg); - virtual void detaching(); - virtual void readyToSend(); - - private: - struct SetChannelProxy : public framing::AMQP_ClientProxy { // Proxy that sets the channel. - framing::ChannelHandler setChannel; - SetChannelProxy(uint16_t ch, framing::FrameHandler* out) - : framing::AMQP_ClientProxy(setChannel), setChannel(ch, out) {} - }; - - Connection& connection; - framing::AMQP_ClientProxy proxy; - std::auto_ptr<SessionState> session; - std::auto_ptr<SetChannelProxy> clusterOrderProxy; -}; - -}} // namespace qpid::broker - - - -#endif /*!QPID_BROKER_SESSIONHANDLER_H*/ diff --git a/cpp/src/qpid/broker/SessionManager.cpp b/cpp/src/qpid/broker/SessionManager.cpp deleted file mode 100644 index 8cc58571af..0000000000 --- a/cpp/src/qpid/broker/SessionManager.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/SessionManager.h" -#include "qpid/broker/SessionState.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/log/Helpers.h" -#include "qpid/memory.h" - -#include <boost/bind.hpp> -#include <boost/range.hpp> - -#include <algorithm> -#include <functional> -#include <ostream> - -namespace qpid { -namespace broker { - -using boost::intrusive_ptr; -using namespace sys; -using namespace framing; - -SessionManager::SessionManager(const SessionState::Configuration& c, Broker& b) - : config(c), broker(b) {} - -SessionManager::~SessionManager() { - detached.clear(); // Must clear before destructor as session dtor will call forget() -} - -std::auto_ptr<SessionState> SessionManager::attach(SessionHandler& h, const SessionId& id, bool/*force*/) { - Mutex::ScopedLock l(lock); - eraseExpired(); // Clean up expired table - std::pair<Attached::iterator, bool> insert = attached.insert(id); - if (!insert.second) - throw SessionBusyException(QPID_MSG("Session already attached: " << id)); - Detached::iterator i = std::find(detached.begin(), detached.end(), id); - std::auto_ptr<SessionState> state; - if (i == detached.end()) - state.reset(new SessionState(broker, h, id, config)); - else { - state.reset(detached.release(i).release()); - state->attach(h); - } - return state; - // FIXME aconway 2008-04-29: implement force -} - -void SessionManager::detach(std::auto_ptr<SessionState> session) { - Mutex::ScopedLock l(lock); - attached.erase(session->getId()); - session->detach(); - if (session->getTimeout() > 0) { - session->expiry = AbsTime(now(),session->getTimeout()*TIME_SEC); - if (session->mgmtObject != 0) - session->mgmtObject->set_expireTime ((uint64_t) Duration (EPOCH, session->expiry)); - detached.push_back(session.release()); // In expiry order - eraseExpired(); -} -} - -void SessionManager::forget(const SessionId& id) { - Mutex::ScopedLock l(lock); - attached.erase(id); -} - -void SessionManager::eraseExpired() { - // Called with lock held. - if (!detached.empty()) { - // This used to use a more elegant invocation of std::lower_bound - // but violated the strict weak ordering rule which Visual Studio - // enforced. See QPID-1424 for more info should you be tempted to - // replace the loop with something more elegant. - AbsTime now = AbsTime::now(); - Detached::iterator keep = detached.begin(); - while ((keep != detached.end()) && ((*keep).expiry < now)) - keep++; - if (detached.begin() != keep) { - QPID_LOG(debug, "Expiring sessions: " << log::formatList(detached.begin(), keep)); - detached.erase(detached.begin(), keep); - } - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SessionManager.h b/cpp/src/qpid/broker/SessionManager.h deleted file mode 100644 index db88e7ec10..0000000000 --- a/cpp/src/qpid/broker/SessionManager.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef QPID_BROKER_SESSIONMANAGER_H -#define QPID_BROKER_SESSIONMANAGER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/SessionState.h> -#include <qpid/sys/Time.h> -#include <qpid/sys/Mutex.h> -#include <qpid/RefCounted.h> - -#include <set> -#include <vector> -#include <memory> - -#include <boost/noncopyable.hpp> -#include <boost/ptr_container/ptr_vector.hpp> -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace broker { -class Broker; -class SessionState; -class SessionHandler; - -/** - * Create and manage SessionState objects. - */ -class SessionManager : private boost::noncopyable { - public: - SessionManager(const qpid::SessionState::Configuration&, Broker&); - - ~SessionManager(); - - /** Open a new active session, caller takes ownership */ - std::auto_ptr<SessionState> attach(SessionHandler& h, const SessionId& id, bool/*force*/); - - /** Return a detached session to the manager, start the timeout counter. */ - void detach(std::auto_ptr<SessionState>); - - /** Forget about an attached session. Called by SessionState destructor. */ - void forget(const SessionId&); - - Broker& getBroker() const { return broker; } - - const qpid::SessionState::Configuration& getSessionConfig() const { return config; } - - private: - typedef boost::ptr_vector<SessionState> Detached; // Sorted in expiry order. - typedef std::set<SessionId> Attached; - - void eraseExpired(); - - sys::Mutex lock; - Detached detached; - Attached attached; - qpid::SessionState::Configuration config; - Broker& broker; -}; - - - -}} // namespace qpid::broker - - - - - -#endif /*!QPID_BROKER_SESSIONMANAGER_H*/ diff --git a/cpp/src/qpid/broker/SessionOutputException.h b/cpp/src/qpid/broker/SessionOutputException.h deleted file mode 100644 index 7c1c5de926..0000000000 --- a/cpp/src/qpid/broker/SessionOutputException.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_BROKER_SESSIONOUTPUTEXCEPTION_H -#define QPID_BROKER_SESSIONOUTPUTEXCEPTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Exception.h" - -namespace qpid { -namespace broker { - -/** - * This exception is used to signal 'session' exceptions (aka - * execution exceptions in AMQP 0-10 terms) that occur during output - * processing. It simply allows the channel of the session to be - * specified in addition to the other details. Special treatment is - * required at present because the output processing chain is - * different from that which handles incoming commands (specifically - * AggregateOutput cannot reasonably handle exceptions as it has no - * context). - */ -struct SessionOutputException : qpid::SessionException -{ - const uint16_t channel; - SessionOutputException(const qpid::SessionException& e, uint16_t c) : qpid::SessionException(e.code, e.getMessage()), channel(c) {} -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SESSIONOUTPUTEXCEPTION_H*/ diff --git a/cpp/src/qpid/broker/SessionState.cpp b/cpp/src/qpid/broker/SessionState.cpp deleted file mode 100644 index 957d5bd4d2..0000000000 --- a/cpp/src/qpid/broker/SessionState.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/SessionState.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/SessionManager.h" -#include "qpid/broker/SessionHandler.h" -#include "qpid/broker/RateFlowcontrol.h" -#include "qpid/sys/Timer.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/ServerInvoker.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/AMQP_ClientProxy.h" - -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> - -namespace qpid { -namespace broker { - -using namespace framing; -using sys::Mutex; -using boost::intrusive_ptr; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::sys::AbsTime; -//using qpid::sys::Timer; -namespace _qmf = qmf::org::apache::qpid::broker; - -SessionState::SessionState( - Broker& b, SessionHandler& h, const SessionId& id, - const SessionState::Configuration& config, bool delayManagement) - : qpid::SessionState(id, config), - broker(b), handler(&h), - semanticState(*this, *this), - adapter(semanticState), - msgBuilder(&broker.getStore()), - mgmtObject(0), - rateFlowcontrol(0), - asyncCommandCompleter(new AsyncCommandCompleter(this)) -{ - uint32_t maxRate = broker.getOptions().maxSessionRate; - if (maxRate) { - if (handler->getConnection().getClientThrottling()) { - rateFlowcontrol.reset(new RateFlowcontrol(maxRate)); - } else { - QPID_LOG(warning, getId() << ": Unable to flow control client - client doesn't support"); - } - } - if (!delayManagement) addManagementObject(); - attach(h); -} - -void SessionState::addManagementObject() { - if (GetManagementObject()) return; // Already added. - Manageable* parent = broker.GetVhostObject (); - if (parent != 0) { - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent != 0) { - mgmtObject = new _qmf::Session - (agent, this, parent, getId().getName()); - mgmtObject->set_attached (0); - mgmtObject->set_detachedLifespan (0); - mgmtObject->clr_expireTime(); - if (rateFlowcontrol) - mgmtObject->set_maxClientRate(rateFlowcontrol->getRate()); - agent->addObject(mgmtObject); - } - } -} - -SessionState::~SessionState() { - asyncCommandCompleter->cancel(); - semanticState.closed(); - if (mgmtObject != 0) - mgmtObject->resourceDestroy (); - - if (flowControlTimer) - flowControlTimer->cancel(); -} - -AMQP_ClientProxy& SessionState::getProxy() { - assert(isAttached()); - return handler->getProxy(); -} - -uint16_t SessionState::getChannel() const { - assert(isAttached()); - return handler->getChannel(); -} - -ConnectionState& SessionState::getConnection() { - assert(isAttached()); - return handler->getConnection(); -} - -bool SessionState::isLocal(const ConnectionToken* t) const -{ - return isAttached() && &(handler->getConnection()) == t; -} - -void SessionState::detach() { - QPID_LOG(debug, getId() << ": detached on broker."); - asyncCommandCompleter->detached(); - disableOutput(); - handler = 0; - if (mgmtObject != 0) - mgmtObject->set_attached (0); -} - -void SessionState::disableOutput() -{ - semanticState.detached(); //prevents further activateOutput calls until reattached -} - -void SessionState::attach(SessionHandler& h) { - QPID_LOG(debug, getId() << ": attached on broker."); - handler = &h; - if (mgmtObject != 0) - { - mgmtObject->set_attached (1); - mgmtObject->set_connectionRef (h.getConnection().GetManagementObject()->getObjectId()); - mgmtObject->set_channelId (h.getChannel()); - } - asyncCommandCompleter->attached(); -} - -void SessionState::abort() { - if (isAttached()) - getConnection().outputTasks.abort(); -} - -void SessionState::activateOutput() { - if (isAttached()) - getConnection().outputTasks.activateOutput(); -} - -void SessionState::giveReadCredit(int32_t credit) { - if (isAttached()) - getConnection().outputTasks.giveReadCredit(credit); -} - -ManagementObject* SessionState::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t SessionState::ManagementMethod (uint32_t methodId, - Args& /*args*/, - string& /*text*/) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - switch (methodId) - { - case _qmf::Session::METHOD_DETACH : - if (handler != 0) { - handler->sendDetach(); - } - status = Manageable::STATUS_OK; - break; - - case _qmf::Session::METHOD_CLOSE : - /* - if (handler != 0) - { - handler->getConnection().closeChannel(handler->getChannel()); - } - status = Manageable::STATUS_OK; - break; - */ - - case _qmf::Session::METHOD_SOLICITACK : - case _qmf::Session::METHOD_RESETLIFESPAN : - status = Manageable::STATUS_NOT_IMPLEMENTED; - break; - } - - return status; -} - -void SessionState::handleCommand(framing::AMQMethodBody* method, const SequenceNumber& id) { - currentCommandComplete = true; // assumed, can be overridden by invoker method (this sucks). - Invoker::Result invocation = invoke(adapter, *method); - if (currentCommandComplete) receiverCompleted(id); - - if (!invocation.wasHandled()) { - throw NotImplementedException(QPID_MSG("Not implemented: " << *method)); - } else if (invocation.hasResult()) { - getProxy().getExecution().result(id, invocation.getResult()); - } - - if (method->isSync() && currentCommandComplete) { - sendAcceptAndCompletion(); - } -} - -struct ScheduledCreditTask : public sys::TimerTask { - sys::Timer& timer; - SessionState& sessionState; - ScheduledCreditTask(const qpid::sys::Duration& d, sys::Timer& t, - SessionState& s) : - TimerTask(d,"ScheduledCredit"), - timer(t), - sessionState(s) - {} - - void fire() { - // This is the best we can currently do to avoid a destruction/fire race - sessionState.getConnection().requestIOProcessing(boost::bind(&ScheduledCreditTask::sendCredit, this)); - } - - void sendCredit() { - if ( !sessionState.processSendCredit(0) ) { - QPID_LOG(warning, sessionState.getId() << ": Reschedule sending credit"); - setupNextFire(); - timer.add(this); - } - } -}; - -void SessionState::handleContent(AMQFrame& frame, const SequenceNumber& id) -{ - if (frame.getBof() && frame.getBos()) //start of frameset - msgBuilder.start(id); - intrusive_ptr<Message> msg(msgBuilder.getMessage()); - msgBuilder.handle(frame); - if (frame.getEof() && frame.getEos()) {//end of frameset - if (frame.getBof()) { - //i.e this is a just a command frame, add a dummy header - AMQFrame header((AMQHeaderBody())); - header.setBof(false); - header.setEof(false); - msg->getFrames().append(header); - } - msg->setPublisher(&getConnection()); - msg->getIngressCompletion().begin(); - semanticState.handle(msg); - msgBuilder.end(); - IncompleteIngressMsgXfer xfer(this, msg); - msg->getIngressCompletion().end(xfer); // allows msg to complete xfer - } - - // Handle producer session flow control - if (rateFlowcontrol && frame.getBof() && frame.getBos()) { - if ( !processSendCredit(1) ) { - QPID_LOG(debug, getId() << ": Schedule sending credit"); - sys::Timer& timer = getBroker().getTimer(); - // Use heuristic for scheduled credit of time for 50 messages, but not longer than 500ms - sys::Duration d = std::min(sys::TIME_SEC * 50 / rateFlowcontrol->getRate(), 500 * sys::TIME_MSEC); - flowControlTimer = new ScheduledCreditTask(d, timer, *this); - timer.add(flowControlTimer); - } - } -} - -bool SessionState::processSendCredit(uint32_t msgs) -{ - qpid::sys::ScopedLock<Mutex> l(rateLock); - // Check for violating flow control - if ( msgs > 0 && rateFlowcontrol->flowStopped() ) { - QPID_LOG(warning, getId() << ": producer throttling violation"); - // TODO: Probably do message.stop("") first time then disconnect - // See comment on getClusterOrderProxy() in .h file - getClusterOrderProxy().getMessage().stop(""); - return true; - } - AbsTime now = AbsTime::now(); - uint32_t sendCredit = rateFlowcontrol->receivedMessage(now, msgs); - if (mgmtObject) mgmtObject->dec_clientCredit(msgs); - if ( sendCredit>0 ) { - QPID_LOG(debug, getId() << ": send producer credit " << sendCredit); - getClusterOrderProxy().getMessage().flow("", 0, sendCredit); - rateFlowcontrol->sentCredit(now, sendCredit); - if (mgmtObject) mgmtObject->inc_clientCredit(sendCredit); - return true; - } else { - return !rateFlowcontrol->flowStopped() ; - } -} - -void SessionState::sendAcceptAndCompletion() -{ - if (!accepted.empty()) { - getProxy().getMessage().accept(accepted); - accepted.clear(); - } - sendCompletion(); -} - -/** Invoked when the given inbound message is finished being processed - * by all interested parties (eg. it is done being enqueued to all queues, - * its credit has been accounted for, etc). At this point, msg is considered - * by this receiver as 'completed' (as defined by AMQP 0_10) - */ -void SessionState::completeRcvMsg(SequenceNumber id, - bool requiresAccept, - bool requiresSync) -{ - bool callSendCompletion = false; - receiverCompleted(id); - if (requiresAccept) - // will cause msg's seq to appear in the next message.accept we send. - accepted.add(id); - - // Are there any outstanding Execution.Sync commands pending the - // completion of this msg? If so, complete them. - while (!pendingExecutionSyncs.empty() && - receiverGetIncomplete().front() >= pendingExecutionSyncs.front()) { - const SequenceNumber id = pendingExecutionSyncs.front(); - pendingExecutionSyncs.pop(); - QPID_LOG(debug, getId() << ": delayed execution.sync " << id << " is completed."); - receiverCompleted(id); - callSendCompletion = true; // likely peer is pending for this completion. - } - - // if the sender has requested immediate notification of the completion... - if (requiresSync) { - sendAcceptAndCompletion(); - } else if (callSendCompletion) { - sendCompletion(); - } -} - -void SessionState::handleIn(AMQFrame& frame) { - SequenceNumber commandId = receiverGetCurrent(); - //TODO: make command handling more uniform, regardless of whether - //commands carry content. - AMQMethodBody* m = frame.getMethod(); - if (m == 0 || m->isContentBearing()) { - handleContent(frame, commandId); - } else if (frame.getBof() && frame.getEof()) { - handleCommand(frame.getMethod(), commandId); - } else { - throw InternalErrorException("Cannot handle multi-frame command segments yet"); - } -} - -void SessionState::handleOut(AMQFrame& frame) { - assert(handler); - handler->out(frame); -} - -void SessionState::deliver(DeliveryRecord& msg, bool sync) -{ - uint32_t maxFrameSize = getConnection().getFrameMax(); - assert(senderGetCommandPoint().offset == 0); - SequenceNumber commandId = senderGetCommandPoint().command; - msg.deliver(getProxy().getHandler(), commandId, maxFrameSize); - assert(senderGetCommandPoint() == SessionPoint(commandId+1, 0)); // Delivery has moved sendPoint. - if (sync) { - AMQP_ClientProxy::Execution& p(getProxy().getExecution()); - Proxy::ScopedSync s(p); - p.sync(); - } -} - -void SessionState::sendCompletion() { - handler->sendCompletion(); -} - -void SessionState::senderCompleted(const SequenceSet& commands) { - qpid::SessionState::senderCompleted(commands); - semanticState.completed(commands); -} - -void SessionState::readyToSend() { - QPID_LOG(debug, getId() << ": ready to send, activating output."); - assert(handler); - semanticState.attached(); - if (rateFlowcontrol) { - qpid::sys::ScopedLock<Mutex> l(rateLock); - // Issue initial credit - use a heuristic here issue min of 300 messages or 1 secs worth - uint32_t credit = std::min(rateFlowcontrol->getRate(), 300U); - QPID_LOG(debug, getId() << ": Issuing producer message credit " << credit); - // See comment on getClusterOrderProxy() in .h file - getClusterOrderProxy().getMessage().setFlowMode("", 0); - getClusterOrderProxy().getMessage().flow("", 0, credit); - rateFlowcontrol->sentCredit(AbsTime::now(), credit); - if (mgmtObject) mgmtObject->inc_clientCredit(credit); - } -} - -Broker& SessionState::getBroker() { return broker; } - -// Session resume is not fully implemented so it is useless to set a -// non-0 timeout. Moreover it creates problems in a cluster because -// dead sessions are kept and interfere with failover. -void SessionState::setTimeout(uint32_t) { } - -framing::AMQP_ClientProxy& SessionState::getClusterOrderProxy() { - return handler->getClusterOrderProxy(); -} - - -// Current received command is an execution.sync command. -// Complete this command only when all preceding commands have completed. -// (called via the invoker() in handleCommand() above) -void SessionState::addPendingExecutionSync() -{ - SequenceNumber syncCommandId = receiverGetCurrent(); - if (receiverGetIncomplete().front() < syncCommandId) { - currentCommandComplete = false; - pendingExecutionSyncs.push(syncCommandId); - asyncCommandCompleter->flushPendingMessages(); - QPID_LOG(debug, getId() << ": delaying completion of execution.sync " << syncCommandId); - } -} - - -/** factory for creating a reference-counted IncompleteIngressMsgXfer object - * which will be attached to a message that will be completed asynchronously. - */ -boost::intrusive_ptr<AsyncCompletion::Callback> -SessionState::IncompleteIngressMsgXfer::clone() -{ - boost::intrusive_ptr<SessionState::IncompleteIngressMsgXfer> cb(new SessionState::IncompleteIngressMsgXfer(session, msg)); - - // Optimization: this routine is *only* invoked when the message needs to be asynchronously completed. - // If the client is pending the message.transfer completion, flush now to force immediate write to journal. - if (requiresSync) - msg->flush(); - else { - // otherwise, we need to track this message in order to flush it if an execution.sync arrives - // before it has been completed (see flushPendingMessages()) - pending = true; - completerContext->addPendingMessage(msg); - } - return cb; -} - - -/** Invoked by the asynchronous completer associated with a received - * msg that is pending Completion. May be invoked by the IO thread - * (sync == true), or some external thread (!sync). - */ -void SessionState::IncompleteIngressMsgXfer::completed(bool sync) -{ - if (pending) completerContext->deletePendingMessage(id); - if (!sync) { - /** note well: this path may execute in any thread. It is safe to access - * the scheduledCompleterContext, since *this has a shared pointer to it. - * but not session! - */ - session = 0; - QPID_LOG(debug, ": async completion callback scheduled for msg seq=" << id); - completerContext->scheduleMsgCompletion(id, requiresAccept, requiresSync); - } else { - // this path runs directly from the ac->end() call in handleContent() above, - // so *session is definately valid. - if (session->isAttached()) { - QPID_LOG(debug, ": receive completed for msg seq=" << id); - session->completeRcvMsg(id, requiresAccept, requiresSync); - } - } - completerContext = boost::intrusive_ptr<AsyncCommandCompleter>(); -} - - -/** Scheduled from an asynchronous command's completed callback to run on - * the IO thread. - */ -void SessionState::AsyncCommandCompleter::schedule(boost::intrusive_ptr<AsyncCommandCompleter> ctxt) -{ - ctxt->completeCommands(); -} - - -/** Track an ingress message that is pending completion */ -void SessionState::AsyncCommandCompleter::addPendingMessage(boost::intrusive_ptr<Message> msg) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - std::pair<SequenceNumber, boost::intrusive_ptr<Message> > item(msg->getCommandId(), msg); - bool unique = pendingMsgs.insert(item).second; - assert(unique); -} - - -/** pending message has completed */ -void SessionState::AsyncCommandCompleter::deletePendingMessage(SequenceNumber id) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - pendingMsgs.erase(id); -} - - -/** done when an execution.sync arrives */ -void SessionState::AsyncCommandCompleter::flushPendingMessages() -{ - std::map<SequenceNumber, boost::intrusive_ptr<Message> > copy; - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - pendingMsgs.swap(copy); // we've only tracked these in case a flush is needed, so nuke 'em now. - } - // drop lock, so it is safe to call "flush()" - for (std::map<SequenceNumber, boost::intrusive_ptr<Message> >::iterator i = copy.begin(); - i != copy.end(); ++i) { - i->second->flush(); - } -} - - -/** mark an ingress Message.Transfer command as completed. - * This method must be thread safe - it may run on any thread. - */ -void SessionState::AsyncCommandCompleter::scheduleMsgCompletion(SequenceNumber cmd, - bool requiresAccept, - bool requiresSync) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - - if (session && isAttached) { - MessageInfo msg(cmd, requiresAccept, requiresSync); - completedMsgs.push_back(msg); - if (completedMsgs.size() == 1) { - session->getConnection().requestIOProcessing(boost::bind(&schedule, - session->asyncCommandCompleter)); - } - } -} - - -/** Cause the session to complete all completed commands. - * Executes on the IO thread. - */ -void SessionState::AsyncCommandCompleter::completeCommands() -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - - // when session is destroyed, it clears the session pointer via cancel(). - if (session && session->isAttached()) { - for (std::vector<MessageInfo>::iterator msg = completedMsgs.begin(); - msg != completedMsgs.end(); ++msg) { - session->completeRcvMsg(msg->cmd, msg->requiresAccept, msg->requiresSync); - } - } - completedMsgs.clear(); -} - - -/** cancel any pending calls to scheduleComplete */ -void SessionState::AsyncCommandCompleter::cancel() -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - session = 0; -} - - -/** inform the completer that the session has attached, - * allows command completion scheduling from any thread */ -void SessionState::AsyncCommandCompleter::attached() -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - isAttached = true; -} - - -/** inform the completer that the session has detached, - * disables command completion scheduling from any thread */ -void SessionState::AsyncCommandCompleter::detached() -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - isAttached = false; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SessionState.h b/cpp/src/qpid/broker/SessionState.h deleted file mode 100644 index b43df0c0aa..0000000000 --- a/cpp/src/qpid/broker/SessionState.h +++ /dev/null @@ -1,284 +0,0 @@ -#ifndef QPID_BROKER_SESSION_H -#define QPID_BROKER_SESSION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/SessionState.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/Time.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Session.h" -#include "qpid/broker/SessionAdapter.h" -#include "qpid/broker/DeliveryAdapter.h" -#include "qpid/broker/AsyncCompletion.h" -#include "qpid/broker/MessageBuilder.h" -#include "qpid/broker/SessionContext.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/sys/Monitor.h" - -#include <boost/noncopyable.hpp> -#include <boost/scoped_ptr.hpp> -#include <boost/intrusive_ptr.hpp> - -#include <set> -#include <vector> -#include <ostream> - -namespace qpid { - -namespace framing { -class AMQP_ClientProxy; -} - -namespace sys { -class TimerTask; -} - -namespace broker { - -class Broker; -class ConnectionState; -class Message; -class SessionHandler; -class SessionManager; -class RateFlowcontrol; - -/** - * Broker-side session state includes session's handler chains, which - * may themselves have state. - */ -class SessionState : public qpid::SessionState, - public SessionContext, - public DeliveryAdapter, - public management::Manageable, - public framing::FrameHandler::InOutHandler -{ - public: - SessionState(Broker&, SessionHandler&, const SessionId&, - const SessionState::Configuration&, bool delayManagement=false); - ~SessionState(); - bool isAttached() const { return handler; } - - void detach(); - void attach(SessionHandler& handler); - void disableOutput(); - - /** @pre isAttached() */ - framing::AMQP_ClientProxy& getProxy(); - - /** @pre isAttached() */ - uint16_t getChannel() const; - - /** @pre isAttached() */ - ConnectionState& getConnection(); - bool isLocal(const ConnectionToken* t) const; - - Broker& getBroker(); - - void setTimeout(uint32_t seconds); - - /** OutputControl **/ - void abort(); - void activateOutput(); - void giveReadCredit(int32_t); - - void senderCompleted(const framing::SequenceSet& ranges); - - void sendCompletion(); - - //delivery adapter methods: - void deliver(DeliveryRecord&, bool sync); - - // Manageable entry points - management::ManagementObject* GetManagementObject (void) const; - management::Manageable::status_t - ManagementMethod (uint32_t methodId, management::Args& args, std::string&); - - void readyToSend(); - - // Used by cluster to create replica sessions. - SemanticState& getSemanticState() { return semanticState; } - boost::intrusive_ptr<Message> getMessageInProgress() { return msgBuilder.getMessage(); } - SessionAdapter& getSessionAdapter() { return adapter; } - - bool processSendCredit(uint32_t msgs); - - const SessionId& getSessionId() const { return getId(); } - - // Used by ExecutionHandler sync command processing. Notifies - // the SessionState of a received Execution.Sync command. - void addPendingExecutionSync(); - - // Used to delay creation of management object for sessions - // belonging to inter-broker bridges - void addManagementObject(); - - private: - void handleCommand(framing::AMQMethodBody* method, const framing::SequenceNumber& id); - void handleContent(framing::AMQFrame& frame, const framing::SequenceNumber& id); - - // indicate that the given ingress msg has been completely received by the - // broker, and the msg's message.transfer command can be considered completed. - void completeRcvMsg(SequenceNumber id, bool requiresAccept, bool requiresSync); - - void handleIn(framing::AMQFrame& frame); - void handleOut(framing::AMQFrame& frame); - - // End of the input & output chains. - void handleInLast(framing::AMQFrame& frame); - void handleOutLast(framing::AMQFrame& frame); - - void sendAcceptAndCompletion(); - - /** - * If commands are sent based on the local time (e.g. in timers), they don't have - * a well-defined ordering across cluster nodes. - * This proxy is for sending such commands. In a clustered broker it will take steps - * to synchronize command order across the cluster. In a stand-alone broker - * it is just a synonym for getProxy() - */ - framing::AMQP_ClientProxy& getClusterOrderProxy(); - - Broker& broker; - SessionHandler* handler; - sys::AbsTime expiry; // Used by SessionManager. - SemanticState semanticState; - SessionAdapter adapter; - MessageBuilder msgBuilder; - qmf::org::apache::qpid::broker::Session* mgmtObject; - qpid::framing::SequenceSet accepted; - - // State used for producer flow control (rate limited) - qpid::sys::Mutex rateLock; - boost::scoped_ptr<RateFlowcontrol> rateFlowcontrol; - boost::intrusive_ptr<sys::TimerTask> flowControlTimer; - - // sequence numbers for pending received Execution.Sync commands - std::queue<SequenceNumber> pendingExecutionSyncs; - bool currentCommandComplete; - - /** This class provides a context for completing asynchronous commands in a thread - * safe manner. Asynchronous commands save their completion state in this class. - * This class then schedules the completeCommands() method in the IO thread. - * While running in the IO thread, completeCommands() may safely complete all - * saved commands without the risk of colliding with other operations on this - * SessionState. - */ - class AsyncCommandCompleter : public RefCounted { - private: - SessionState *session; - bool isAttached; - qpid::sys::Mutex completerLock; - - // special-case message.transfer commands for optimization - struct MessageInfo { - SequenceNumber cmd; // message.transfer command id - bool requiresAccept; - bool requiresSync; - MessageInfo(SequenceNumber c, bool a, bool s) - : cmd(c), requiresAccept(a), requiresSync(s) {} - }; - std::vector<MessageInfo> completedMsgs; - // If an ingress message does not require a Sync, we need to - // hold a reference to it in case an Execution.Sync command is received and we - // have to manually flush the message. - std::map<SequenceNumber, boost::intrusive_ptr<Message> > pendingMsgs; - - /** complete all pending commands, runs in IO thread */ - void completeCommands(); - - /** for scheduling a run of "completeCommands()" on the IO thread */ - static void schedule(boost::intrusive_ptr<AsyncCommandCompleter>); - - public: - AsyncCommandCompleter(SessionState *s) : session(s), isAttached(s->isAttached()) {}; - ~AsyncCommandCompleter() {}; - - /** track a message pending ingress completion */ - void addPendingMessage(boost::intrusive_ptr<Message> m); - void deletePendingMessage(SequenceNumber id); - void flushPendingMessages(); - /** schedule the processing of a completed ingress message.transfer command */ - void scheduleMsgCompletion(SequenceNumber cmd, - bool requiresAccept, - bool requiresSync); - void cancel(); // called by SessionState destructor. - void attached(); // called by SessionState on attach() - void detached(); // called by SessionState on detach() - }; - boost::intrusive_ptr<AsyncCommandCompleter> asyncCommandCompleter; - - /** Abstract class that represents a single asynchronous command that is - * pending completion. - */ - class AsyncCommandContext : public AsyncCompletion::Callback - { - public: - AsyncCommandContext( SessionState *ss, SequenceNumber _id ) - : id(_id), completerContext(ss->asyncCommandCompleter) {} - virtual ~AsyncCommandContext() {} - - protected: - SequenceNumber id; - boost::intrusive_ptr<AsyncCommandCompleter> completerContext; - }; - - /** incomplete Message.transfer commands - inbound to broker from client - */ - class IncompleteIngressMsgXfer : public SessionState::AsyncCommandContext - { - public: - IncompleteIngressMsgXfer( SessionState *ss, - boost::intrusive_ptr<Message> m ) - : AsyncCommandContext(ss, m->getCommandId()), - session(ss), - msg(m), - requiresAccept(m->requiresAccept()), - requiresSync(m->getFrames().getMethod()->isSync()), - pending(false) {} - virtual ~IncompleteIngressMsgXfer() {}; - - virtual void completed(bool); - virtual boost::intrusive_ptr<AsyncCompletion::Callback> clone(); - - private: - SessionState *session; // only valid if sync flag in callback is true - boost::intrusive_ptr<Message> msg; - bool requiresAccept; - bool requiresSync; - bool pending; // true if msg saved on pending list... - }; - - friend class SessionManager; -}; - - -inline std::ostream& operator<<(std::ostream& out, const SessionState& session) { - return out << session.getId(); -} - -}} // namespace qpid::broker - - - -#endif /*!QPID_BROKER_SESSION_H*/ diff --git a/cpp/src/qpid/broker/SignalHandler.cpp b/cpp/src/qpid/broker/SignalHandler.cpp deleted file mode 100644 index 16c141f21c..0000000000 --- a/cpp/src/qpid/broker/SignalHandler.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/SignalHandler.h" -#include "qpid/broker/Broker.h" -#include "qpid/sys/Mutex.h" -#include <signal.h> - -namespace qpid { -namespace broker { - -// Lock is to ensure that broker is not concurrently set to 0 and -// deleted while we are in a call to broker->shutdown() - -sys::Mutex brokerLock; -Broker* SignalHandler::broker; - -void SignalHandler::setBroker(Broker* b) { - sys::Mutex::ScopedLock l(brokerLock); - broker = b; - signal(SIGINT,shutdownHandler); - signal(SIGTERM, shutdownHandler); - signal(SIGHUP,SIG_IGN); - signal(SIGCHLD,SIG_IGN); -} - -void SignalHandler::shutdown() { shutdownHandler(0); } - -void SignalHandler::shutdownHandler(int) { - sys::Mutex::ScopedLock l(brokerLock); - if (broker) { - broker->shutdown(); - broker = 0; - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SignalHandler.h b/cpp/src/qpid/broker/SignalHandler.h deleted file mode 100644 index 7bfa9ea630..0000000000 --- a/cpp/src/qpid/broker/SignalHandler.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_BROKER_SIGNALHANDLER_H -#define QPID_BROKER_SIGNALHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -namespace qpid { -namespace broker { - -class Broker; - -/** - * Handle signals e.g. to shut-down a broker. - */ -class SignalHandler -{ - public: - /** Set the broker to be shutdown on signals. - * Must be reset by calling setBroker(0) before the broker is deleted. - */ - static void setBroker(Broker* broker); - - /** Initiate shut-down of broker */ - static void shutdown(); - - private: - static void shutdownHandler(int); - static Broker* broker; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SIGNALHANDLER_H*/ diff --git a/cpp/src/qpid/broker/StatefulQueueObserver.h b/cpp/src/qpid/broker/StatefulQueueObserver.h deleted file mode 100644 index c682d460b7..0000000000 --- a/cpp/src/qpid/broker/StatefulQueueObserver.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef QPID_BROKER_STATEFULQUEUEOBSERVER_H -#define QPID_BROKER_STATEFULQUEUEOBSERVER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueObserver.h" -#include "qpid/framing/FieldTable.h" - -namespace qpid { -namespace broker { - -/** - * Specialized type of QueueObserver that maintains internal state that has to - * be replicated across clustered brokers. - */ -class StatefulQueueObserver : public QueueObserver -{ - public: - StatefulQueueObserver(std::string _id) : id(_id) {} - virtual ~StatefulQueueObserver() {} - - /** This identifier must uniquely identify this particular observer amoung - * all observers on a queue. For cluster replication, this id will be used - * to identify the peer queue observer for synchronization across - * brokers. - */ - const std::string& getId() const { return id; } - - /** This method should return the observer's internal state as an opaque - * map. - */ - virtual void getState(qpid::framing::FieldTable& state ) const = 0; - - /** The input map represents the internal state of the peer observer that - * this observer should synchonize to. - */ - virtual void setState(const qpid::framing::FieldTable&) = 0; - - - private: - std::string id; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_STATEFULQUEUEOBSERVER_H*/ diff --git a/cpp/src/qpid/broker/System.cpp b/cpp/src/qpid/broker/System.cpp deleted file mode 100644 index 8cd2edda76..0000000000 --- a/cpp/src/qpid/broker/System.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/broker/System.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/types/Uuid.h" -#include <iostream> -#include <fstream> - -using qpid::management::ManagementAgent; -using namespace qpid::broker; -using namespace std; -namespace _qmf = qmf::org::apache::qpid::broker; - -System::System (string _dataDir, Broker* broker) : mgmtObject(0) -{ - ManagementAgent* agent = broker ? broker->getManagementAgent() : 0; - - if (agent != 0) - { - framing::Uuid systemId; - - if (_dataDir.empty ()) - { - systemId.generate (); - } - else - { - string filename (_dataDir + "/systemId"); - ifstream inFile (filename.c_str ()); - - if (inFile.good ()) - { - inFile >> systemId; - inFile.close (); - } - else - { - systemId.generate (); - ofstream outFile (filename.c_str ()); - if (outFile.good ()) - { - outFile << systemId << endl; - outFile.close (); - } - } - } - - mgmtObject = new _qmf::System(agent, this, types::Uuid(systemId.c_array())); - std::string sysname, nodename, release, version, machine; - qpid::sys::SystemInfo::getSystemId (sysname, - nodename, - release, - version, - machine); - mgmtObject->set_osName (sysname); - mgmtObject->set_nodeName (nodename); - mgmtObject->set_release (release); - mgmtObject->set_version (version); - mgmtObject->set_machine (machine); - - agent->addObject(mgmtObject, 0, true); - } -} - diff --git a/cpp/src/qpid/broker/System.h b/cpp/src/qpid/broker/System.h deleted file mode 100644 index 0fc2c2bd88..0000000000 --- a/cpp/src/qpid/broker/System.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _BrokerSystem_ -#define _BrokerSystem_ - -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/System.h" -#include <boost/shared_ptr.hpp> -#include <string> - -namespace qpid { -namespace broker { - -class Broker; - -class System : public management::Manageable -{ - private: - - qmf::org::apache::qpid::broker::System* mgmtObject; - - public: - - typedef boost::shared_ptr<System> shared_ptr; - - System (std::string _dataDir, Broker* broker = 0); - - management::ManagementObject* GetManagementObject (void) const - { return mgmtObject; } -}; - -}} - -#endif /*!_BrokerSystem_*/ diff --git a/cpp/src/qpid/broker/ThresholdAlerts.cpp b/cpp/src/qpid/broker/ThresholdAlerts.cpp deleted file mode 100644 index 3c9e210d4d..0000000000 --- a/cpp/src/qpid/broker/ThresholdAlerts.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/ThresholdAlerts.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/broker/EventQueueThresholdExceeded.h" - -namespace qpid { -namespace broker { -namespace { -const qmf::org::apache::qpid::broker::EventQueueThresholdExceeded EVENT("dummy", 0, 0); -bool isQMFv2(const boost::intrusive_ptr<Message> message) -{ - const qpid::framing::MessageProperties* props = message->getProperties<qpid::framing::MessageProperties>(); - return props && props->getAppId() == "qmf2"; -} - -bool isThresholdEvent(const boost::intrusive_ptr<Message> message) -{ - if (message->getIsManagementMessage()) { - //is this a qmf event? if so is it a threshold event? - if (isQMFv2(message)) { - const qpid::framing::FieldTable* headers = message->getApplicationHeaders(); - if (headers && headers->getAsString("qmf.content") == "_event") { - //decode as list - std::string content = message->getFrames().getContent(); - qpid::types::Variant::List list; - qpid::amqp_0_10::ListCodec::decode(content, list); - if (list.empty() || list.front().getType() != qpid::types::VAR_MAP) return false; - qpid::types::Variant::Map map = list.front().asMap(); - try { - std::string eventName = map["_schema_id"].asMap()["_class_name"].asString(); - return eventName == EVENT.getEventName(); - } catch (const std::exception& e) { - QPID_LOG(error, "Error checking for recursive threshold alert: " << e.what()); - } - } - } else { - std::string content = message->getFrames().getContent(); - qpid::framing::Buffer buffer(const_cast<char*>(content.data()), content.size()); - if (buffer.getOctet() == 'A' && buffer.getOctet() == 'M' && buffer.getOctet() == '2' && buffer.getOctet() == 'e') { - buffer.getLong();//sequence - std::string packageName; - buffer.getShortString(packageName); - if (packageName != EVENT.getPackageName()) return false; - std::string eventName; - buffer.getShortString(eventName); - return eventName == EVENT.getEventName(); - } - } - } - return false; -} -} - -ThresholdAlerts::ThresholdAlerts(const std::string& n, - qpid::management::ManagementAgent& a, - const uint32_t ct, - const uint64_t st, - const long repeat) - : name(n), agent(a), countThreshold(ct), sizeThreshold(st), - repeatInterval(repeat ? repeat*qpid::sys::TIME_SEC : 0), - count(0), size(0), lastAlert(qpid::sys::EPOCH) {} - -void ThresholdAlerts::enqueued(const QueuedMessage& m) -{ - size += m.payload->contentSize(); - ++count; - if ((countThreshold && count >= countThreshold) || (sizeThreshold && size >= sizeThreshold)) { - if ((repeatInterval == 0 && lastAlert == qpid::sys::EPOCH) - || qpid::sys::Duration(lastAlert, qpid::sys::now()) > repeatInterval) { - //Note: Raising an event may result in messages being - //enqueued on queues; it may even be that this event - //causes a message to be enqueued on the queue we are - //tracking, and so we need to avoid recursing - if (isThresholdEvent(m.payload)) return; - lastAlert = qpid::sys::now(); - agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdExceeded(name, count, size)); - QPID_LOG(info, "Threshold event triggered for " << name << ", count=" << count << ", size=" << size); - } - } -} - -void ThresholdAlerts::dequeued(const QueuedMessage& m) -{ - size -= m.payload->contentSize(); - --count; - if ((countThreshold && count < countThreshold) || (sizeThreshold && size < sizeThreshold)) { - lastAlert = qpid::sys::EPOCH; - } -} - - - -void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent, - const uint64_t countThreshold, - const uint64_t sizeThreshold, - const long repeatInterval) -{ - if (countThreshold || sizeThreshold) { - boost::shared_ptr<QueueObserver> observer( - new ThresholdAlerts(queue.getName(), agent, countThreshold, sizeThreshold, repeatInterval) - ); - queue.addObserver(observer); - } -} - -void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent, - const qpid::framing::FieldTable& settings, uint16_t limitRatio) - -{ - qpid::types::Variant::Map map; - qpid::amqp_0_10::translate(settings, map); - observe(queue, agent, map, limitRatio); -} - -template <class T> -class Option -{ - public: - Option(const std::string& name, T d) : defaultValue(d) { names.push_back(name); } - void addAlias(const std::string& name) { names.push_back(name); } - T get(const qpid::types::Variant::Map& settings) const - { - T value(defaultValue); - for (std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) { - if (get(settings, *i, value)) break; - } - return value; - } - private: - std::vector<std::string> names; - T defaultValue; - - bool get(const qpid::types::Variant::Map& settings, const std::string& name, T& value) const - { - qpid::types::Variant::Map::const_iterator i = settings.find(name); - if (i != settings.end()) { - try { - value = (T) i->second; - } catch (const qpid::types::InvalidConversion&) { - QPID_LOG(warning, "Bad value for" << name << ": " << i->second); - } - return true; - } else { - return false; - } - } -}; - -void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent, - const qpid::types::Variant::Map& settings, uint16_t limitRatio) - -{ - //Note: aliases are keys defined by java broker - Option<int64_t> repeatInterval("qpid.alert_repeat_gap", 60); - repeatInterval.addAlias("x-qpid-minimum-alert-repeat-gap"); - - //If no explicit threshold settings were given use specified - //percentage of any limit from the policy. - const QueuePolicy* policy = queue.getPolicy(); - Option<uint32_t> countThreshold("qpid.alert_count", (uint32_t) (policy && limitRatio ? (policy->getMaxCount()*limitRatio/100) : 0)); - countThreshold.addAlias("x-qpid-maximum-message-count"); - Option<uint64_t> sizeThreshold("qpid.alert_size", (uint64_t) (policy && limitRatio ? (policy->getMaxSize()*limitRatio/100) : 0)); - sizeThreshold.addAlias("x-qpid-maximum-message-size"); - - observe(queue, agent, countThreshold.get(settings), sizeThreshold.get(settings), repeatInterval.get(settings)); -} - -}} diff --git a/cpp/src/qpid/broker/ThresholdAlerts.h b/cpp/src/qpid/broker/ThresholdAlerts.h deleted file mode 100644 index c77722e700..0000000000 --- a/cpp/src/qpid/broker/ThresholdAlerts.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef QPID_BROKER_THRESHOLDALERTS_H -#define QPID_BROKER_THRESHOLDALERTS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueObserver.h" -#include "qpid/sys/Time.h" -#include "qpid/types/Variant.h" -#include <string> - -namespace qpid { -namespace framing { -class FieldTable; -} -namespace management { -class ManagementAgent; -} -namespace broker { - -class Queue; -/** - * Class to manage generation of QMF alerts when particular thresholds - * are breached on a queue. - */ -class ThresholdAlerts : public QueueObserver -{ - public: - ThresholdAlerts(const std::string& name, - qpid::management::ManagementAgent& agent, - const uint32_t countThreshold, - const uint64_t sizeThreshold, - const long repeatInterval); - void enqueued(const QueuedMessage&); - void dequeued(const QueuedMessage&); - static void observe(Queue& queue, qpid::management::ManagementAgent& agent, - const uint64_t countThreshold, - const uint64_t sizeThreshold, - const long repeatInterval); - static void observe(Queue& queue, qpid::management::ManagementAgent& agent, - const qpid::framing::FieldTable& settings, uint16_t limitRatio); - static void observe(Queue& queue, qpid::management::ManagementAgent& agent, - const qpid::types::Variant::Map& settings, uint16_t limitRatio); - private: - const std::string name; - qpid::management::ManagementAgent& agent; - const uint32_t countThreshold; - const uint64_t sizeThreshold; - const qpid::sys::Duration repeatInterval; - uint64_t count; - uint64_t size; - qpid::sys::AbsTime lastAlert; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_THRESHOLDALERTS_H*/ diff --git a/cpp/src/qpid/broker/TopicExchange.cpp b/cpp/src/qpid/broker/TopicExchange.cpp deleted file mode 100644 index 644a3d628e..0000000000 --- a/cpp/src/qpid/broker/TopicExchange.cpp +++ /dev/null @@ -1,692 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/TopicExchange.h" -#include "qpid/broker/FedOps.h" -#include "qpid/log/Statement.h" -#include <algorithm> - - -namespace qpid { -namespace broker { - -using namespace qpid::framing; -using namespace qpid::sys; -using namespace std; -namespace _qmf = qmf::org::apache::qpid::broker; - - -// TODO aconway 2006-09-20: More efficient matching algorithm. -// Areas for improvement: -// - excessive string copying: should be 0 copy, match from original buffer. -// - match/lookup: use descision tree or other more efficient structure. - -namespace -{ -const std::string STAR("*"); -const std::string HASH("#"); -} - -// iterator for federation ReOrigin bind operation -class TopicExchange::ReOriginIter : public TopicExchange::BindingNode::TreeIterator { -public: - ReOriginIter() {}; - ~ReOriginIter() {}; - bool visit(BindingNode& node) { - if (node.bindings.fedBinding.hasLocal()) { - keys2prop.push_back(node.routePattern); - } - return true; - } - std::vector<std::string> keys2prop; -}; - - -// match iterator used by route(): builds BindingList of all unique queues -// that match the routing key. -class TopicExchange::BindingsFinderIter : public TopicExchange::BindingNode::TreeIterator { -public: - BindingsFinderIter(BindingList &bl) : b(bl) {}; - ~BindingsFinderIter() {}; - - BindingList& b; - std::set<std::string> qSet; - - bool visit(BindingNode& node) { - - Binding::vector& qv(node.bindings.bindingVector); - for (Binding::vector::iterator j = qv.begin(); j != qv.end(); j++) { - // do not duplicate queues on the binding list - if (qSet.insert(j->get()->queue->getName()).second) { - b->push_back(*j); - } - } - return true; - } -}; - - - -// Iterator to visit all bindings until a given queue is found -class TopicExchange::QueueFinderIter : public TopicExchange::BindingNode::TreeIterator { -public: - QueueFinderIter(Queue::shared_ptr queue) : queue(queue), found(false) {}; - ~QueueFinderIter() {}; - bool visit(BindingNode& node) { - - Binding::vector& qv(node.bindings.bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) { - if ((*q)->queue == queue) { - found = true; - return false; // search done - } - } - return true; // continue search - } - - Queue::shared_ptr queue; - bool found; -}; - - -// Iterate over a string of '.'-separated tokens. -struct TopicExchange::TokenIterator { - typedef pair<const char*,const char*> Token; - - TokenIterator(const char* b, const char* e) : end(e), token(make_pair(b, find(b,e,'.'))) {} - - TokenIterator(const string& key) : end(&key[0]+key.size()), token(make_pair(&key[0], find(&key[0],end,'.'))) {} - - bool finished() const { return !token.first; } - - void next() { - if (token.second == end) - token.first = token.second = 0; - else { - token.first=token.second+1; - token.second=(find(token.first, end, '.')); - } - } - - void pop(string &top) { - ptrdiff_t l = len(); - if (l) { - top.assign(token.first, l); - } else top.clear(); - next(); - } - - bool match1(char c) const { - return token.second==token.first+1 && *token.first == c; - } - - bool match(const Token& token2) const { - ptrdiff_t l=len(); - return l == token2.second-token2.first && - strncmp(token.first, token2.first, l) == 0; - } - - bool match(const string& str) const { - ptrdiff_t l=len(); - return l == ptrdiff_t(str.size()) && - str.compare(0, l, token.first, l) == 0; - } - - ptrdiff_t len() const { return token.second - token.first; } - - - const char* end; - Token token; -}; - - -class TopicExchange::Normalizer : public TopicExchange::TokenIterator { - public: - Normalizer(string& p) - : TokenIterator(&p[0], &p[0]+p.size()), pattern(p) - { normalize(); } - - private: - // Apply 2 transformations: #.* -> *.# and #.# -> # - void normalize() { - while (!finished()) { - if (match1('#')) { - const char* hash1=token.first; - next(); - if (!finished()) { - if (match1('#')) { // Erase #.# -> # - pattern.erase(hash1-pattern.data(), 2); - token.first -= 2; - token.second -= 2; - end -= 2; - } - else if (match1('*')) { // Swap #.* -> *.# - swap(*const_cast<char*>(hash1), - *const_cast<char*>(token.first)); - } - } - } - else - next(); - } - } - - string& pattern; -}; - - - -// Convert sequences of * and # to a sequence of * followed by a single # -string TopicExchange::normalize(const string& pattern) { - string normal(pattern); - Normalizer n(normal); - return normal; -} - - -TopicExchange::TopicExchange(const string& _name, Manageable* _parent, Broker* b) - : Exchange(_name, _parent, b), - nBindings(0) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -TopicExchange::TopicExchange(const std::string& _name, bool _durable, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, _args, _parent, b), - nBindings(0) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args) -{ - ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit. - string fedOp(args ? args->getAsString(qpidFedOp) : fedOpBind); - string fedTags(args ? args->getAsString(qpidFedTags) : ""); - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - string routingPattern = normalize(routingKey); - - if (args == 0 || fedOp.empty() || fedOp == fedOpBind) { - RWlock::ScopedWlock l(lock); - BindingKey *bk = bindingTree.addBindingKey(routingPattern); - if (bk) { - Binding::vector& qv(bk->bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) { - if ((*q)->queue == queue) { - // already bound, but may be from a different fedOrigin - bk->fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } - - Binding::shared_ptr binding (new Binding (routingPattern, queue, this, FieldTable(), fedOrigin)); - binding->startManagement(); - bk->bindingVector.push_back(binding); - nBindings++; - propagate = bk->fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - QPID_LOG(debug, "Binding key [" << routingPattern << "] to queue " << queue->getName() - << " on exchange " << getName() << " (origin=" << fedOrigin << ")"); - } - } else if (fedOp == fedOpUnbind) { - RWlock::ScopedWlock l(lock); - BindingKey* bk = getQueueBinding(queue, routingPattern); - if (bk) { - QPID_LOG(debug, "FedOpUnbind [" << routingPattern << "] from exchange " << getName() - << " on queue=" << queue->getName() << " origin=" << fedOrigin); - propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin); - // if this was the last binding for the queue, delete the binding - if (bk->fedBinding.countFedBindings(queue->getName()) == 0) { - deleteBinding(queue, routingPattern, bk); - } - } - } else if (fedOp == fedOpReorigin) { - /** gather up all the keys that need rebinding in a local vector - * while holding the lock. Then propagate once the lock is - * released - */ - ReOriginIter reOriginIter; - { - RWlock::ScopedRlock l(lock); - bindingTree.iterateAll( reOriginIter ); - } /* lock dropped */ - - for (std::vector<std::string>::const_iterator key = reOriginIter.keys2prop.begin(); - key != reOriginIter.keys2prop.end(); key++) { - propagateFedOp( *key, string(), fedOpBind, string()); - } - } - - cc.clearCache(); // clear the cache before we IVE route. - routeIVE(); - if (propagate) - propagateFedOp(routingKey, fedTags, fedOp, fedOrigin); - return true; -} - -bool TopicExchange::unbind(Queue::shared_ptr queue, const string& constRoutingKey, const FieldTable* args) -{ - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - QPID_LOG(debug, "Unbinding key [" << constRoutingKey << "] from queue " << queue->getName() - << " on exchange " << getName() << " origin=" << fedOrigin << ")" ); - - ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit. - RWlock::ScopedWlock l(lock); - string routingKey = normalize(constRoutingKey); - BindingKey* bk = getQueueBinding(queue, routingKey); - if (!bk) return false; - bool propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin); - deleteBinding(queue, routingKey, bk); - if (propagate) - propagateFedOp(routingKey, string(), fedOpUnbind, string()); - return true; -} - - -bool TopicExchange::deleteBinding(Queue::shared_ptr queue, - const std::string& routingKey, - BindingKey *bk) -{ - // Note well: write lock held by caller - Binding::vector& qv(bk->bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) - if ((*q)->queue == queue) - break; - if(q == qv.end()) return false; - qv.erase(q); - assert(nBindings > 0); - nBindings--; - - if(qv.empty()) { - bindingTree.removeBindingKey(routingKey); - } - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - QPID_LOG(debug, "Unbound key [" << routingKey << "] from queue " << queue->getName() - << " on exchange " << getName()); - return true; -} - -/** returns a pointer to the BindingKey if the given queue is bound to this - * exchange using the routing pattern. 0 if queue binding does not exist. - */ -TopicExchange::BindingKey *TopicExchange::getQueueBinding(Queue::shared_ptr queue, const string& pattern) -{ - // Note well: lock held by caller.... - BindingKey *bk = bindingTree.getBindingKey(pattern); // Exact match against binding pattern - if (!bk) return 0; - Binding::vector& qv(bk->bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) - if ((*q)->queue == queue) - break; - return (q != qv.end()) ? bk : 0; -} - -void TopicExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/) -{ - // Note: PERFORMANCE CRITICAL!!! - BindingList b; - std::map<std::string, BindingList>::iterator it; - { // only lock the cache for read - RWlock::ScopedRlock cl(cacheLock); - it = bindingCache.find(routingKey); - if (it != bindingCache.end()) { - b = it->second; - } - } - PreRoute pr(msg, this); - if (!b.get()) // no cache hit - { - RWlock::ScopedRlock l(lock); - b = BindingList(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >); - BindingsFinderIter bindingsFinder(b); - bindingTree.iterateMatch(routingKey, bindingsFinder); - RWlock::ScopedWlock cwl(cacheLock); - bindingCache[routingKey] = b; // update cache - } - doRoute(msg, b); -} - -bool TopicExchange::isBound(Queue::shared_ptr queue, const string* const routingKey, const FieldTable* const) -{ - RWlock::ScopedRlock l(lock); - if (routingKey && queue) { - string key(normalize(*routingKey)); - return getQueueBinding(queue, key) != 0; - } else if (!routingKey && !queue) { - return nBindings > 0; - } else if (routingKey) { - if (bindingTree.getBindingKey(*routingKey)) { - return true; - } - } else { - QueueFinderIter queueFinder(queue); - bindingTree.iterateAll( queueFinder ); - return queueFinder.found; - } - return false; -} - -TopicExchange::~TopicExchange() {} - -const std::string TopicExchange::typeName("topic"); - -// -// class BindingNode -// - -TopicExchange::BindingNode::~BindingNode() -{ - childTokens.clear(); -} - - -// Add a binding pattern to the tree. Return a pointer to the binding key -// of the node that matches the binding pattern. -TopicExchange::BindingKey* -TopicExchange::BindingNode::addBindingKey(const std::string& normalizedRoute) -{ - TokenIterator bKey(normalizedRoute); - return addBindingKey(bKey, normalizedRoute); -} - - -// Return a pointer to the binding key of the leaf node that matches the binding pattern. -TopicExchange::BindingKey* -TopicExchange::BindingNode::getBindingKey(const std::string& normalizedRoute) -{ - TokenIterator bKey(normalizedRoute); - return getBindingKey(bKey); -} - - -// Delete the binding associated with the given route. -void TopicExchange::BindingNode::removeBindingKey(const std::string& normalizedRoute) -{ - TokenIterator bKey2(normalizedRoute); - removeBindingKey(bKey2, normalizedRoute); -} - -// visit each node in the tree. Note: all nodes are visited, -// even non-leaf nodes (i.e. nodes without any bindings) -bool TopicExchange::BindingNode::iterateAll(TopicExchange::BindingNode::TreeIterator& iter) -{ - if (!iter.visit(*this)) return false; - - if (starChild && !starChild->iterateAll(iter)) return false; - - if (hashChild && !hashChild->iterateAll(iter)) return false; - - for (ChildMap::iterator ptr = childTokens.begin(); - ptr != childTokens.end(); ptr++) { - - if (!ptr->second->iterateAll(iter)) return false; - } - - return true; -} - -// applies iter against only matching nodes until iter returns false -// Note Well: the iter may match against the same node more than once -// if # wildcards are present! -bool TopicExchange::BindingNode::iterateMatch(const std::string& routingKey, TreeIterator& iter) -{ - TopicExchange::TokenIterator rKey(routingKey); - return iterateMatch( rKey, iter ); -} - - -// recurse over binding using token iterator. -// Note well: bkey is modified! -TopicExchange::BindingKey* -TopicExchange::BindingNode::addBindingKey(TokenIterator &bKey, - const string& fullPattern) -{ - if (bKey.finished()) { - // this node's binding - if (routePattern.empty()) { - routePattern = fullPattern; - } else assert(routePattern == fullPattern); - - return &bindings; - - } else { - // pop the topmost token & recurse... - - if (bKey.match(STAR)) { - if (!starChild) { - starChild.reset(new StarNode()); - } - bKey.next(); - return starChild->addBindingKey(bKey, fullPattern); - - } else if (bKey.match(HASH)) { - if (!hashChild) { - hashChild.reset(new HashNode()); - } - bKey.next(); - return hashChild->addBindingKey(bKey, fullPattern); - - } else { - ChildMap::iterator ptr; - std::string next_token; - bKey.pop(next_token); - ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - return ptr->second->addBindingKey(bKey, fullPattern); - } else { - BindingNode::shared_ptr child(new BindingNode(next_token)); - childTokens[next_token] = child; - return child->addBindingKey(bKey, fullPattern); - } - } - } -} - - -// Remove a binding pattern from the tree. Return true if the current -// node becomes a leaf without any bindings (therefore can be deleted). -// Note Well: modifies parameter bKey's value! -bool -TopicExchange::BindingNode::removeBindingKey(TokenIterator &bKey, - const string& fullPattern) -{ - bool remove; - - if (!bKey.finished()) { - - if (bKey.match(STAR)) { - bKey.next(); - if (starChild) { - remove = starChild->removeBindingKey(bKey, fullPattern); - if (remove) { - starChild.reset(); - } - } - } else if (bKey.match(HASH)) { - bKey.next(); - if (hashChild) { - remove = hashChild->removeBindingKey(bKey, fullPattern); - if (remove) { - hashChild.reset(); - } - } - } else { - ChildMap::iterator ptr; - std::string next_token; - bKey.pop(next_token); - ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - remove = ptr->second->removeBindingKey(bKey, fullPattern); - if (remove) { - childTokens.erase(ptr); - } - } - } - } - - // no bindings and no children == parent can delete this node. - return getChildCount() == 0 && bindings.bindingVector.empty(); -} - - -// find the binding key that matches the given binding pattern. -// Note Well: modifies key parameter! -TopicExchange::BindingKey* -TopicExchange::BindingNode::getBindingKey(TokenIterator &key) -{ - if (key.finished()) { - return &bindings; - } - - string next_token; - - key.pop(next_token); - - if (next_token == STAR) { - if (starChild) - return starChild->getBindingKey(key); - } else if (next_token == HASH) { - if (hashChild) - return hashChild->getBindingKey(key); - } else { - ChildMap::iterator ptr; - ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - return ptr->second->getBindingKey(key); - } - } - - return 0; -} - - - -// iterate over all nodes that match the given key. Note well: the set of nodes -// that are visited includes matching non-leaf nodes. -// Note well: parameter key is modified! -bool TopicExchange::BindingNode::iterateMatch(TokenIterator& key, TreeIterator& iter) -{ - // invariant: key has matched all previous tokens up to this node. - if (key.finished()) { - // exact match this node: visit if bound - if (!bindings.bindingVector.empty()) - if (!iter.visit(*this)) return false; - } - - // check remaining key against children, even if empty. - return iterateMatchChildren(key, iter); -} - - -TopicExchange::StarNode::StarNode() - : BindingNode(STAR) {} - - -// See iterateMatch() above. -// Special case: this node must verify a token is available (match exactly one). -bool TopicExchange::StarNode::iterateMatch(TokenIterator& key, TreeIterator& iter) -{ - // must match one token: - if (key.finished()) - return true; // match failed, but continue iteration on siblings - - // pop the topmost token - key.next(); - - if (key.finished()) { - // exact match this node: visit if bound - if (!bindings.bindingVector.empty()) - if (!iter.visit(*this)) return false; - } - - return iterateMatchChildren(key, iter); -} - - -TopicExchange::HashNode::HashNode() - : BindingNode(HASH) {} - - -// See iterateMatch() above. -// Special case: can match zero or more tokens at the head of the key. -bool TopicExchange::HashNode::iterateMatch(TokenIterator& key, TreeIterator& iter) -{ - // consume each token and look for a match on the - // remaining key. - while (!key.finished()) { - if (!iterateMatchChildren(key, iter)) return false; - key.next(); - } - - if (!bindings.bindingVector.empty()) - return iter.visit(*this); - - return true; -} - - -// helper: iterate over current node's matching children -bool -TopicExchange::BindingNode::iterateMatchChildren(const TopicExchange::TokenIterator& key, - TopicExchange::BindingNode::TreeIterator& iter) -{ - // always try glob - it can match empty keys - if (hashChild) { - TokenIterator tmp(key); - if (!hashChild->iterateMatch(tmp, iter)) - return false; - } - - if (!key.finished()) { - - if (starChild) { - TokenIterator tmp(key); - if (!starChild->iterateMatch(tmp, iter)) - return false; - } - - if (!childTokens.empty()) { - TokenIterator newKey(key); - std::string next_token; - newKey.pop(next_token); - - ChildMap::iterator ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - return ptr->second->iterateMatch(newKey, iter); - } - } - } - - return true; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/TopicExchange.h b/cpp/src/qpid/broker/TopicExchange.h deleted file mode 100644 index 636918f8a1..0000000000 --- a/cpp/src/qpid/broker/TopicExchange.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TopicExchange_ -#define _TopicExchange_ - -#include <map> -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Monitor.h" -#include "qpid/broker/Queue.h" - - -namespace qpid { -namespace broker { - -class TopicExchange : public virtual Exchange { - - struct TokenIterator; - class Normalizer; - - struct BindingKey { // binding for this node - Binding::vector bindingVector; - FedBinding fedBinding; - }; - - // Binding database: - // The dotted form of a binding key is broken up and stored in a directed tree graph. - // Common binding prefix are merged. This allows the route match alogrithm to quickly - // isolate those sub-trees that match a given routingKey. - // For example, given the routes: - // a.b.c.<...> - // a.b.d.<...> - // a.x.y.<...> - // The resulting tree would be: - // a-->b-->c-->... - // | +-->d-->... - // +-->x-->y-->... - // - class QPID_BROKER_CLASS_EXTERN BindingNode { - public: - - typedef boost::shared_ptr<BindingNode> shared_ptr; - - // for database transversal (visit a node). - class TreeIterator { - public: - TreeIterator() {}; - virtual ~TreeIterator() {}; - virtual bool visit(BindingNode& node) = 0; - }; - - BindingNode() {}; - BindingNode(const std::string& token) : token(token) {}; - QPID_BROKER_EXTERN virtual ~BindingNode(); - - // add normalizedRoute to tree, return associated BindingKey - QPID_BROKER_EXTERN BindingKey* addBindingKey(const std::string& normalizedRoute); - - // return BindingKey associated with normalizedRoute - QPID_BROKER_EXTERN BindingKey* getBindingKey(const std::string& normalizedRoute); - - // remove BindingKey associated with normalizedRoute - QPID_BROKER_EXTERN void removeBindingKey(const std::string& normalizedRoute); - - // applies iter against each node in tree until iter returns false - QPID_BROKER_EXTERN bool iterateAll(TreeIterator& iter); - - // applies iter against only matching nodes until iter returns false - QPID_BROKER_EXTERN bool iterateMatch(const std::string& routingKey, TreeIterator& iter); - - std::string routePattern; // normalized binding that matches this node - BindingKey bindings; // for matches against this node - - protected: - - std::string token; // portion of pattern represented by this node - - // children - typedef std::map<const std::string, BindingNode::shared_ptr> ChildMap; - ChildMap childTokens; - BindingNode::shared_ptr starChild; // "*" subtree - BindingNode::shared_ptr hashChild; // "#" subtree - - unsigned int getChildCount() { return childTokens.size() + - (starChild ? 1 : 0) + (hashChild ? 1 : 0); } - BindingKey* addBindingKey(TokenIterator& bKey, - const std::string& fullPattern); - bool removeBindingKey(TokenIterator& bKey, - const std::string& fullPattern); - BindingKey* getBindingKey(TokenIterator& bKey); - QPID_BROKER_EXTERN virtual bool iterateMatch(TokenIterator& rKey, TreeIterator& iter); - bool iterateMatchChildren(const TokenIterator& key, TreeIterator& iter); - }; - - // Special case: ("*" token) Node in the tree for a match exactly one wildcard - class StarNode : public BindingNode { - public: - StarNode(); - ~StarNode() {}; - - protected: - virtual bool iterateMatch(TokenIterator& key, TreeIterator& iter); - }; - - // Special case: ("#" token) Node in the tree for a match zero or more - class HashNode : public BindingNode { - public: - HashNode(); - ~HashNode() {}; - - protected: - virtual bool iterateMatch(TokenIterator& key, TreeIterator& iter); - }; - - BindingNode bindingTree; - unsigned long nBindings; - qpid::sys::RWlock lock; // protects bindingTree and nBindings - qpid::sys::RWlock cacheLock; // protects cache - std::map<std::string, BindingList> bindingCache; // cache of matched routes. - class ClearCache { - private: - qpid::sys::RWlock* cacheLock; - std::map<std::string, BindingList>* bindingCache; - bool cleared; - public: - ClearCache(qpid::sys::RWlock* l, std::map<std::string, BindingList>* bc): cacheLock(l), - bindingCache(bc),cleared(false) {}; - void clearCache() { - qpid::sys::RWlock::ScopedWlock l(*cacheLock); - if (!cleared) { - bindingCache->clear(); - cleared =true; - } - }; - ~ClearCache(){ - clearCache(); - }; - }; - BindingKey *getQueueBinding(Queue::shared_ptr queue, const std::string& pattern); - bool deleteBinding(Queue::shared_ptr queue, - const std::string& routingKey, - BindingKey *bk); - - class ReOriginIter; - class BindingsFinderIter; - class QueueFinderIter; - - public: - static const std::string typeName; - - static QPID_BROKER_EXTERN std::string normalize(const std::string& pattern); - - QPID_BROKER_EXTERN TopicExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN TopicExchange(const std::string& _name, - bool _durable, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual bool isBound(Queue::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~TopicExchange(); - virtual bool supportsDynamicBinding() { return true; } - - class TopicExchangeTester; - friend class TopicExchangeTester; -}; - - - -} -} - -#endif diff --git a/cpp/src/qpid/broker/TransactionalStore.h b/cpp/src/qpid/broker/TransactionalStore.h deleted file mode 100644 index 2a2bac0c51..0000000000 --- a/cpp/src/qpid/broker/TransactionalStore.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TransactionalStore_ -#define _TransactionalStore_ - -#include <memory> -#include <string> -#include <set> - -namespace qpid { -namespace broker { - -struct InvalidTransactionContextException : public std::exception {}; - -class TransactionContext { -public: - virtual ~TransactionContext(){} -}; - -class TPCTransactionContext : public TransactionContext { -public: - virtual ~TPCTransactionContext(){} -}; - -class TransactionalStore { -public: - virtual std::auto_ptr<TransactionContext> begin() = 0; - virtual std::auto_ptr<TPCTransactionContext> begin(const std::string& xid) = 0; - virtual void prepare(TPCTransactionContext& txn) = 0; - virtual void commit(TransactionContext& txn) = 0; - virtual void abort(TransactionContext& txn) = 0; - - virtual void collectPreparedXids(std::set<std::string>& xids) = 0; - - virtual ~TransactionalStore(){} -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/TxAccept.cpp b/cpp/src/qpid/broker/TxAccept.cpp deleted file mode 100644 index 928ac12c10..0000000000 --- a/cpp/src/qpid/broker/TxAccept.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/TxAccept.h" -#include "qpid/log/Statement.h" - -using std::bind1st; -using std::bind2nd; -using std::mem_fun_ref; -using namespace qpid::broker; -using qpid::framing::SequenceSet; -using qpid::framing::SequenceNumber; - -TxAccept::RangeOp::RangeOp(const AckRange& r) : range(r) {} - -void TxAccept::RangeOp::prepare(TransactionContext* ctxt) -{ - for_each(range.start, range.end, bind(&DeliveryRecord::dequeue, _1, ctxt)); -} - -void TxAccept::RangeOp::commit() -{ - for_each(range.start, range.end, bind(&DeliveryRecord::committed, _1)); - for_each(range.start, range.end, bind(&DeliveryRecord::setEnded, _1)); -} - -TxAccept::RangeOps::RangeOps(DeliveryRecords& u) : unacked(u) {} - -void TxAccept::RangeOps::operator()(SequenceNumber start, SequenceNumber end) -{ - ranges.push_back(RangeOp(DeliveryRecord::findRange(unacked, start, end))); -} - -void TxAccept::RangeOps::prepare(TransactionContext* ctxt) -{ - std::for_each(ranges.begin(), ranges.end(), bind(&RangeOp::prepare, _1, ctxt)); -} - -void TxAccept::RangeOps::commit() -{ - std::for_each(ranges.begin(), ranges.end(), bind(&RangeOp::commit, _1)); - //now remove if isRedundant(): - if (!ranges.empty()) { - DeliveryRecords::iterator begin = ranges.front().range.start; - DeliveryRecords::iterator end = ranges.back().range.end; - DeliveryRecords::iterator removed = remove_if(begin, end, mem_fun_ref(&DeliveryRecord::isRedundant)); - unacked.erase(removed, end); - } -} - -TxAccept::TxAccept(const SequenceSet& _acked, DeliveryRecords& _unacked) : - acked(_acked), unacked(_unacked), ops(unacked) -{ - //populate the ops - acked.for_each(ops); -} - -bool TxAccept::prepare(TransactionContext* ctxt) throw() -{ - try{ - ops.prepare(ctxt); - return true; - }catch(const std::exception& e){ - QPID_LOG(error, "Failed to prepare: " << e.what()); - return false; - }catch(...){ - QPID_LOG(error, "Failed to prepare"); - return false; - } -} - -void TxAccept::commit() throw() -{ - try { - ops.commit(); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to commit (unknown error)"); - } -} - -void TxAccept::rollback() throw() {} diff --git a/cpp/src/qpid/broker/TxAccept.h b/cpp/src/qpid/broker/TxAccept.h deleted file mode 100644 index 314a150176..0000000000 --- a/cpp/src/qpid/broker/TxAccept.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TxAccept_ -#define _TxAccept_ - -#include <algorithm> -#include <functional> -#include <list> -#include "qpid/framing/SequenceSet.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/TxOp.h" - -namespace qpid { - namespace broker { - /** - * Defines the transactional behaviour for accepts received by - * a transactional channel. - */ - class TxAccept : public TxOp { - struct RangeOp - { - AckRange range; - - RangeOp(const AckRange& r); - void prepare(TransactionContext* ctxt); - void commit(); - }; - - struct RangeOps - { - std::vector<RangeOp> ranges; - DeliveryRecords& unacked; - - RangeOps(DeliveryRecords& u); - - void operator()(framing::SequenceNumber start, framing::SequenceNumber end); - void prepare(TransactionContext* ctxt); - void commit(); - }; - - framing::SequenceSet acked; - DeliveryRecords& unacked; - RangeOps ops; - - public: - /** - * @param acked a representation of the accumulation of - * acks received - * @param unacked the record of delivered messages - */ - TxAccept(const framing::SequenceSet& acked, DeliveryRecords& unacked); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~TxAccept(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - - // Used by cluster replication. - const framing::SequenceSet& getAcked() const { return acked; } - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/TxBuffer.cpp b/cpp/src/qpid/broker/TxBuffer.cpp deleted file mode 100644 index b509778e89..0000000000 --- a/cpp/src/qpid/broker/TxBuffer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/TxBuffer.h" -#include "qpid/log/Statement.h" - -#include <boost/mem_fn.hpp> -#include <boost/bind.hpp> -using boost::mem_fn; -using namespace qpid::broker; - -bool TxBuffer::prepare(TransactionContext* const ctxt) -{ - for(op_iterator i = ops.begin(); i < ops.end(); i++){ - if(!(*i)->prepare(ctxt)){ - return false; - } - } - return true; -} - -void TxBuffer::commit() -{ - std::for_each(ops.begin(), ops.end(), mem_fn(&TxOp::commit)); - ops.clear(); -} - -void TxBuffer::rollback() -{ - std::for_each(ops.begin(), ops.end(), mem_fn(&TxOp::rollback)); - ops.clear(); -} - -void TxBuffer::enlist(TxOp::shared_ptr op) -{ - ops.push_back(op); -} - -bool TxBuffer::commitLocal(TransactionalStore* const store) -{ - if (!store) return false; - try { - std::auto_ptr<TransactionContext> ctxt = store->begin(); - if (prepare(ctxt.get())) { - store->commit(*ctxt); - commit(); - return true; - } else { - store->abort(*ctxt); - rollback(); - return false; - } - } catch (std::exception& e) { - QPID_LOG(error, "Commit failed with exception: " << e.what()); - } catch (...) { - QPID_LOG(error, "Commit failed with unknown exception"); - } - return false; -} - -void TxBuffer::accept(TxOpConstVisitor& v) const { - std::for_each(ops.begin(), ops.end(), boost::bind(&TxOp::accept, _1, boost::ref(v))); -} diff --git a/cpp/src/qpid/broker/TxBuffer.h b/cpp/src/qpid/broker/TxBuffer.h deleted file mode 100644 index d49c8ba16a..0000000000 --- a/cpp/src/qpid/broker/TxBuffer.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TxBuffer_ -#define _TxBuffer_ - -#include <algorithm> -#include <functional> -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/broker/TxOp.h" - -/** - * Represents a single transaction. As such, an instance of this class - * will hold a list of operations representing the workload of the - * transaction. This work can be committed or rolled back. Committing - * is a two-stage process: first all the operations should be - * prepared, then if that succeeds they can be committed. - * - * In the 2pc case, a successful prepare may be followed by either a - * commit or a rollback. - * - * Atomicity of prepare is ensured by using a lower level - * transactional facility. This saves explicitly rolling back all the - * successfully prepared ops when one of them fails. i.e. we do not - * use 2pc internally, we instead ensure that prepare is atomic at a - * lower level. This makes individual prepare operations easier to - * code. - * - * Transactions on a messaging broker effect three types of 'action': - * (1) updates to persistent storage (2) updates to transient storage - * or cached data (3) network writes. - * - * Of these, (1) should always occur atomically during prepare to - * ensure that if the broker crashes while a transaction is being - * completed the persistent state (which is all that then remains) is - * consistent. (3) can only be done on commit, after a successful - * prepare. There is a little more flexibility with (2) but any - * changes made during prepare should be subject to the control of the - * TransactionalStore in use. - */ -namespace qpid { - namespace broker { - class TxBuffer{ - typedef std::vector<TxOp::shared_ptr>::iterator op_iterator; - std::vector<TxOp::shared_ptr> ops; - protected: - - public: - typedef boost::shared_ptr<TxBuffer> shared_ptr; - /** - * Adds an operation to the transaction. - */ - QPID_BROKER_EXTERN void enlist(TxOp::shared_ptr op); - - /** - * Requests that all ops are prepared. This should - * primarily involve making sure that a persistent record - * of the operations is stored where necessary. - * - * Once prepared, a transaction can be committed (or in - * the 2pc case, rolled back). - * - * @returns true if all the operations prepared - * successfully, false if not. - */ - QPID_BROKER_EXTERN bool prepare(TransactionContext* const ctxt); - - /** - * Signals that the ops all prepared successfully and can - * now commit, i.e. the operation can now be fully carried - * out. - * - * Should only be called after a call to prepare() returns - * true. - */ - QPID_BROKER_EXTERN void commit(); - - /** - * Signals that all ops can be rolled back. - * - * Should only be called either after a call to prepare() - * returns true (2pc) or instead of a prepare call - * ('server-local') - */ - QPID_BROKER_EXTERN void rollback(); - - /** - * Helper method for managing the process of server local - * commit - */ - QPID_BROKER_EXTERN bool commitLocal(TransactionalStore* const store); - - // Used by cluster to replicate transaction status. - void accept(TxOpConstVisitor& v) const; - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/TxOp.h b/cpp/src/qpid/broker/TxOp.h deleted file mode 100644 index a8fa1c2621..0000000000 --- a/cpp/src/qpid/broker/TxOp.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TxOp_ -#define _TxOp_ - -#include "qpid/broker/TxOpVisitor.h" -#include "qpid/broker/TransactionalStore.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { - namespace broker { - - class TxOp{ - public: - typedef boost::shared_ptr<TxOp> shared_ptr; - - virtual bool prepare(TransactionContext*) throw() = 0; - virtual void commit() throw() = 0; - virtual void rollback() throw() = 0; - virtual ~TxOp(){} - - virtual void accept(TxOpConstVisitor&) const = 0; - }; - -}} // namespace qpid::broker - - -#endif diff --git a/cpp/src/qpid/broker/TxOpVisitor.h b/cpp/src/qpid/broker/TxOpVisitor.h deleted file mode 100644 index ceb894896e..0000000000 --- a/cpp/src/qpid/broker/TxOpVisitor.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef QPID_BROKER_TXOPVISITOR_H -#define QPID_BROKER_TXOPVISITOR_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -namespace qpid { -namespace broker { - -class DtxAck; -class RecoveredDequeue; -class RecoveredEnqueue; -class TxAccept; -class TxPublish; - -/** - * Visitor for TxOp familly of classes. - */ -struct TxOpConstVisitor -{ - virtual ~TxOpConstVisitor() {} - virtual void operator()(const DtxAck&) = 0; - virtual void operator()(const RecoveredDequeue&) = 0; - virtual void operator()(const RecoveredEnqueue&) = 0; - virtual void operator()(const TxAccept&) = 0; - virtual void operator()(const TxPublish&) = 0; -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_TXOPVISITOR_H*/ -#ifndef QPID_BROKER_TXOPVISITOR_H -#define QPID_BROKER_TXOPVISITOR_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -namespace qpid { -namespace broker { - -class DtxAck; -class RecoveredDequeue; -class RecoveredEnqueue; -class TxAccept; -class TxPublish; - -/** - * Visitor for TxOp familly of classes. - */ -struct TxOpConstVisitor -{ - virtual ~TxOpConstVisitor() {} - virtual void operator()(const DtxAck&) = 0; - virtual void operator()(const RecoveredDequeue&) = 0; - virtual void operator()(const RecoveredEnqueue&) = 0; - virtual void operator()(const TxAccept&) = 0; - virtual void operator()(const TxPublish&) = 0; -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_TXOPVISITOR_H*/ diff --git a/cpp/src/qpid/broker/TxPublish.cpp b/cpp/src/qpid/broker/TxPublish.cpp deleted file mode 100644 index 9c2cf4a467..0000000000 --- a/cpp/src/qpid/broker/TxPublish.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/log/Statement.h" -#include "qpid/broker/TxPublish.h" -#include "qpid/broker/Queue.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; - -TxPublish::TxPublish(intrusive_ptr<Message> _msg) : msg(_msg) {} - -bool TxPublish::prepare(TransactionContext* ctxt) throw() -{ - try{ - while (!queues.empty()) { - prepare(ctxt, queues.front()); - prepared.push_back(queues.front()); - queues.pop_front(); - } - return true; - }catch(const std::exception& e){ - QPID_LOG(error, "Failed to prepare: " << e.what()); - }catch(...){ - QPID_LOG(error, "Failed to prepare (unknown error)"); - } - return false; -} - -void TxPublish::commit() throw() -{ - try { - for_each(prepared.begin(), prepared.end(), Commit(msg)); - if (msg->isContentReleaseRequested()) { - // NOTE: The log messages in this section are used for flow-to-disk testing (which checks the log for the - // presence of these messages). Do not change these without also checking these tests. - if (msg->isContentReleaseBlocked()) { - QPID_LOG(debug, "Message id=\"" << msg->getProperties<qpid::framing::MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content release blocked on commit"); - } else { - msg->releaseContent(); - QPID_LOG(debug, "Message id=\"" << msg->getProperties<qpid::framing::MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content released on commit"); - } - } - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to commit (unknown error)"); - } -} - -void TxPublish::rollback() throw() -{ - try { - for_each(prepared.begin(), prepared.end(), Rollback(msg)); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to complete rollback: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to complete rollback (unknown error)"); - } - -} - -void TxPublish::deliverTo(const boost::shared_ptr<Queue>& queue){ - if (!queue->isLocal(msg)) { - queues.push_back(queue); - delivered = true; - } else { - QPID_LOG(debug, "Won't enqueue local message for " << queue->getName()); - } -} - -void TxPublish::prepare(TransactionContext* ctxt, const boost::shared_ptr<Queue> queue) -{ - queue->enqueue(ctxt, msg); -} - -TxPublish::Commit::Commit(intrusive_ptr<Message>& _msg) : msg(_msg){} - -void TxPublish::Commit::operator()(const boost::shared_ptr<Queue>& queue){ - queue->process(msg); -} - -TxPublish::Rollback::Rollback(intrusive_ptr<Message>& _msg) : msg(_msg){} - -void TxPublish::Rollback::operator()(const boost::shared_ptr<Queue>& queue){ - queue->enqueueAborted(msg); -} - -uint64_t TxPublish::contentSize () -{ - return msg->contentSize (); -} diff --git a/cpp/src/qpid/broker/TxPublish.h b/cpp/src/qpid/broker/TxPublish.h deleted file mode 100644 index f0b9c0a302..0000000000 --- a/cpp/src/qpid/broker/TxPublish.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TxPublish_ -#define _TxPublish_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/TxOp.h" - -#include <algorithm> -#include <functional> -#include <list> - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - namespace broker { - /** - * Defines the behaviour for publish operations on a - * transactional channel. Messages are routed through - * exchanges when received but are not at that stage delivered - * to the matching queues, rather the queues are held in an - * instance of this class. On prepare() the message is marked - * enqueued to the relevant queues in the MessagesStore. On - * commit() the messages will be passed to the queue for - * dispatch or to be added to the in-memory queue. - */ - class QPID_BROKER_CLASS_EXTERN TxPublish : public TxOp, public Deliverable{ - - class Commit{ - boost::intrusive_ptr<Message>& msg; - public: - Commit(boost::intrusive_ptr<Message>& msg); - void operator()(const boost::shared_ptr<Queue>& queue); - }; - class Rollback{ - boost::intrusive_ptr<Message>& msg; - public: - Rollback(boost::intrusive_ptr<Message>& msg); - void operator()(const boost::shared_ptr<Queue>& queue); - }; - - boost::intrusive_ptr<Message> msg; - std::list<boost::shared_ptr<Queue> > queues; - std::list<boost::shared_ptr<Queue> > prepared; - - void prepare(TransactionContext* ctxt, boost::shared_ptr<Queue>); - - public: - QPID_BROKER_EXTERN TxPublish(boost::intrusive_ptr<Message> msg); - QPID_BROKER_EXTERN virtual bool prepare(TransactionContext* ctxt) throw(); - QPID_BROKER_EXTERN virtual void commit() throw(); - QPID_BROKER_EXTERN virtual void rollback() throw(); - - virtual Message& getMessage() { return *msg; }; - - QPID_BROKER_EXTERN virtual void deliverTo(const boost::shared_ptr<Queue>& queue); - - virtual ~TxPublish(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - - QPID_BROKER_EXTERN uint64_t contentSize(); - - boost::intrusive_ptr<Message> getMessage() const { return msg; } - const std::list<boost::shared_ptr<Queue> > getQueues() const { return queues; } - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/Vhost.cpp b/cpp/src/qpid/broker/Vhost.cpp deleted file mode 100644 index a9ca3b42ab..0000000000 --- a/cpp/src/qpid/broker/Vhost.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/broker/Vhost.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" - -using namespace qpid::broker; -using qpid::management::ManagementAgent; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { namespace management { -class Manageable; -}} - -Vhost::Vhost (qpid::management::Manageable* parentBroker, Broker* broker) : mgmtObject(0) -{ - if (parentBroker != 0 && broker != 0) - { - ManagementAgent* agent = broker->getManagementAgent(); - - if (agent != 0) - { - mgmtObject = new _qmf::Vhost(agent, this, parentBroker, "/"); - agent->addObject(mgmtObject, 0, true); - } - } -} - -void Vhost::setFederationTag(const std::string& tag) -{ - mgmtObject->set_federationTag(tag); -} diff --git a/cpp/src/qpid/broker/Vhost.h b/cpp/src/qpid/broker/Vhost.h deleted file mode 100644 index 9554d641c2..0000000000 --- a/cpp/src/qpid/broker/Vhost.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _Vhost_ -#define _Vhost_ - -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Vhost.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -class Broker; -class Vhost : public management::Manageable -{ - private: - - qmf::org::apache::qpid::broker::Vhost* mgmtObject; - - public: - - typedef boost::shared_ptr<Vhost> shared_ptr; - - Vhost (management::Manageable* parentBroker, Broker* broker = 0); - - management::ManagementObject* GetManagementObject (void) const - { return mgmtObject; } - void setFederationTag(const std::string& tag); -}; - -}} - -#endif /*!_Vhost_*/ diff --git a/cpp/src/qpid/broker/posix/BrokerDefaults.cpp b/cpp/src/qpid/broker/posix/BrokerDefaults.cpp deleted file mode 100644 index 9e463fa32d..0000000000 --- a/cpp/src/qpid/broker/posix/BrokerDefaults.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include <stdlib.h> - -namespace qpid { -namespace broker { - -const std::string Broker::Options::DEFAULT_DATA_DIR_LOCATION("/tmp"); -const std::string Broker::Options::DEFAULT_DATA_DIR_NAME("/.qpidd"); - -std::string -Broker::Options::getHome() { - std::string home; - char *home_c = ::getenv("HOME"); - if (home_c != 0) - home += home_c; - return home; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/windows/BrokerDefaults.cpp b/cpp/src/qpid/broker/windows/BrokerDefaults.cpp deleted file mode 100644 index b65440b5ad..0000000000 --- a/cpp/src/qpid/broker/windows/BrokerDefaults.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include <stdlib.h> - -namespace qpid { -namespace broker { - -const std::string Broker::Options::DEFAULT_DATA_DIR_LOCATION("\\TEMP"); -const std::string Broker::Options::DEFAULT_DATA_DIR_NAME("\\QPIDD.DATA"); - -std::string -Broker::Options::getHome() { - std::string home; -#ifdef _MSC_VER - char home_c[MAX_PATH+1]; - size_t unused; - if (0 == getenv_s (&unused, home_c, sizeof(home_c), "HOME")) - home += home_c; -#else - char *home_c = getenv("HOME"); - if (home_c) - home += home_c; -#endif - return home; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp b/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp deleted file mode 100644 index 962877a471..0000000000 --- a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// This source is only used on Windows; SSPI is the Windows mechanism for -// accessing authentication mechanisms, analogous to Cyrus SASL. - -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" - -#include <windows.h> - -using namespace qpid::framing; -using qpid::sys::SecurityLayer; - -namespace qpid { -namespace broker { - -class NullAuthenticator : public SaslAuthenticator -{ - Connection& connection; - framing::AMQP_ClientProxy::Connection client; -public: - NullAuthenticator(Connection& connection); - ~NullAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string&) {} - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); -}; - -class SspiAuthenticator : public SaslAuthenticator -{ - HANDLE userToken; - Connection& connection; - framing::AMQP_ClientProxy::Connection client; - -public: - SspiAuthenticator(Connection& connection); - ~SspiAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string& response); - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); -}; - -bool SaslAuthenticator::available(void) -{ - return true; -} - -// Initialize the SASL mechanism; throw if it fails. -void SaslAuthenticator::init(const std::string& /*saslName*/, const std::string& /*saslConfig*/) -{ - return; -} - -void SaslAuthenticator::fini(void) -{ - return; -} - -std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connection& c, bool) -{ - if (c.getBroker().getOptions().auth) { - return std::auto_ptr<SaslAuthenticator>(new SspiAuthenticator(c)); - } else { - return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c)); - } -} - -NullAuthenticator::NullAuthenticator(Connection& c) : connection(c), client(c.getOutput()) {} -NullAuthenticator::~NullAuthenticator() {} - -void NullAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("ANONYMOUS"))); -} - -void NullAuthenticator::start(const string& mechanism, const string& response) -{ - QPID_LOG(warning, "SASL: No Authentication Performed"); - if (mechanism == "PLAIN") { // Old behavior - if (response.size() > 0 && response[0] == (char) 0) { - string temp = response.substr(1); - string::size_type i = temp.find((char)0); - string uid = temp.substr(0, i); - string pwd = temp.substr(i + 1); - connection.setUserId(uid); - } - } else { - connection.setUserId("anonymous"); - } - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); -} - -std::auto_ptr<SecurityLayer> NullAuthenticator::getSecurityLayer(uint16_t) -{ - std::auto_ptr<SecurityLayer> securityLayer; - return securityLayer; -} - - -SspiAuthenticator::SspiAuthenticator(Connection& c) : userToken(INVALID_HANDLE_VALUE), connection(c), client(c.getOutput()) -{ -} - -SspiAuthenticator::~SspiAuthenticator() -{ - if (INVALID_HANDLE_VALUE != userToken) { - CloseHandle(userToken); - userToken = INVALID_HANDLE_VALUE; - } -} - -void SspiAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value(string("ANONYMOUS")))); - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value(string("PLAIN")))); - QPID_LOG(info, "SASL: Mechanism list: ANONYMOUS PLAIN"); -} - -void SspiAuthenticator::start(const string& mechanism, const string& response) -{ - QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism); - if (mechanism == "ANONYMOUS") { - connection.setUserId("anonymous"); - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); - return; - } - if (mechanism != "PLAIN") - throw ConnectionForcedException("Unsupported mechanism"); - - // PLAIN's response is composed of 3 strings separated by 0 bytes: - // authorization id, authentication id (user), clear-text password. - if (response.size() == 0) - throw ConnectionForcedException("Authentication failed"); - - string::size_type i = response.find((char)0); - string auth = response.substr(0, i); - string::size_type j = response.find((char)0, i+1); - string uid = response.substr(i+1, j-1); - string pwd = response.substr(j+1); - string dot("."); - int error = 0; - if (!LogonUser(const_cast<char*>(uid.c_str()), - const_cast<char*>(dot.c_str()), - const_cast<char*>(pwd.c_str()), - LOGON32_LOGON_NETWORK, - LOGON32_PROVIDER_DEFAULT, - &userToken)) - error = GetLastError(); - pwd.replace(0, string::npos, 1, (char)0); - if (error != 0) { - QPID_LOG(info, - "SASL: Auth failed [" << error << "]: " << qpid::sys::strError(error)); - throw ConnectionForcedException("Authentication failed"); - } - - connection.setUserId(uid); - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); -} - -void SspiAuthenticator::step(const string& /*response*/) -{ - QPID_LOG(info, "SASL: Need another step!!!"); -} - -std::auto_ptr<SecurityLayer> SspiAuthenticator::getSecurityLayer(uint16_t) -{ - std::auto_ptr<SecurityLayer> securityLayer; - return securityLayer; -} - -}} diff --git a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp b/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp deleted file mode 100644 index fd0e537192..0000000000 --- a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ProtocolFactory.h" - -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/AsynchIOHandler.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/windows/SslAsynchIO.h" -#include <boost/bind.hpp> -#include <memory> -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include <security.h> -#include <Schnlsp.h> -#undef SECURITY_WIN32 - - -namespace qpid { -namespace sys { -namespace windows { - -struct SslServerOptions : qpid::Options -{ - std::string certStore; - std::string certName; - uint16_t port; - bool clientAuth; - - SslServerOptions() : qpid::Options("SSL Options"), - certStore("My"), port(5671), clientAuth(false) - { - qpid::Address me; - if (qpid::sys::SystemInfo::getLocalHostname(me)) - certName = me.host; - else - certName = "localhost"; - - addOptions() - ("ssl-cert-store", optValue(certStore, "NAME"), "Local store name from which to obtain certificate") - ("ssl-cert-name", optValue(certName, "NAME"), "Name of the certificate to use") - ("ssl-port", optValue(port, "PORT"), "Port on which to listen for SSL connections") - ("ssl-require-client-authentication", optValue(clientAuth), - "Forces clients to authenticate in order to establish an SSL connection"); - } -}; - -class SslProtocolFactory : public qpid::sys::ProtocolFactory { - qpid::sys::Socket listener; - const bool tcpNoDelay; - const uint16_t listeningPort; - std::string brokerHost; - const bool clientAuthSelected; - std::auto_ptr<qpid::sys::AsynchAcceptor> acceptor; - ConnectFailedCallback connectFailedCallback; - CredHandle credHandle; - - public: - SslProtocolFactory(const SslServerOptions&, int backlog, bool nodelay); - ~SslProtocolFactory(); - void accept(sys::Poller::shared_ptr, sys::ConnectionCodec::Factory*); - void connect(sys::Poller::shared_ptr, const std::string& host, int16_t port, - sys::ConnectionCodec::Factory*, - ConnectFailedCallback failed); - - uint16_t getPort() const; - std::string getHost() const; - bool supports(const std::string& capability); - - private: - void connectFailed(const qpid::sys::Socket&, - int err, - const std::string& msg); - void established(sys::Poller::shared_ptr, - const qpid::sys::Socket&, - sys::ConnectionCodec::Factory*, - bool isClient); -}; - -// Static instance to initialise plugin -static struct SslPlugin : public Plugin { - SslServerOptions options; - - Options* getOptions() { return &options; } - - void earlyInitialize(Target&) { - } - - void initialize(Target& target) { - broker::Broker* broker = dynamic_cast<broker::Broker*>(&target); - // Only provide to a Broker - if (broker) { - try { - const broker::Broker::Options& opts = broker->getOptions(); - ProtocolFactory::shared_ptr protocol(new SslProtocolFactory(options, - opts.connectionBacklog, - opts.tcpNoDelay)); - QPID_LOG(notice, "Listening for SSL connections on TCP port " << protocol->getPort()); - broker->registerProtocolFactory("ssl", protocol); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL listener: " << e.what()); - } - } - } -} sslPlugin; - -SslProtocolFactory::SslProtocolFactory(const SslServerOptions& options, - int backlog, - bool nodelay) - : tcpNoDelay(nodelay), - listeningPort(listener.listen(options.port, backlog)), - clientAuthSelected(options.clientAuth) { - - SecInvalidateHandle(&credHandle); - - // Get the certificate for this server. - HCERTSTORE certStoreHandle; - certStoreHandle = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, - X509_ASN_ENCODING, - 0, - CERT_SYSTEM_STORE_LOCAL_MACHINE, - options.certStore.c_str()); - if (!certStoreHandle) - throw qpid::Exception(QPID_MSG("Opening store " << options.certStore << " " << qpid::sys::strError(GetLastError()))); - - PCCERT_CONTEXT certContext; - certContext = ::CertFindCertificateInStore(certStoreHandle, - X509_ASN_ENCODING, - 0, - CERT_FIND_SUBJECT_STR_A, - options.certName.c_str(), - NULL); - if (certContext == NULL) { - int err = ::GetLastError(); - ::CertCloseStore(certStoreHandle, 0); - throw qpid::Exception(QPID_MSG("Locating certificate " << options.certName << " in store " << options.certStore << " " << qpid::sys::strError(GetLastError()))); - throw QPID_WINDOWS_ERROR(err); - } - - SCHANNEL_CRED cred; - memset(&cred, 0, sizeof(cred)); - cred.dwVersion = SCHANNEL_CRED_VERSION; - cred.cCreds = 1; - cred.paCred = &certContext; - SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL, - UNISP_NAME, - SECPKG_CRED_INBOUND, - NULL, - &cred, - NULL, - NULL, - &credHandle, - NULL); - if (status != SEC_E_OK) - throw QPID_WINDOWS_ERROR(status); - ::CertFreeCertificateContext(certContext); - ::CertCloseStore(certStoreHandle, 0); -} - -SslProtocolFactory::~SslProtocolFactory() { - ::FreeCredentialsHandle(&credHandle); -} - -void SslProtocolFactory::connectFailed(const qpid::sys::Socket&, - int err, - const std::string& msg) { - if (connectFailedCallback) - connectFailedCallback(err, msg); -} - -void SslProtocolFactory::established(sys::Poller::shared_ptr poller, - const qpid::sys::Socket& s, - sys::ConnectionCodec::Factory* f, - bool isClient) { - sys::AsynchIOHandler* async = new sys::AsynchIOHandler(s.getFullAddress(), f); - - if (tcpNoDelay) { - s.setTcpNoDelay(); - QPID_LOG(info, - "Set TCP_NODELAY on connection to " << s.getPeerAddress()); - } - - SslAsynchIO *aio; - if (isClient) { - async->setClient(); - aio = - new qpid::sys::windows::ClientSslAsynchIO(brokerHost, - s, - credHandle, - boost::bind(&AsynchIOHandler::readbuff, async, _1, _2), - boost::bind(&AsynchIOHandler::eof, async, _1), - boost::bind(&AsynchIOHandler::disconnect, async, _1), - boost::bind(&AsynchIOHandler::closedSocket, async, _1, _2), - boost::bind(&AsynchIOHandler::nobuffs, async, _1), - boost::bind(&AsynchIOHandler::idle, async, _1)); - } - else { - aio = - new qpid::sys::windows::ServerSslAsynchIO(clientAuthSelected, - s, - credHandle, - boost::bind(&AsynchIOHandler::readbuff, async, _1, _2), - boost::bind(&AsynchIOHandler::eof, async, _1), - boost::bind(&AsynchIOHandler::disconnect, async, _1), - boost::bind(&AsynchIOHandler::closedSocket, async, _1, _2), - boost::bind(&AsynchIOHandler::nobuffs, async, _1), - boost::bind(&AsynchIOHandler::idle, async, _1)); - } - - async->init(aio, 4); - aio->start(poller); -} - -uint16_t SslProtocolFactory::getPort() const { - return listeningPort; // Immutable no need for lock. -} - -std::string SslProtocolFactory::getHost() const { - return listener.getSockname(); -} - -void SslProtocolFactory::accept(sys::Poller::shared_ptr poller, - sys::ConnectionCodec::Factory* fact) { - acceptor.reset( - AsynchAcceptor::create(listener, - boost::bind(&SslProtocolFactory::established, this, poller, _1, fact, false))); - acceptor->start(poller); -} - -void SslProtocolFactory::connect(sys::Poller::shared_ptr poller, - const std::string& host, - int16_t port, - sys::ConnectionCodec::Factory* fact, - ConnectFailedCallback failed) -{ - SCHANNEL_CRED cred; - memset(&cred, 0, sizeof(cred)); - cred.dwVersion = SCHANNEL_CRED_VERSION; - SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL, - UNISP_NAME, - SECPKG_CRED_OUTBOUND, - NULL, - &cred, - NULL, - NULL, - &credHandle, - NULL); - if (status != SEC_E_OK) - throw QPID_WINDOWS_ERROR(status); - - brokerHost = host; - // Note that the following logic does not cause a memory leak. - // The allocated Socket is freed either by the AsynchConnector - // upon connection failure or by the AsynchIO upon connection - // shutdown. The allocated AsynchConnector frees itself when it - // is no longer needed. - qpid::sys::Socket* socket = new qpid::sys::Socket(); - connectFailedCallback = failed; - AsynchConnector::create(*socket, - host, - port, - boost::bind(&SslProtocolFactory::established, - this, poller, _1, fact, true), - boost::bind(&SslProtocolFactory::connectFailed, - this, _1, _2, _3)); -} - -namespace -{ -const std::string SSL = "ssl"; -} - -bool SslProtocolFactory::supports(const std::string& capability) -{ - std::string s = capability; - transform(s.begin(), s.end(), s.begin(), tolower); - return s == SSL; -} - -}}} // namespace qpid::sys::windows diff --git a/cpp/src/qpid/client/Bounds.cpp b/cpp/src/qpid/client/Bounds.cpp deleted file mode 100644 index cc2577d5fc..0000000000 --- a/cpp/src/qpid/client/Bounds.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Bounds.h" - -#include "qpid/log/Statement.h" -#include "qpid/sys/Waitable.h" - -namespace qpid { -namespace client { - -using sys::Waitable; - -Bounds::Bounds(size_t maxSize) : max(maxSize), current(0) {} - -bool Bounds::expand(size_t sizeRequired, bool block) { - if (!max) return true; - Waitable::ScopedLock l(lock); - if (block) { - Waitable::ScopedWait w(lock); - while (current + sizeRequired > max) - lock.wait(); - } - current += sizeRequired; - return current <= max; -} - -void Bounds::reduce(size_t size) { - if (!max || size == 0) return; - Waitable::ScopedLock l(lock); - assert(current >= size); - current -= std::min(size, current); - if (current < max && lock.hasWaiters()) { - lock.notifyAll(); - } -} - -size_t Bounds::getCurrentSize() { - Waitable::ScopedLock l(lock); - return current; -} - -std::ostream& operator<<(std::ostream& out, const Bounds& bounds) { - out << "current=" << bounds.current << ", max=" << bounds.max << " [" << &bounds << "]"; - return out; -} - -void Bounds::setException(const sys::ExceptionHolder& e) { - Waitable::ScopedLock l(lock); - lock.setException(e); - lock.waitWaiters(); // Wait for waiting threads to exit. -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Bounds.h b/cpp/src/qpid/client/Bounds.h deleted file mode 100644 index 838fcb8368..0000000000 --- a/cpp/src/qpid/client/Bounds.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef QPID_CLIENT_BOUNDSCHECKING_H -#define QPID_CLIENT_BOUNDSCHECKING_H -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Waitable.h" - -namespace qpid{ -namespace client{ - -class Bounds -{ - public: - Bounds(size_t maxSize); - bool expand(size_t, bool block); - void reduce(size_t); - size_t getCurrentSize(); - void setException(const sys::ExceptionHolder&); - - private: - friend std::ostream& operator<<(std::ostream&, const Bounds&); - sys::Waitable lock; - const size_t max; - size_t current; -}; - -std::ostream& operator<<(std::ostream&, const Bounds&); - - -}} - -#endif diff --git a/cpp/src/qpid/client/ChainableFrameHandler.h b/cpp/src/qpid/client/ChainableFrameHandler.h deleted file mode 100644 index 29e16d53dc..0000000000 --- a/cpp/src/qpid/client/ChainableFrameHandler.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _ChainableFrameHandler_ -#define _ChainableFrameHandler_ - -#include <boost/function.hpp> -#include "qpid/framing/AMQFrame.h" - -namespace qpid { -namespace client { - -struct ChainableFrameHandler -{ - typedef boost::function<void(framing::AMQFrame&)> FrameDelegate; - - FrameDelegate in; - FrameDelegate out; - - ChainableFrameHandler() {} - ChainableFrameHandler(FrameDelegate i, FrameDelegate o): in(i), out(o) {} - virtual ~ChainableFrameHandler() {} -}; - -}} - - - -#endif diff --git a/cpp/src/qpid/client/Completion.cpp b/cpp/src/qpid/client/Completion.cpp deleted file mode 100644 index a97c8c3534..0000000000 --- a/cpp/src/qpid/client/Completion.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Completion.h" -#include "qpid/client/CompletionImpl.h" -#include "qpid/client/PrivateImplRef.h" - -namespace qpid { -namespace client { - -typedef PrivateImplRef<Completion> PI; -Completion::Completion(CompletionImpl* p) { PI::ctor(*this, p); } -Completion::Completion(const Completion& c) : Handle<CompletionImpl>() { PI::copy(*this, c); } -Completion::~Completion() { PI::dtor(*this); } -Completion& Completion::operator=(const Completion& c) { return PI::assign(*this, c); } - - -void Completion::wait() { impl->wait(); } -bool Completion::isComplete() { return impl->isComplete(); } -std::string Completion::getResult() { return impl->getResult(); } - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/CompletionImpl.h b/cpp/src/qpid/client/CompletionImpl.h deleted file mode 100644 index f180708316..0000000000 --- a/cpp/src/qpid/client/CompletionImpl.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef QPID_CLIENT_COMPLETIONIMPL_H -#define QPID_CLIENT_COMPLETIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qpid/client/Future.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace client { - -///@internal -class CompletionImpl : public RefCounted -{ -public: - CompletionImpl() {} - CompletionImpl(Future f, boost::shared_ptr<SessionImpl> s) : future(f), session(s) {} - - bool isComplete() { return future.isComplete(*session); } - void wait() { future.wait(*session); } - std::string getResult() { return future.getResult(*session); } - -protected: - Future future; - boost::shared_ptr<SessionImpl> session; -}; - -}} // namespace qpid::client - - -#endif /*!QPID_CLIENT_COMPLETIONIMPL_H*/ diff --git a/cpp/src/qpid/client/Connection.cpp b/cpp/src/qpid/client/Connection.cpp deleted file mode 100644 index 2882ef5d42..0000000000 --- a/cpp/src/qpid/client/Connection.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/client/Message.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/Url.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/AMQP_HighestVersion.h" - -#include <algorithm> -#include <iostream> -#include <sstream> -#include <functional> -#include <boost/format.hpp> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> - -using namespace qpid::framing; -using namespace qpid::sys; - - -namespace qpid { -namespace client { - -Connection::Connection() : version(framing::highestProtocolVersion) -{ - ConnectionImpl::init(); -} - -Connection::~Connection() {} - -void Connection::open( - const Url& url, - const std::string& uid, const std::string& pwd, - const std::string& vhost, - uint16_t maxFrameSize) -{ - ConnectionSettings settings; - settings.username = uid; - settings.password = pwd; - settings.virtualhost = vhost; - settings.maxFrameSize = maxFrameSize; - open(url, settings); -} - -void Connection::open(const Url& url, const ConnectionSettings& settings) { - if (url.empty()) - throw Exception(QPID_MSG("Attempt to open URL with no addresses.")); - Url::const_iterator i = url.begin(); - do { - const Address& addr = *i; - i++; - try { - ConnectionSettings cs(settings); - cs.protocol = addr.protocol; - cs.host = addr.host; - cs.port = addr.port; - open(cs); - break; - } - catch (const Exception& /*e*/) { - if (i == url.end()) throw; - } - } while (i != url.end()); -} - -void Connection::open( - const std::string& host, int port, - const std::string& uid, const std::string& pwd, - const std::string& vhost, - uint16_t maxFrameSize) -{ - ConnectionSettings settings; - settings.host = host; - settings.port = port; - settings.username = uid; - settings.password = pwd; - settings.virtualhost = vhost; - settings.maxFrameSize = maxFrameSize; - open(settings); -} - -bool Connection::isOpen() const { - return impl && impl->isOpen(); -} - -void -Connection::registerFailureCallback ( boost::function<void ()> fn ) { - failureCallback = fn; - if ( impl ) - impl->registerFailureCallback ( fn ); -} - - - -void Connection::open(const ConnectionSettings& settings) -{ - if (isOpen()) - throw Exception(QPID_MSG("Connection::open() was already called")); - - impl = ConnectionImpl::create(version, settings); - impl->open(); - if ( failureCallback ) - impl->registerFailureCallback ( failureCallback ); -} - -const ConnectionSettings& Connection::getNegotiatedSettings() -{ - if (!isOpen()) - throw Exception(QPID_MSG("Connection is not open.")); - return impl->getNegotiatedSettings(); -} - -Session Connection::newSession(const std::string& name, uint32_t timeout) { - if (!isOpen()) - throw Exception(QPID_MSG("Connection has not yet been opened")); - Session s; - SessionBase_0_10Access(s).set(impl->newSession(name, timeout)); - return s; -} - -void Connection::resume(Session& session) { - if (!isOpen()) - throw Exception(QPID_MSG("Connection is not open.")); - impl->addSession(session.impl); - session.impl->resume(impl); -} - -void Connection::close() { - if ( impl ) - impl->close(); -} - -std::vector<Url> Connection::getInitialBrokers() { - return impl ? impl->getInitialBrokers() : std::vector<Url>(); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/ConnectionAccess.h b/cpp/src/qpid/client/ConnectionAccess.h deleted file mode 100644 index 3a763f692f..0000000000 --- a/cpp/src/qpid/client/ConnectionAccess.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_CLIENT_CONNECTIONACCESS_H -#define QPID_CLIENT_CONNECTIONACCESS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Connection.h" - -/**@file @internal Internal use only */ - -namespace qpid { -namespace client { - - - -struct ConnectionAccess { - static void setVersion(Connection& c, const framing::ProtocolVersion& v) { c.version = v; } - static boost::shared_ptr<ConnectionImpl> getImpl(Connection& c) { return c.impl; } - static void setImpl(Connection& c, boost::shared_ptr<ConnectionImpl> i) { c.impl = i; } -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_CONNECTIONACCESS_H*/ diff --git a/cpp/src/qpid/client/ConnectionHandler.cpp b/cpp/src/qpid/client/ConnectionHandler.cpp deleted file mode 100644 index 4fbf55aa60..0000000000 --- a/cpp/src/qpid/client/ConnectionHandler.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ConnectionHandler.h" - -#include "qpid/SaslFactory.h" -#include "qpid/StringUtils.h" -#include "qpid/client/Bounds.h" -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/ClientInvoker.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Helpers.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SystemInfo.h" - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::framing::connection; -using qpid::sys::SecurityLayer; -using qpid::sys::Duration; -using qpid::sys::TimerTask; -using qpid::sys::Timer; -using qpid::sys::AbsTime; -using qpid::sys::TIME_SEC; -using qpid::sys::ScopedLock; -using qpid::sys::Mutex; - -namespace { -const std::string OK("OK"); -const std::string PLAIN("PLAIN"); -const std::string en_US("en_US"); - -const std::string INVALID_STATE_START("start received in invalid state"); -const std::string INVALID_STATE_TUNE("tune received in invalid state"); -const std::string INVALID_STATE_OPEN_OK("open-ok received in invalid state"); -const std::string INVALID_STATE_CLOSE_OK("close-ok received in invalid state"); - -const std::string SESSION_FLOW_CONTROL("qpid.session_flow"); -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -const std::string CLIENT_PPID("qpid.client_ppid"); -const int SESSION_FLOW_CONTROL_VER = 1; -} - -CloseCode ConnectionHandler::convert(uint16_t replyCode) -{ - switch (replyCode) { - case 200: return CLOSE_CODE_NORMAL; - case 320: return CLOSE_CODE_CONNECTION_FORCED; - case 402: return CLOSE_CODE_INVALID_PATH; - case 501: default: - return CLOSE_CODE_FRAMING_ERROR; - } -} - -ConnectionHandler::Adapter::Adapter(ConnectionHandler& h, Bounds& b) : handler(h), bounds(b) {} -void ConnectionHandler::Adapter::handle(qpid::framing::AMQFrame& f) -{ - bounds.expand(f.encodedSize(), false); - handler.out(f); -} - -ConnectionHandler::ConnectionHandler(const ConnectionSettings& s, ProtocolVersion& v, Bounds& b) - : StateManager(NOT_STARTED), ConnectionSettings(s), outHandler(*this, b), proxy(outHandler), - errorCode(CLOSE_CODE_NORMAL), version(v) -{ - insist = true; - - ESTABLISHED.insert(FAILED); - ESTABLISHED.insert(CLOSED); - ESTABLISHED.insert(OPEN); - - FINISHED.insert(FAILED); - FINISHED.insert(CLOSED); - - properties.setInt(SESSION_FLOW_CONTROL, SESSION_FLOW_CONTROL_VER); - properties.setString(CLIENT_PROCESS_NAME, sys::SystemInfo::getProcessName()); - properties.setInt(CLIENT_PID, sys::SystemInfo::getProcessId()); - properties.setInt(CLIENT_PPID, sys::SystemInfo::getParentProcessId()); -} - -void ConnectionHandler::incoming(AMQFrame& frame) -{ - if (getState() == CLOSED) { - throw Exception("Received frame on closed connection"); - } - - if (rcvTimeoutTask) { - // Received frame on connection so delay timeout - rcvTimeoutTask->restart(); - } - - AMQBody* body = frame.getBody(); - try { - if (frame.getChannel() != 0 || !invoke(static_cast<ConnectionOperations&>(*this), *body)) { - switch(getState()) { - case OPEN: - in(frame); - break; - case CLOSING: - QPID_LOG(warning, "Ignoring frame while closing connection: " << frame); - break; - default: - throw Exception("Cannot receive frames on non-zero channel until connection is established."); - } - } - }catch(std::exception& e){ - QPID_LOG(warning, "Closing connection due to " << e.what()); - setState(CLOSING); - errorCode = CLOSE_CODE_FRAMING_ERROR; - errorText = e.what(); - proxy.close(501, e.what()); - } -} - -void ConnectionHandler::outgoing(AMQFrame& frame) -{ - if (getState() == OPEN) - out(frame); - else - throw TransportFailure(errorText.empty() ? "Connection is not open." : errorText); -} - -void ConnectionHandler::waitForOpen() -{ - waitFor(ESTABLISHED); - if (getState() == FAILED || getState() == CLOSED) { - throw ConnectionException(errorCode, errorText); - } -} - -void ConnectionHandler::close() -{ - switch (getState()) { - case NEGOTIATING: - case OPENING: - fail("Connection closed before it was established"); - break; - case OPEN: - if (setState(CLOSING, OPEN)) { - proxy.close(200, OK); - if (ConnectionSettings::heartbeat) { - //heartbeat timer is turned off at this stage, so don't wait indefinately - if (!waitFor(FINISHED, qpid::sys::Duration(ConnectionSettings::heartbeat * qpid::sys::TIME_SEC))) { - QPID_LOG(warning, "Connection close timed out"); - } - } else { - waitFor(FINISHED);//FINISHED = CLOSED or FAILED - } - } - //else, state was changed from open after we checked, can only - //change to failed or closed, so nothing to do - break; - - // Nothing to do if already CLOSING, CLOSED, FAILED or if NOT_STARTED - } -} - -void ConnectionHandler::heartbeat() -{ - // Do nothing - the purpose of heartbeats is just to make sure that there is some - // traffic on the connection within the heart beat interval, we check for the - // traffic and don't need to do anything in response to heartbeats - - // Although the above is still true we're now using a received heartbeat as a trigger - // to send out our own heartbeat - proxy.heartbeat(); -} - -void ConnectionHandler::checkState(STATES s, const std::string& msg) -{ - if (getState() != s) { - throw CommandInvalidException(msg); - } -} - -void ConnectionHandler::fail(const std::string& message) -{ - errorCode = CLOSE_CODE_FRAMING_ERROR; - errorText = message; - QPID_LOG(warning, message); - setState(FAILED); -} - -namespace { -std::string SPACE(" "); - -std::string join(const std::vector<std::string>& in) -{ - std::string result; - for (std::vector<std::string>::const_iterator i = in.begin(); i != in.end(); ++i) { - if (result.size()) result += SPACE; - result += *i; - } - return result; -} - -void intersection(const std::vector<std::string>& a, const std::vector<std::string>& b, std::vector<std::string>& results) -{ - for (std::vector<std::string>::const_iterator i = a.begin(); i != a.end(); ++i) { - if (std::find(b.begin(), b.end(), *i) != b.end()) results.push_back(*i); - } -} - -} - -void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& mechanisms, const Array& /*locales*/) -{ - checkState(NOT_STARTED, INVALID_STATE_START); - setState(NEGOTIATING); - sasl = SaslFactory::getInstance().create( username, - password, - service, - host, - minSsf, - maxSsf - ); - - std::vector<std::string> mechlist; - if (mechanism.empty()) { - //mechlist is simply what the server offers - mechanisms.collect(mechlist); - } else { - //mechlist is the intersection of those indicated by user and - //those supported by server, in the order listed by user - std::vector<std::string> allowed = split(mechanism, " "); - std::vector<std::string> supported; - mechanisms.collect(supported); - intersection(allowed, supported, mechlist); - if (mechlist.empty()) { - throw Exception(QPID_MSG("Desired mechanism(s) not valid: " << mechanism << " (supported: " << join(supported) << ")")); - } - } - - if (sasl.get()) { - string response = sasl->start(join(mechlist), getSecuritySettings ? getSecuritySettings() : 0); - proxy.startOk(properties, sasl->getMechanism(), response, locale); - } else { - //TODO: verify that desired mechanism and locale are supported - string response = ((char)0) + username + ((char)0) + password; - proxy.startOk(properties, mechanism, response, locale); - } -} - -void ConnectionHandler::secure(const std::string& challenge) -{ - if (sasl.get()) { - string response = sasl->step(challenge); - proxy.secureOk(response); - } else { - throw NotImplementedException("Challenge-response cycle not yet implemented in client"); - } -} - -void ConnectionHandler::tune(uint16_t maxChannelsProposed, uint16_t maxFrameSizeProposed, - uint16_t heartbeatMin, uint16_t heartbeatMax) -{ - checkState(NEGOTIATING, INVALID_STATE_TUNE); - maxChannels = std::min(maxChannels, maxChannelsProposed); - maxFrameSize = std::min(maxFrameSize, maxFrameSizeProposed); - // Clip the requested heartbeat to the maximum/minimum offered - uint16_t heartbeat = ConnectionSettings::heartbeat; - heartbeat = heartbeat < heartbeatMin ? heartbeatMin : - heartbeat > heartbeatMax ? heartbeatMax : - heartbeat; - ConnectionSettings::heartbeat = heartbeat; - proxy.tuneOk(maxChannels, maxFrameSize, heartbeat); - setState(OPENING); - proxy.open(virtualhost, capabilities, insist); -} - -void ConnectionHandler::openOk ( const Array& knownBrokers ) -{ - checkState(OPENING, INVALID_STATE_OPEN_OK); - knownBrokersUrls.clear(); - framing::Array::ValueVector::const_iterator i; - for ( i = knownBrokers.begin(); i != knownBrokers.end(); ++i ) - knownBrokersUrls.push_back(Url((*i)->get<std::string>())); - if (sasl.get()) { - securityLayer = sasl->getSecurityLayer(maxFrameSize); - operUserId = sasl->getUserId(); - } - setState(OPEN); - QPID_LOG(debug, "Known-brokers for connection: " << log::formatList(knownBrokersUrls)); -} - - -void ConnectionHandler::redirect(const std::string& /*host*/, const Array& /*knownHosts*/) -{ - throw NotImplementedException("Redirection received from broker; not yet implemented in client"); -} - -void ConnectionHandler::close(uint16_t replyCode, const std::string& replyText) -{ - proxy.closeOk(); - errorCode = convert(replyCode); - errorText = replyText; - setState(CLOSED); - QPID_LOG(warning, "Broker closed connection: " << replyCode << ", " << replyText); - if (onError) { - onError(replyCode, replyText); - } -} - -void ConnectionHandler::closeOk() -{ - checkState(CLOSING, INVALID_STATE_CLOSE_OK); - if (onError && errorCode != CLOSE_CODE_NORMAL) { - onError(errorCode, errorText); - } else if (onClose) { - onClose(); - } - setState(CLOSED); -} - -bool ConnectionHandler::isOpen() const -{ - return getState() == OPEN; -} - -bool ConnectionHandler::isClosed() const -{ - int s = getState(); - return s == CLOSED || s == FAILED; -} - -bool ConnectionHandler::isClosing() const { return getState() == CLOSING; } - -std::auto_ptr<qpid::sys::SecurityLayer> ConnectionHandler::getSecurityLayer() -{ - return securityLayer; -} - -void ConnectionHandler::setRcvTimeoutTask(boost::intrusive_ptr<qpid::sys::TimerTask> t) -{ - rcvTimeoutTask = t; -} diff --git a/cpp/src/qpid/client/ConnectionHandler.h b/cpp/src/qpid/client/ConnectionHandler.h deleted file mode 100644 index 6af2e987fb..0000000000 --- a/cpp/src/qpid/client/ConnectionHandler.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionHandler_ -#define _ConnectionHandler_ - -#include "qpid/client/ChainableFrameHandler.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/Sasl.h" -#include "qpid/client/StateManager.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/AMQP_ClientOperations.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/InputHandler.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/Timer.h" -#include "qpid/Url.h" -#include <memory> - -namespace qpid { - -namespace sys { -struct SecuritySettings; -} - -namespace client { - -class Bounds; - -class ConnectionHandler : private StateManager, - public ConnectionSettings, - public ChainableFrameHandler, - public framing::InputHandler, - private framing::AMQP_ClientOperations::ConnectionHandler -{ - typedef framing::AMQP_ClientOperations::ConnectionHandler ConnectionOperations; - enum STATES {NOT_STARTED, NEGOTIATING, OPENING, OPEN, CLOSING, CLOSED, FAILED}; - std::set<int> ESTABLISHED, FINISHED; - - class Adapter : public framing::FrameHandler - { - ConnectionHandler& handler; - Bounds& bounds; - public: - Adapter(ConnectionHandler& h, Bounds& bounds); - void handle(framing::AMQFrame& f); - }; - - Adapter outHandler; - framing::AMQP_ServerProxy::Connection proxy; - framing::connection::CloseCode errorCode; - std::string errorText; - bool insist; - framing::ProtocolVersion version; - framing::Array capabilities; - framing::FieldTable properties; - std::auto_ptr<Sasl> sasl; - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; - boost::intrusive_ptr<qpid::sys::TimerTask> rcvTimeoutTask; - std::string operUserId; - - void checkState(STATES s, const std::string& msg); - - //methods corresponding to connection controls: - void start(const framing::FieldTable& serverProperties, - const framing::Array& mechanisms, - const framing::Array& locales); - void secure(const std::string& challenge); - void tune(uint16_t channelMax, - uint16_t frameMax, - uint16_t heartbeatMin, - uint16_t heartbeatMax); - void openOk(const framing::Array& knownHosts); - void redirect(const std::string& host, - const framing::Array& knownHosts); - void close(uint16_t replyCode, const std::string& replyText); - void closeOk(); - void heartbeat(); - -public: - using InputHandler::handle; - typedef boost::function<void()> CloseListener; - typedef boost::function<void(uint16_t, const std::string&)> ErrorListener; - typedef boost::function<const qpid::sys::SecuritySettings*()> GetSecuritySettings; - - ConnectionHandler(const ConnectionSettings&, framing::ProtocolVersion&, Bounds&); - - void received(framing::AMQFrame& f) { incoming(f); } - - void incoming(framing::AMQFrame& frame); - void outgoing(framing::AMQFrame& frame); - - void waitForOpen(); - void close(); - void fail(const std::string& message); - - // Note that open and closed aren't related by open = !closed - bool isOpen() const; - bool isClosed() const; - bool isClosing() const; - - std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(); - void setRcvTimeoutTask(boost::intrusive_ptr<qpid::sys::TimerTask>); - - CloseListener onClose; - ErrorListener onError; - - std::vector<Url> knownBrokersUrls; - - static framing::connection::CloseCode convert(uint16_t replyCode); - const std::string& getUserId() const { return operUserId; } - GetSecuritySettings getSecuritySettings; /** query the transport for its security details */ -}; - -}} - -#endif diff --git a/cpp/src/qpid/client/ConnectionImpl.cpp b/cpp/src/qpid/client/ConnectionImpl.cpp deleted file mode 100644 index 40c004f166..0000000000 --- a/cpp/src/qpid/client/ConnectionImpl.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ConnectionImpl.h" - -#include "qpid/client/LoadPlugins.h" -#include "qpid/client/Connector.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/client/SessionImpl.h" - -#include "qpid/log/Statement.h" -#include "qpid/Url.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/Options.h" - -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <boost/shared_ptr.hpp> - -#include <limits> -#include <vector> - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -namespace qpid { -namespace client { - -using namespace qpid::framing; -using namespace qpid::framing::connection; -using namespace qpid::sys; -using namespace qpid::framing::connection;//for connection error codes - -namespace { -// Maybe should amalgamate the singletons into a single client singleton - -// Get timer singleton -Timer& theTimer() { - static Mutex timerInitLock; - ScopedLock<Mutex> l(timerInitLock); - - static qpid::sys::Timer t; - return t; -} - -struct IOThreadOptions : public qpid::Options { - int maxIOThreads; - - IOThreadOptions(int c) : - Options("IO threading options"), - maxIOThreads(c) - { - addOptions() - ("max-iothreads", optValue(maxIOThreads, "N"), "Maximum number of io threads to use"); - } -}; - -// IO threads -class IOThread { - int maxIOThreads; - int ioThreads; - int connections; - Mutex threadLock; - std::vector<Thread> t; - Poller::shared_ptr poller_; - -public: - void add() { - ScopedLock<Mutex> l(threadLock); - ++connections; - if (!poller_) - poller_.reset(new Poller); - if (ioThreads < connections && ioThreads < maxIOThreads) { - QPID_LOG(debug, "Created IO thread: " << ioThreads); - ++ioThreads; - t.push_back( Thread(poller_.get()) ); - } - } - - void sub() { - ScopedLock<Mutex> l(threadLock); - --connections; - } - - Poller::shared_ptr poller() const { - assert(poller_); - return poller_; - } - - // Here is where the maximum number of threads is set - IOThread(int c) : - ioThreads(0), - connections(0) - { - IOThreadOptions options(c); - options.parse(0, 0, QPIDC_CONF_FILE, true); - maxIOThreads = (options.maxIOThreads != -1) ? - options.maxIOThreads : 1; - } - - // We can't destroy threads one-by-one as the only - // control we have is to shutdown the whole lot - // and we can't do that before we're unloaded as we can't - // restart the Poller after shutting it down - ~IOThread() { - std::vector<Thread> threads; - { - ScopedLock<Mutex> l(threadLock); - if (poller_) - poller_->shutdown(); - t.swap(threads); - } - for (std::vector<Thread>::iterator i = threads.begin(); i != threads.end(); ++i) { - i->join(); - } - } -}; - -IOThread& theIO() { - static IOThread io(SystemInfo::concurrency()); - return io; -} - -class HeartbeatTask : public TimerTask { - TimeoutHandler& timeout; - - void fire() { - // If we ever get here then we have timed out - QPID_LOG(debug, "Traffic timeout"); - timeout.idleIn(); - } - -public: - HeartbeatTask(Duration p, TimeoutHandler& t) : - TimerTask(p,"Heartbeat"), - timeout(t) - {} -}; - -} - -void ConnectionImpl::init() { - // Ensure that the plugin modules have been loaded - // This will make sure that any plugin protocols are available - theModuleLoader(); - - // Ensure the IO threads exist: - // This needs to be called in the Connection constructor - // so that they will still exist at last connection destruction - (void) theIO(); -} - -boost::shared_ptr<ConnectionImpl> ConnectionImpl::create(framing::ProtocolVersion version, const ConnectionSettings& settings) -{ - boost::shared_ptr<ConnectionImpl> instance(new ConnectionImpl(version, settings), boost::bind(&ConnectionImpl::release, _1)); - return instance; -} - -ConnectionImpl::ConnectionImpl(framing::ProtocolVersion v, const ConnectionSettings& settings) - : Bounds(settings.maxFrameSize * settings.bounds), - handler(settings, v, *this), - version(v), - nextChannel(1), - shutdownComplete(false), - released(false) -{ - handler.in = boost::bind(&ConnectionImpl::incoming, this, _1); - handler.out = boost::bind(&Connector::send, boost::ref(connector), _1); - handler.onClose = boost::bind(&ConnectionImpl::closed, this, - CLOSE_CODE_NORMAL, std::string()); - //only set error handler once open - handler.onError = boost::bind(&ConnectionImpl::closed, this, _1, _2); - handler.getSecuritySettings = boost::bind(&Connector::getSecuritySettings, boost::ref(connector)); -} - -const uint16_t ConnectionImpl::NEXT_CHANNEL = std::numeric_limits<uint16_t>::max(); - -ConnectionImpl::~ConnectionImpl() { - if (heartbeatTask) heartbeatTask->cancel(); - theIO().sub(); -} - -void ConnectionImpl::addSession(const boost::shared_ptr<SessionImpl>& session, uint16_t channel) -{ - Mutex::ScopedLock l(lock); - for (uint16_t i = 0; i < NEXT_CHANNEL; i++) { //will at most search through channels once - uint16_t c = channel == NEXT_CHANNEL ? nextChannel++ : channel; - boost::weak_ptr<SessionImpl>& s = sessions[c]; - boost::shared_ptr<SessionImpl> ss = s.lock(); - if (!ss) { - //channel is free, we can assign it to this session - session->setChannel(c); - s = session; - return; - } else if (channel != NEXT_CHANNEL) { - //channel is taken and was requested explicitly so don't look for another - throw SessionBusyException(QPID_MSG("Channel " << ss->getChannel() << " attached to " << ss->getId())); - } //else channel is busy, but we can keep looking for a free one - } - // If we get here, we didn't find any available channel. - throw ResourceLimitExceededException("There are no channels available"); -} - -void ConnectionImpl::handle(framing::AMQFrame& frame) -{ - handler.outgoing(frame); -} - -void ConnectionImpl::incoming(framing::AMQFrame& frame) -{ - boost::shared_ptr<SessionImpl> s; - { - Mutex::ScopedLock l(lock); - s = sessions[frame.getChannel()].lock(); - } - if (!s) { - QPID_LOG(info, *this << " dropping frame received on invalid channel: " << frame); - } else { - s->in(frame); - } -} - -bool ConnectionImpl::isOpen() const -{ - return handler.isOpen(); -} - -void ConnectionImpl::open() -{ - const std::string& protocol = handler.protocol; - const std::string& host = handler.host; - int port = handler.port; - - theIO().add(); - connector.reset(Connector::create(protocol, theIO().poller(), version, handler, this)); - connector->setInputHandler(&handler); - connector->setShutdownHandler(this); - try { - connector->connect(host, port); - - } catch (const std::exception& e) { - QPID_LOG(debug, "Failed to connect to " << protocol << ":" << host << ":" << port << " " << e.what()); - connector.reset(); - throw; - } - connector->init(); - QPID_LOG(info, *this << " connected to " << protocol << ":" << host << ":" << port); - - // Enable heartbeat if requested - uint16_t heartbeat = static_cast<ConnectionSettings&>(handler).heartbeat; - if (heartbeat) { - // Set connection timeout to be 2x heart beat interval and setup timer - heartbeatTask = new HeartbeatTask(heartbeat * 2 * TIME_SEC, *this); - handler.setRcvTimeoutTask(heartbeatTask); - theTimer().add(heartbeatTask); - } - - // If the connect fails then the connector is cleaned up either when we try to connect again - // - in that case in connector.reset() above; - // - or when we are deleted - handler.waitForOpen(); - - // If the SASL layer has provided an "operational" userId for the connection, - // put it in the negotiated settings. - const std::string& userId(handler.getUserId()); - if (!userId.empty()) - handler.username = userId; - - //enable security layer if one has been negotiated: - std::auto_ptr<SecurityLayer> securityLayer = handler.getSecurityLayer(); - if (securityLayer.get()) { - QPID_LOG(debug, *this << " activating security layer"); - connector->activateSecurityLayer(securityLayer); - } else { - QPID_LOG(debug, *this << " no security layer in place"); - } -} - -void ConnectionImpl::idleIn() -{ - connector->abort(); -} - -void ConnectionImpl::idleOut() -{ - AMQFrame frame((AMQHeartbeatBody())); - connector->send(frame); -} - -void ConnectionImpl::close() -{ - if (heartbeatTask) - heartbeatTask->cancel(); - // close() must be idempotent and no-throw as it will often be called in destructors. - if (handler.isOpen()) { - try { - handler.close(); - closed(CLOSE_CODE_NORMAL, "Closed by client"); - } catch (...) {} - } - assert(!handler.isOpen()); -} - - -template <class F> void ConnectionImpl::closeInternal(const F& f) { - if (heartbeatTask) { - heartbeatTask->cancel(); - } - { - Mutex::ScopedUnlock u(lock); - connector->close(); - } - //notifying sessions of failure can result in those session being - //deleted which in turn results in a call to erase(); this can - //even happen on this thread, when 's' goes out of scope - //below. Using a copy prevents the map being modified as we - //iterate through. - SessionMap copy; - sessions.swap(copy); - for (SessionMap::iterator i = copy.begin(); i != copy.end(); ++i) { - boost::shared_ptr<SessionImpl> s = i->second.lock(); - if (s) f(s); - } -} - -void ConnectionImpl::closed(uint16_t code, const std::string& text) { - Mutex::ScopedLock l(lock); - setException(new ConnectionException(ConnectionHandler::convert(code), text)); - closeInternal(boost::bind(&SessionImpl::connectionClosed, _1, code, text)); -} - -void ConnectionImpl::shutdown() { - if (!handler.isClosed()) { - failedConnection(); - } - bool canDelete; - { - Mutex::ScopedLock l(lock); - //association with IO thread is now ended - shutdownComplete = true; - //If we have already been released, we can now delete ourselves - canDelete = released; - } - if (canDelete) delete this; -} - -void ConnectionImpl::release() { - bool isActive; - { - Mutex::ScopedLock l(lock); - isActive = connector && !shutdownComplete; - } - //If we are still active - i.e. associated with an IO thread - - //then we cannot delete ourselves yet, but must wait for the - //shutdown callback which we can trigger by calling - //connector.close() - if (isActive) { - connector->close(); - bool canDelete; - { - Mutex::ScopedLock l(lock); - released = true; - canDelete = shutdownComplete; - } - if (canDelete) delete this; - } else { - delete this; - } -} - -static const std::string CONN_CLOSED("Connection closed"); - -void ConnectionImpl::failedConnection() { - if ( failureCallback ) - failureCallback(); - - if (handler.isClosed()) return; - - bool isClosing = handler.isClosing(); - bool isOpen = handler.isOpen(); - - std::ostringstream msg; - msg << *this << " closed"; - - // FIXME aconway 2008-06-06: exception use, amqp0-10 does not seem to have - // an appropriate close-code. connection-forced is not right. - handler.fail(msg.str());//ensure connection is marked as failed before notifying sessions - - // At this point if the object isn't open and isn't closing it must have failed to open - // so we can't do the rest of the cleanup - if (!isClosing && !isOpen) return; - - Mutex::ScopedLock l(lock); - closeInternal(boost::bind(&SessionImpl::connectionBroke, _1, msg.str())); - setException(new TransportFailure(msg.str())); -} - -void ConnectionImpl::erase(uint16_t ch) { - Mutex::ScopedLock l(lock); - sessions.erase(ch); -} - -const ConnectionSettings& ConnectionImpl::getNegotiatedSettings() -{ - return handler; -} - -std::vector<qpid::Url> ConnectionImpl::getInitialBrokers() { - return handler.knownBrokersUrls; -} - -boost::shared_ptr<SessionImpl> ConnectionImpl::newSession(const std::string& name, uint32_t timeout, uint16_t channel) { - boost::shared_ptr<SessionImpl> simpl(new SessionImpl(name, shared_from_this())); - addSession(simpl, channel); - simpl->open(timeout); - return simpl; -} - -std::ostream& operator<<(std::ostream& o, const ConnectionImpl& c) { - if (c.connector) - return o << "Connection " << c.connector->getIdentifier(); - else - return o << "Connection <not connected>"; -} - - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/ConnectionImpl.h b/cpp/src/qpid/client/ConnectionImpl.h deleted file mode 100644 index cc81500b18..0000000000 --- a/cpp/src/qpid/client/ConnectionImpl.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _ConnectionImpl_ -#define _ConnectionImpl_ - -#include "qpid/client/Bounds.h" -#include "qpid/client/ConnectionHandler.h" - -#include "qpid/framing/FrameHandler.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/ShutdownHandler.h" -#include "qpid/sys/TimeoutHandler.h" - -#include <map> -#include <iosfwd> -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> -#include <boost/scoped_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> - -namespace qpid { -namespace client { - -class Connector; -struct ConnectionSettings; -class SessionImpl; - -class ConnectionImpl : public Bounds, - public framing::FrameHandler, - public sys::TimeoutHandler, - public sys::ShutdownHandler, - public boost::enable_shared_from_this<ConnectionImpl> -{ - typedef std::map<uint16_t, boost::weak_ptr<SessionImpl> > SessionMap; - - static const uint16_t NEXT_CHANNEL; - - SessionMap sessions; - ConnectionHandler handler; - boost::scoped_ptr<Connector> connector; - framing::ProtocolVersion version; - uint16_t nextChannel; - sys::Mutex lock; - bool shutdownComplete; - bool released; - - boost::intrusive_ptr<qpid::sys::TimerTask> heartbeatTask; - - template <class F> void closeInternal(const F&); - - void incoming(framing::AMQFrame& frame); - void closed(uint16_t, const std::string&); - void idleOut(); - void idleIn(); - void shutdown(); - void failedConnection(); - void release(); - ConnectionImpl(framing::ProtocolVersion version, const ConnectionSettings& settings); - - boost::function<void ()> failureCallback; - - public: - static void init(); - static boost::shared_ptr<ConnectionImpl> create(framing::ProtocolVersion version, const ConnectionSettings& settings); - ~ConnectionImpl(); - - void open(); - bool isOpen() const; - - boost::shared_ptr<SessionImpl> newSession(const std::string& name, uint32_t timeout, uint16_t channel=NEXT_CHANNEL); - void addSession(const boost::shared_ptr<SessionImpl>&, uint16_t channel=NEXT_CHANNEL); - - void close(); - void handle(framing::AMQFrame& frame); - void erase(uint16_t channel); - const ConnectionSettings& getNegotiatedSettings(); - - std::vector<Url> getInitialBrokers(); - void registerFailureCallback ( boost::function<void ()> fn ) { failureCallback = fn; } - framing::ProtocolVersion getVersion() { return version; } - - friend std::ostream& operator<<(std::ostream&, const ConnectionImpl&); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/client/ConnectionSettings.cpp b/cpp/src/qpid/client/ConnectionSettings.cpp deleted file mode 100644 index 822e4af269..0000000000 --- a/cpp/src/qpid/client/ConnectionSettings.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/ConnectionSettings.h" - -#include "qpid/log/Logger.h" -#include "qpid/sys/Socket.h" -#include "qpid/Url.h" -#include "qpid/Version.h" - -namespace qpid { -namespace client { - -ConnectionSettings::ConnectionSettings() : - protocol("tcp"), - host("localhost"), - port(5672), - locale("en_US"), - heartbeat(0), - maxChannels(32767), - maxFrameSize(65535), - bounds(2), - tcpNoDelay(false), - service(qpid::saslName), - minSsf(0), - maxSsf(256), - sslCertName("") -{} - -ConnectionSettings::~ConnectionSettings() {} - -void ConnectionSettings::configureSocket(qpid::sys::Socket& socket) const -{ - if (tcpNoDelay) { - socket.setTcpNoDelay(); - QPID_LOG(info, "Set TCP_NODELAY"); - } -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Connector.cpp b/cpp/src/qpid/client/Connector.cpp deleted file mode 100644 index c71dd9ecb6..0000000000 --- a/cpp/src/qpid/client/Connector.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Connector.h" -#include "qpid/Url.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SecurityLayer.h" - -#include <map> - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; - -namespace { - typedef std::map<std::string, Connector::Factory*> ProtocolRegistry; - - ProtocolRegistry& theProtocolRegistry() { - static ProtocolRegistry protocolRegistry; - - return protocolRegistry; - } -} - -Connector* Connector::create(const std::string& proto, - boost::shared_ptr<Poller> p, - framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) -{ - ProtocolRegistry::const_iterator i = theProtocolRegistry().find(proto); - if (i==theProtocolRegistry().end()) { - throw Exception(QPID_MSG("Unknown protocol: " << proto)); - } - return (i->second)(p, v, s, c); -} - -void Connector::registerFactory(const std::string& proto, Factory* connectorFactory) -{ - ProtocolRegistry::const_iterator i = theProtocolRegistry().find(proto); - if (i!=theProtocolRegistry().end()) { - QPID_LOG(error, "Tried to register protocol: " << proto << " more than once"); - } - theProtocolRegistry()[proto] = connectorFactory; - Url::addProtocol(proto); -} - -void Connector::activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>) -{ -} - - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Connector.h b/cpp/src/qpid/client/Connector.h deleted file mode 100644 index 586012f9d6..0000000000 --- a/cpp/src/qpid/client/Connector.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Connector_ -#define _Connector_ - - -#include "qpid/framing/OutputHandler.h" -#include "qpid/framing/ProtocolVersion.h" - -#include <boost/shared_ptr.hpp> - -#include <string> - -namespace qpid { - -namespace sys { -class ShutdownHandler; -class SecurityLayer; -class Poller; -struct SecuritySettings; -} - -namespace framing { -class InputHandler; -class AMQFrame; -} - -namespace client { - -struct ConnectionSettings; -class ConnectionImpl; - -///@internal -class Connector : public framing::OutputHandler -{ - public: - // Protocol connector factory related stuff (it might be better to separate this code from the TCP Connector in the future) - typedef Connector* Factory(boost::shared_ptr<qpid::sys::Poller>, - framing::ProtocolVersion, const ConnectionSettings&, ConnectionImpl*); - static Connector* create(const std::string& proto, - boost::shared_ptr<qpid::sys::Poller>, - framing::ProtocolVersion, const ConnectionSettings&, ConnectionImpl*); - static void registerFactory(const std::string& proto, Factory* connectorFactory); - - virtual ~Connector() {}; - virtual void connect(const std::string& host, int port) = 0; - virtual void init() {}; - virtual void close() = 0; - virtual void send(framing::AMQFrame& frame) = 0; - virtual void abort() = 0; - - virtual void setInputHandler(framing::InputHandler* handler) = 0; - virtual void setShutdownHandler(sys::ShutdownHandler* handler) = 0; - virtual sys::ShutdownHandler* getShutdownHandler() const = 0; - virtual framing::OutputHandler* getOutputHandler() = 0; - virtual const std::string& getIdentifier() const = 0; - - virtual void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>); - - virtual const qpid::sys::SecuritySettings* getSecuritySettings() = 0; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/client/Demux.cpp b/cpp/src/qpid/client/Demux.cpp deleted file mode 100644 index abc23c75df..0000000000 --- a/cpp/src/qpid/client/Demux.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Demux.h" -#include "qpid/Exception.h" -#include "qpid/framing/MessageTransferBody.h" - -#include <iostream> - -namespace qpid { -namespace client { - -ByTransferDest::ByTransferDest(const std::string& d) : dest(d) {} -bool ByTransferDest::operator()(const framing::FrameSet& frameset) const -{ - return frameset.isA<framing::MessageTransferBody>() && - frameset.as<framing::MessageTransferBody>()->getDestination() == dest; -} - -ScopedDivert::ScopedDivert(const std::string& _dest, Demux& _demuxer) : dest(_dest), demuxer(_demuxer) -{ - queue = demuxer.add(dest, ByTransferDest(dest)); -} - -ScopedDivert::~ScopedDivert() -{ - demuxer.remove(dest); -} - -Demux::Demux() : defaultQueue(new Queue()) {} - -Demux::~Demux() { close(sys::ExceptionHolder(new ClosedException())); } - -Demux::QueuePtr ScopedDivert::getQueue() -{ - return queue; -} - -void Demux::handle(framing::FrameSet::shared_ptr frameset) -{ - sys::Mutex::ScopedLock l(lock); - bool matched = false; - for (iterator i = records.begin(); i != records.end() && !matched; i++) { - if (i->condition && i->condition(*frameset)) { - matched = true; - i->queue->push(frameset); - } - } - if (!matched) { - defaultQueue->push(frameset); - } -} - -void Demux::close(const sys::ExceptionHolder& ex) -{ - sys::Mutex::ScopedLock l(lock); - for (iterator i = records.begin(); i != records.end(); i++) { - i->queue->close(ex); - } - defaultQueue->close(ex); -} - -void Demux::open() -{ - sys::Mutex::ScopedLock l(lock); - for (iterator i = records.begin(); i != records.end(); i++) { - i->queue->open(); - } - defaultQueue->open(); -} - -Demux::QueuePtr Demux::add(const std::string& name, Condition condition) -{ - sys::Mutex::ScopedLock l(lock); - iterator i = std::find_if(records.begin(), records.end(), Find(name)); - if (i == records.end()) { - Record r(name, condition); - records.push_back(r); - return r.queue; - } else { - throw Exception("Queue already exists for " + name); - } -} - -void Demux::remove(const std::string& name) -{ - sys::Mutex::ScopedLock l(lock); - records.remove_if(Find(name)); -} - -Demux::QueuePtr Demux::get(const std::string& name) -{ - sys::Mutex::ScopedLock l(lock); - iterator i = std::find_if(records.begin(), records.end(), Find(name)); - if (i == records.end()) { - throw Exception("No queue for " + name); - } - return i->queue; -} - -Demux::QueuePtr Demux::getDefault() -{ - return defaultQueue; -} - -Demux::Find::Find(const std::string& n) : name(n) {} - -bool Demux::Find::operator()(const Record& record) const -{ - return record.name == name; -} - -}} - diff --git a/cpp/src/qpid/client/Demux.h b/cpp/src/qpid/client/Demux.h deleted file mode 100644 index 31dc3f9c06..0000000000 --- a/cpp/src/qpid/client/Demux.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <list> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include "qpid/framing/FrameSet.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/client/ClientImportExport.h" - -#ifndef _Demux_ -#define _Demux_ - -namespace qpid { -namespace client { - -///@internal -class ByTransferDest -{ - const std::string dest; -public: - ByTransferDest(const std::string& dest); - bool operator()(const framing::FrameSet& frameset) const; -}; - -///@internal -class Demux -{ -public: - typedef boost::function<bool(const framing::FrameSet&)> Condition; - typedef sys::BlockingQueue<framing::FrameSet::shared_ptr> Queue; - typedef boost::shared_ptr<Queue> QueuePtr; - - QPID_CLIENT_EXTERN Demux(); - QPID_CLIENT_EXTERN ~Demux(); - - QPID_CLIENT_EXTERN void handle(framing::FrameSet::shared_ptr); - QPID_CLIENT_EXTERN void close(const sys::ExceptionHolder& ex); - QPID_CLIENT_EXTERN void open(); - - QPID_CLIENT_EXTERN QueuePtr add(const std::string& name, Condition); - QPID_CLIENT_EXTERN void remove(const std::string& name); - QPID_CLIENT_EXTERN QueuePtr get(const std::string& name); - QPID_CLIENT_EXTERN QueuePtr getDefault(); - -private: - struct Record - { - const std::string name; - Condition condition; - QueuePtr queue; - - Record(const std::string& n, Condition c) : name(n), condition(c), queue(new Queue()) {} - }; - - sys::Mutex lock; - std::list<Record> records; - QueuePtr defaultQueue; - - typedef std::list<Record>::iterator iterator; - - struct Find - { - const std::string name; - Find(const std::string& name); - bool operator()(const Record& record) const; - }; -}; - -class ScopedDivert -{ - const std::string dest; - Demux& demuxer; - Demux::QueuePtr queue; -public: - ScopedDivert(const std::string& dest, Demux& demuxer); - ~ScopedDivert(); - Demux::QueuePtr getQueue(); -}; - -}} // namespace qpid::client - - -#endif diff --git a/cpp/src/qpid/client/Dispatcher.cpp b/cpp/src/qpid/client/Dispatcher.cpp deleted file mode 100644 index a715c623bf..0000000000 --- a/cpp/src/qpid/client/Dispatcher.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Dispatcher.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/SessionImpl.h" - -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/client/Message.h" -#include "qpid/client/MessageImpl.h" - -#include <boost/version.hpp> -#if (BOOST_VERSION >= 104000) -# include <boost/serialization/state_saver.hpp> - using boost::serialization::state_saver; -#else -# include <boost/state_saver.hpp> - using boost::state_saver; -#endif /* BOOST_VERSION */ - -using qpid::framing::FrameSet; -using qpid::framing::MessageTransferBody; -using qpid::sys::Mutex; -using qpid::sys::ScopedLock; -using qpid::sys::Thread; - -namespace qpid { -namespace client { - -Dispatcher::Dispatcher(const Session& s, const std::string& q) - : session(s), - running(false), - autoStop(true), - failoverHandler(0) -{ - Demux& demux = SessionBase_0_10Access(session).get()->getDemux(); - queue = q.empty() ? demux.getDefault() : demux.get(q); -} - -void Dispatcher::start() -{ - worker = Thread(this); -} - -void Dispatcher::wait() -{ - worker.join(); -} - -void Dispatcher::run() -{ - Mutex::ScopedLock l(lock); - if (running) - throw Exception("Dispatcher is already running."); - state_saver<bool> reset(running); // Reset to false on exit. - running = true; - try { - while (!queue->isClosed()) { - Mutex::ScopedUnlock u(lock); - FrameSet::shared_ptr content = queue->pop(); - if (content->isA<MessageTransferBody>()) { - Message msg(new MessageImpl(*content)); - boost::intrusive_ptr<SubscriptionImpl> listener = find(msg.getDestination()); - if (!listener) { - QPID_LOG(error, "No listener found for destination " << msg.getDestination()); - } else { - assert(listener); - listener->received(msg); - } - } else { - if (handler.get()) { - handler->handle(*content); - } else { - QPID_LOG(warning, "No handler found for " << *(content->getMethod())); - } - } - } - session.sync(); // Make sure all our acks are received before returning. - } - catch (const ClosedException&) { - QPID_LOG(debug, QPID_MSG(session.getId() << ": closed by peer")); - } - catch (const TransportFailure&) { - QPID_LOG(info, QPID_MSG(session.getId() << ": transport failure")); - throw; - } - catch (const std::exception& e) { - if ( failoverHandler ) { - QPID_LOG(debug, QPID_MSG(session.getId() << " failover: " << e.what())); - failoverHandler(); - } else { - QPID_LOG(error, session.getId() << " error: " << e.what()); - throw; - } - } -} - -void Dispatcher::stop() -{ - ScopedLock<Mutex> l(lock); - queue->close(); // Will interrupt thread blocked in pop() -} - -void Dispatcher::setAutoStop(bool b) -{ - ScopedLock<Mutex> l(lock); - autoStop = b; -} - -boost::intrusive_ptr<SubscriptionImpl> Dispatcher::find(const std::string& name) -{ - ScopedLock<Mutex> l(lock); - Listeners::iterator i = listeners.find(name); - if (i == listeners.end()) { - return defaultListener; - } - return i->second; -} - -void Dispatcher::listen(const boost::intrusive_ptr<SubscriptionImpl>& subscription) { - ScopedLock<Mutex> l(lock); - listeners[subscription->getName()] = subscription; -} - -void Dispatcher::cancel(const std::string& destination) { - ScopedLock<Mutex> l(lock); - if (listeners.erase(destination) && running && autoStop && listeners.empty()) - queue->close(); -} - -}} diff --git a/cpp/src/qpid/client/Dispatcher.h b/cpp/src/qpid/client/Dispatcher.h deleted file mode 100644 index 74fdb90103..0000000000 --- a/cpp/src/qpid/client/Dispatcher.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Dispatcher_ -#define _Dispatcher_ - -#include <map> -#include <memory> -#include <string> -#include <boost/shared_ptr.hpp> -#include "qpid/client/Session.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include "qpid/client/ClientImportExport.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/SubscriptionImpl.h" - -namespace qpid { -namespace client { - -class SubscriptionImpl; - -///@internal -typedef framing::Handler<framing::FrameSet> FrameSetHandler; - -///@internal -class Dispatcher : public sys::Runnable -{ - typedef std::map<std::string, boost::intrusive_ptr<SubscriptionImpl> >Listeners; - sys::Mutex lock; - sys::Thread worker; - Session session; - Demux::QueuePtr queue; - bool running; - bool autoStop; - Listeners listeners; - boost::intrusive_ptr<SubscriptionImpl> defaultListener; - std::auto_ptr<FrameSetHandler> handler; - - boost::intrusive_ptr<SubscriptionImpl> find(const std::string& name); - bool isStopped(); - - boost::function<void ()> failoverHandler; - -public: - Dispatcher(const Session& session, const std::string& queue = ""); - ~Dispatcher() {} - - void start(); - void wait(); - // As this class is marked 'internal', no extern should be made here; - // however, some test programs rely on it. - QPID_CLIENT_EXTERN void run(); - void stop(); - void setAutoStop(bool b); - - void registerFailoverHandler ( boost::function<void ()> fh ) - { - failoverHandler = fh; - } - - void listen(const boost::intrusive_ptr<SubscriptionImpl>& subscription); - void cancel(const std::string& destination); -}; - -}} - -#endif diff --git a/cpp/src/qpid/client/Execution.h b/cpp/src/qpid/client/Execution.h deleted file mode 100644 index ad622af9c1..0000000000 --- a/cpp/src/qpid/client/Execution.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Execution_ -#define _Execution_ - -#include "qpid/framing/SequenceNumber.h" -#include "qpid/client/Demux.h" - -namespace qpid { -namespace client { - -/**@internal - * - * Provides access to more detailed aspects of the session - * implementation. - */ -class Execution -{ -public: - virtual ~Execution() {} - /** - * Provides access to the demultiplexing function within the - * session implementation - */ - virtual Demux& getDemux() = 0; - /** - * Wait until notification has been received of completion of the - * outgoing command with the specified id. - */ - void waitForCompletion(const framing::SequenceNumber& id); -}; - -}} - -#endif diff --git a/cpp/src/qpid/client/FailoverListener.cpp b/cpp/src/qpid/client/FailoverListener.cpp deleted file mode 100644 index bf4fa91d49..0000000000 --- a/cpp/src/qpid/client/FailoverListener.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/FailoverListener.h" -#include "qpid/client/Session.h" -#include "qpid/framing/Uuid.h" -#include "qpid/log/Statement.h" -#include "qpid/log/Helpers.h" - -namespace qpid { -namespace client { - -const std::string FailoverListener::AMQ_FAILOVER("amq.failover"); - -FailoverListener::FailoverListener(Connection c) : - connection(c), - session(c.newSession(AMQ_FAILOVER+"."+framing::Uuid(true).str())), - subscriptions(session) -{ init(true); } - -FailoverListener::FailoverListener(Connection c, bool useInitial) : - connection(c), - session(c.newSession(AMQ_FAILOVER+"."+framing::Uuid(true).str())), - subscriptions(session) -{ init(useInitial); } - -void FailoverListener::init(bool useInitial) { - if (useInitial) knownBrokers = connection.getInitialBrokers(); - if (session.exchangeQuery(arg::name=AMQ_FAILOVER).getNotFound()) { - session.close(); - return; - } - std::string qname=session.getId().getName(); - session.queueDeclare(arg::queue=qname, arg::exclusive=true, arg::autoDelete=true); - session.exchangeBind(arg::queue=qname, arg::exchange=AMQ_FAILOVER); - subscriptions.subscribe(*this, qname, SubscriptionSettings(FlowControl::unlimited(), - ACCEPT_MODE_NONE)); - thread = sys::Thread(*this); -} - -void FailoverListener::run() { - try { - subscriptions.run(); - } catch(...) {} -} - -FailoverListener::~FailoverListener() { - try { - subscriptions.stop(); - thread.join(); - if (connection.isOpen()) { - session.sync(); - session.close(); - } - } catch (...) {} -} - -void FailoverListener::received(Message& msg) { - sys::Mutex::ScopedLock l(lock); - knownBrokers = getKnownBrokers(msg); -} - -std::vector<Url> FailoverListener::getKnownBrokers() const { - sys::Mutex::ScopedLock l(lock); - return knownBrokers; -} - -std::vector<Url> FailoverListener::getKnownBrokers(const Message& msg) { - std::vector<Url> knownBrokers; - framing::Array urlArray; - msg.getHeaders().getArray("amq.failover", urlArray); - for (framing::Array::ValueVector::const_iterator i = urlArray.begin(); - i != urlArray.end(); - ++i ) - knownBrokers.push_back(Url((*i)->get<std::string>())); - return knownBrokers; -} - - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/FailoverManager.cpp b/cpp/src/qpid/client/FailoverManager.cpp deleted file mode 100644 index 9405765b47..0000000000 --- a/cpp/src/qpid/client/FailoverManager.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/FailoverManager.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" - - -namespace qpid { -namespace client { - -using qpid::sys::Monitor; -using qpid::sys::AbsTime; -using qpid::sys::Duration; - -FailoverManager::FailoverManager(const ConnectionSettings& s, - ReconnectionStrategy* rs) : settings(s), strategy(rs), state(IDLE) {} - -void FailoverManager::execute(Command& c) -{ - bool retry = false; - bool completed = false; - AbsTime failed; - while (!completed) { - try { - AsyncSession session = connect().newSession(); - if (retry) { - Duration failoverTime(failed, AbsTime::now()); - QPID_LOG(info, "Failed over for " << &c << " in " << (failoverTime/qpid::sys::TIME_MSEC) << " milliseconds"); - } - c.execute(session, retry); - session.sync();//TODO: shouldn't be required - session.close(); - completed = true; - } catch(const TransportFailure&) { - retry = true; - failed = AbsTime::now(); - } - } -} - -void FailoverManager::close() -{ - Monitor::ScopedLock l(lock); - connection.close(); -} - -Connection& FailoverManager::connect(std::vector<Url> brokers) -{ - Monitor::ScopedLock l(lock); - if (state == CANT_CONNECT) { - state = IDLE;//retry - } - while (!connection.isOpen()) { - if (state == CONNECTING) { - lock.wait(); - } else if (state == CANT_CONNECT) { - throw CannotConnectException("Cannot establish a connection"); - } else { - state = CONNECTING; - Connection c; - if (brokers.empty() && failoverListener.get()) - brokers = failoverListener->getKnownBrokers(); - attempt(c, settings, brokers); - if (c.isOpen()) state = IDLE; - else state = CANT_CONNECT; - connection = c; - lock.notifyAll(); - } - } - return connection; -} - -Connection& FailoverManager::getConnection() -{ - Monitor::ScopedLock l(lock); - return connection; -} - -void FailoverManager::attempt(Connection& c, ConnectionSettings s, std::vector<Url> urls) -{ - Monitor::ScopedUnlock u(lock); - if (strategy) strategy->editUrlList(urls); - if (urls.empty()) { - attempt(c, s); - } else { - for (std::vector<Url>::const_iterator i = urls.begin(); i != urls.end() && !c.isOpen(); ++i) { - for (Url::const_iterator j = i->begin(); j != i->end() && !c.isOpen(); ++j) { - const Address& addr = *j; - s.protocol = addr.protocol; - s.host = addr.host; - s.port = addr.port; - attempt(c, s); - } - } - } -} - -void FailoverManager::attempt(Connection& c, ConnectionSettings s) -{ - try { - QPID_LOG(info, "Attempting to connect to " << s.host << " on " << s.port << "..."); - c.open(s); - failoverListener.reset(new FailoverListener(c)); - QPID_LOG(info, "Connected to " << s.host << " on " << s.port); - } catch (const Exception& e) { - QPID_LOG(info, "Could not connect to " << s.host << " on " << s.port << ": " << e.what()); - } -} - - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Future.cpp b/cpp/src/qpid/client/Future.cpp deleted file mode 100644 index 740cd3df59..0000000000 --- a/cpp/src/qpid/client/Future.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Future.h" -#include "qpid/client/SessionImpl.h" - -namespace qpid { -namespace client { - -void Future::wait(SessionImpl& session) -{ - if (!complete) { - session.waitForCompletion(command); - } - complete = true; -} - -bool Future::isComplete(SessionImpl& session) -{ - return complete || session.isComplete(command); -} - -void Future::setFutureResult(boost::shared_ptr<FutureResult> r) -{ - result = r; -} - -}} diff --git a/cpp/src/qpid/client/FutureCompletion.cpp b/cpp/src/qpid/client/FutureCompletion.cpp deleted file mode 100644 index ccfb073855..0000000000 --- a/cpp/src/qpid/client/FutureCompletion.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/FutureCompletion.h" - -using namespace qpid::client; -using namespace qpid::sys; - -FutureCompletion::FutureCompletion() : complete(false) {} - -bool FutureCompletion::isComplete() const -{ - Monitor::ScopedLock l(lock); - return complete; -} - -void FutureCompletion::completed() -{ - Monitor::ScopedLock l(lock); - complete = true; - lock.notifyAll(); -} - -void FutureCompletion::waitForCompletion() const -{ - Monitor::ScopedLock l(lock); - while (!complete) { - lock.wait(); - } -} diff --git a/cpp/src/qpid/client/FutureResult.cpp b/cpp/src/qpid/client/FutureResult.cpp deleted file mode 100644 index 0237eb1464..0000000000 --- a/cpp/src/qpid/client/FutureResult.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/FutureResult.h" - -#include "qpid/client/SessionImpl.h" - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; - -const std::string& FutureResult::getResult(SessionImpl& session) const -{ - waitForCompletion(); - session.assertOpen(); - return result; -} - -void FutureResult::received(const std::string& r) -{ - Monitor::ScopedLock l(lock); - result = r; - complete = true; - lock.notifyAll(); -} diff --git a/cpp/src/qpid/client/LoadPlugins.cpp b/cpp/src/qpid/client/LoadPlugins.cpp deleted file mode 100644 index 246eb60c67..0000000000 --- a/cpp/src/qpid/client/LoadPlugins.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "LoadPlugins.h" - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "qpid/Modules.h" -#include "qpid/sys/Shlib.h" -#include <string> -#include <vector> - -using std::vector; -using std::string; - -namespace qpid { -namespace client { - -namespace { - -struct LoadtimeInitialise { - LoadtimeInitialise() { - qpid::ModuleOptions moduleOptions(QPIDC_MODULE_DIR); - string defaultPath (moduleOptions.loadDir); - moduleOptions.parse (0, 0, QPIDC_CONF_FILE, true); - - for (vector<string>::iterator iter = moduleOptions.load.begin(); - iter != moduleOptions.load.end(); - iter++) - qpid::tryShlib (iter->data(), false); - - if (!moduleOptions.noLoad) { - bool isDefault = defaultPath == moduleOptions.loadDir; - qpid::loadModuleDir (moduleOptions.loadDir, isDefault); - } - } -}; - -} // namespace - -void theModuleLoader() { - static LoadtimeInitialise l; -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/LoadPlugins.h b/cpp/src/qpid/client/LoadPlugins.h deleted file mode 100644 index 0be4ae9f0c..0000000000 --- a/cpp/src/qpid/client/LoadPlugins.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _LoadPlugins_ -#define _LoadPlugins_ - -namespace qpid { -namespace client { - -void theModuleLoader(); - -}} - - -#endif diff --git a/cpp/src/qpid/client/LocalQueue.cpp b/cpp/src/qpid/client/LocalQueue.cpp deleted file mode 100644 index 0019adabaf..0000000000 --- a/cpp/src/qpid/client/LocalQueue.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/LocalQueue.h" -#include "qpid/client/LocalQueueImpl.h" -#include "qpid/client/MessageImpl.h" -#include "qpid/Exception.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/client/PrivateImplRef.h" -#include "qpid/client/SubscriptionImpl.h" - -namespace qpid { -namespace client { - -using namespace framing; - -typedef PrivateImplRef<LocalQueue> PI; - -LocalQueue::LocalQueue() { PI::ctor(*this, new LocalQueueImpl()); } -LocalQueue::LocalQueue(const LocalQueue& x) : Handle<LocalQueueImpl>() { PI::copy(*this, x); } -LocalQueue::~LocalQueue() { PI::dtor(*this); } -LocalQueue& LocalQueue::operator=(const LocalQueue& x) { return PI::assign(*this, x); } - -Message LocalQueue::pop(sys::Duration timeout) { return impl->pop(timeout); } - -Message LocalQueue::get(sys::Duration timeout) { return impl->get(timeout); } - -bool LocalQueue::get(Message& result, sys::Duration timeout) { return impl->get(result, timeout); } - -bool LocalQueue::empty() const { return impl->empty(); } -size_t LocalQueue::size() const { return impl->size(); } - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/LocalQueueImpl.cpp b/cpp/src/qpid/client/LocalQueueImpl.cpp deleted file mode 100644 index 8b191728f4..0000000000 --- a/cpp/src/qpid/client/LocalQueueImpl.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/LocalQueueImpl.h" -#include "qpid/client/MessageImpl.h" -#include "qpid/Exception.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/client/PrivateImplRef.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/CompletionImpl.h" - -namespace qpid { -namespace client { - -using namespace framing; - -Message LocalQueueImpl::pop(sys::Duration timeout) { return get(timeout); } - -Message LocalQueueImpl::get(sys::Duration timeout) { - Message result; - bool ok = get(result, timeout); - if (!ok) throw Exception("Timed out waiting for a message"); - return result; -} - -bool LocalQueueImpl::get(Message& result, sys::Duration timeout) { - if (!queue) - throw ClosedException(); - FrameSet::shared_ptr content; - bool ok = queue->pop(content, timeout); - if (!ok) return false; - if (content->isA<MessageTransferBody>()) { - - *MessageImpl::get(result) = MessageImpl(*content); - boost::intrusive_ptr<SubscriptionImpl> si = PrivateImplRef<Subscription>::get(subscription); - assert(si); - if (si) si->received(result); - return true; - } - else - throw CommandInvalidException( - QPID_MSG("Unexpected method: " << content->getMethod())); -} - -bool LocalQueueImpl::empty() const -{ - if (!queue) - throw ClosedException(); - return queue->empty(); -} - -size_t LocalQueueImpl::size() const -{ - if (!queue) - throw ClosedException(); - return queue->size(); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/LocalQueueImpl.h b/cpp/src/qpid/client/LocalQueueImpl.h deleted file mode 100644 index 75b62cf203..0000000000 --- a/cpp/src/qpid/client/LocalQueueImpl.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef QPID_CLIENT_LOCALQUEUEIMPL_H -#define QPID_CLIENT_LOCALQUEUEIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ClientImportExport.h" -#include "qpid/client/Handle.h" -#include "qpid/client/Message.h" -#include "qpid/client/Subscription.h" -#include "qpid/client/Demux.h" -#include "qpid/sys/Time.h" -#include "qpid/RefCounted.h" - -namespace qpid { -namespace client { - -/** - * A local queue to collect messages retrieved from a remote broker - * queue. Create a queue and subscribe it using the SubscriptionManager. - * Messages from the remote queue on the broker will be stored in the - * local queue until you retrieve them. - * - * \ingroup clientapi - * - * \details Using a Local Queue - * - * <pre> - * LocalQueue local_queue; - * subscriptions.subscribe(local_queue, string("message_queue")); - * for (int i=0; i<10; i++) { - * Message message = local_queue.get(); - * std::cout << message.getData() << std::endl; - * } - * </pre> - * - * <h2>Getting Messages</h2> - * - * <ul><li> - * <p>get()</p> - * <pre>Message message = local_queue.get();</pre> - * <pre>// Specifying timeouts (TIME_SEC, TIME_MSEC, TIME_USEC, TIME_NSEC) - *#include <qpid/sys/Time.h> - *Message message; - *local_queue.get(message, 5*sys::TIME_SEC);</pre></li></ul> - * - * <h2>Checking size</h2> - * <ul><li> - * <p>empty()</p> - * <pre>if (local_queue.empty()) { ... }</pre></li> - * <li><p>size()</p> - * <pre>std::cout << local_queue.size();</pre></li> - * </ul> - */ - -class LocalQueueImpl : public RefCounted { - public: - /** Wait up to timeout for the next message from the local queue. - *@param result Set to the message from the queue. - *@param timeout wait up this timeout for a message to appear. - *@return true if result was set, false if queue was empty after timeout. - */ - bool get(Message& result, sys::Duration timeout=0); - - /** Get the next message off the local queue, or wait up to the timeout - * for message from the broker queue. - *@param timeout wait up this timeout for a message to appear. - *@return message from the queue. - *@throw ClosedException if subscription is closed or timeout exceeded. - */ - Message get(sys::Duration timeout=sys::TIME_INFINITE); - - /** Synonym for get() */ - Message pop(sys::Duration timeout=sys::TIME_INFINITE); - - /** Return true if local queue is empty. */ - bool empty() const; - - /** Number of messages on the local queue */ - size_t size() const; - - private: - Demux::QueuePtr queue; - Subscription subscription; - friend class SubscriptionManagerImpl; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_LOCALQUEUEIMPL_H*/ diff --git a/cpp/src/qpid/client/Message.cpp b/cpp/src/qpid/client/Message.cpp deleted file mode 100644 index 00f911c57e..0000000000 --- a/cpp/src/qpid/client/Message.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Message.h" -#include "qpid/client/MessageImpl.h" - -namespace qpid { -namespace client { - -Message::Message(MessageImpl* mi) : impl(mi) {} - -Message::Message(const std::string& data, const std::string& routingKey) - : impl(new MessageImpl(data, routingKey)) {} - -Message::Message(const Message& m) : impl(new MessageImpl(*m.impl)) {} - -Message::~Message() { delete impl; } - -Message& Message::operator=(const Message& m) { *impl = *m.impl; return *this; } - -void Message::swap(Message& m) { std::swap(impl, m.impl); } - -std::string Message::getDestination() const { return impl->getDestination(); } -bool Message::isRedelivered() const { return impl->isRedelivered(); } -void Message::setRedelivered(bool redelivered) { impl->setRedelivered(redelivered); } -framing::FieldTable& Message::getHeaders() { return impl->getHeaders(); } -const framing::FieldTable& Message::getHeaders() const { return impl->getHeaders(); } -const framing::SequenceNumber& Message::getId() const { return impl->getId(); } - -void Message::setData(const std::string& s) { impl->setData(s); } -const std::string& Message::getData() const { return impl->getData(); } -std::string& Message::getData() { return impl->getData(); } - -void Message::appendData(const std::string& s) { impl->appendData(s); } - -bool Message::hasMessageProperties() const { return impl->hasMessageProperties(); } -framing::MessageProperties& Message::getMessageProperties() { return impl->getMessageProperties(); } -const framing::MessageProperties& Message::getMessageProperties() const { return impl->getMessageProperties(); } - -bool Message::hasDeliveryProperties() const { return impl->hasDeliveryProperties(); } -framing::DeliveryProperties& Message::getDeliveryProperties() { return impl->getDeliveryProperties(); } -const framing::DeliveryProperties& Message::getDeliveryProperties() const { return impl->getDeliveryProperties(); } - -}} diff --git a/cpp/src/qpid/client/MessageImpl.cpp b/cpp/src/qpid/client/MessageImpl.cpp deleted file mode 100644 index 865c462b15..0000000000 --- a/cpp/src/qpid/client/MessageImpl.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/MessageImpl.h" - -namespace qpid { -namespace client { - -MessageImpl::MessageImpl(const std::string& data, const std::string& routingKey) : TransferContent(data, routingKey) {} - -std::string MessageImpl::getDestination() const -{ - return method.getDestination(); -} - -bool MessageImpl::isRedelivered() const -{ - return hasDeliveryProperties() && getDeliveryProperties().getRedelivered(); -} - -void MessageImpl::setRedelivered(bool redelivered) -{ - getDeliveryProperties().setRedelivered(redelivered); -} - -framing::FieldTable& MessageImpl::getHeaders() -{ - return getMessageProperties().getApplicationHeaders(); -} - -const framing::FieldTable& MessageImpl::getHeaders() const -{ - return getMessageProperties().getApplicationHeaders(); -} - -const framing::MessageTransferBody& MessageImpl::getMethod() const -{ - return method; -} - -const framing::SequenceNumber& MessageImpl::getId() const -{ - return id; -} - -/**@internal for incoming messages */ -MessageImpl::MessageImpl(const framing::FrameSet& frameset) : - method(*frameset.as<framing::MessageTransferBody>()), id(frameset.getId()) -{ - populate(frameset); -} - -}} diff --git a/cpp/src/qpid/client/MessageImpl.h b/cpp/src/qpid/client/MessageImpl.h deleted file mode 100644 index a64ddd20d8..0000000000 --- a/cpp/src/qpid/client/MessageImpl.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef QPID_CLIENT_MESSAGEIMPL_H -#define QPID_CLIENT_MESSAGEIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Message.h" -#include "qpid/client/Session.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/TransferContent.h" -#include <string> - -namespace qpid { -namespace client { - -class MessageImpl : public framing::TransferContent -{ -public: - /** Create a Message. - *@param data Data for the message body. - *@param routingKey Passed to the exchange that routes the message. - */ - MessageImpl(const std::string& data=std::string(), - const std::string& routingKey=std::string()); - - /** The destination of messages sent to the broker is the exchange - * name. The destination of messages received from the broker is - * the delivery tag identifyig the local subscription (often this - * is the name of the subscribed queue.) - */ - std::string getDestination() const; - - /** Check the redelivered flag. */ - bool isRedelivered() const; - /** Set the redelivered flag. */ - void setRedelivered(bool redelivered); - - /** Get a modifyable reference to the message headers. */ - framing::FieldTable& getHeaders(); - - /** Get a non-modifyable reference to the message headers. */ - const framing::FieldTable& getHeaders() const; - - ///@internal - const framing::MessageTransferBody& getMethod() const; - ///@internal - const framing::SequenceNumber& getId() const; - - /**@internal for incoming messages */ - MessageImpl(const framing::FrameSet& frameset); - - static MessageImpl* get(Message& m) { return m.impl; } - static const MessageImpl* get(const Message& m) { return m.impl; } - -private: - //method and id are only set for received messages: - framing::MessageTransferBody method; - framing::SequenceNumber id; -}; - -}} - -#endif /*!QPID_CLIENT_MESSAGEIMPL_H*/ diff --git a/cpp/src/qpid/client/MessageListener.cpp b/cpp/src/qpid/client/MessageListener.cpp deleted file mode 100644 index 0f2a71287c..0000000000 --- a/cpp/src/qpid/client/MessageListener.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/MessageListener.h" - -qpid::client::MessageListener::~MessageListener() {} diff --git a/cpp/src/qpid/client/MessageReplayTracker.cpp b/cpp/src/qpid/client/MessageReplayTracker.cpp deleted file mode 100644 index 3afaae74e8..0000000000 --- a/cpp/src/qpid/client/MessageReplayTracker.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/MessageReplayTracker.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace client { - -MessageReplayTracker::MessageReplayTracker(uint f) : flushInterval(f), count(0) {} - -void MessageReplayTracker::send(const Message& message, const std::string& destination) -{ - buffer.push_back(ReplayRecord(message, destination)); - buffer.back().send(*this); - if (flushInterval && (++count % flushInterval == 0)) { - checkCompletion(); - if (!buffer.empty()) session.flush(); - } -} -void MessageReplayTracker::init(AsyncSession s) -{ - session = s; -} - -void MessageReplayTracker::replay(AsyncSession s) -{ - session = s; - std::for_each(buffer.begin(), buffer.end(), boost::bind(&ReplayRecord::send, _1, boost::ref(*this))); - session.flush(); - count = 0; -} - -void MessageReplayTracker::setFlushInterval(uint f) -{ - flushInterval = f; -} - -uint MessageReplayTracker::getFlushInterval() -{ - return flushInterval; -} - -void MessageReplayTracker::checkCompletion() -{ - buffer.remove_if(boost::bind(&ReplayRecord::isComplete, _1)); -} - -MessageReplayTracker::ReplayRecord::ReplayRecord(const Message& m, const std::string& d) : message(m), destination(d) {} - -void MessageReplayTracker::ReplayRecord::send(MessageReplayTracker& tracker) -{ - status = tracker.session.messageTransfer(arg::destination=destination, arg::content=message); -} - -bool MessageReplayTracker::ReplayRecord::isComplete() -{ - return status.isComplete(); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/PrivateImplRef.h b/cpp/src/qpid/client/PrivateImplRef.h deleted file mode 100644 index 503a383c31..0000000000 --- a/cpp/src/qpid/client/PrivateImplRef.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef QPID_CLIENT_PRIVATEIMPL_H -#define QPID_CLIENT_PRIVATEIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ClientImportExport.h" -#include <boost/intrusive_ptr.hpp> -#include "qpid/RefCounted.h" - -namespace qpid { -namespace client { - -// FIXME aconway 2009-04-24: details! -/** @file - * - * Helper class to implement a class with a private, reference counted - * implementation and reference semantics. - * - * Such classes are used in the public API to hide implementation, they - * should. Example of use: - * - * === Foo.h - * - * template <class T> PrivateImplRef; - * class FooImpl; - * - * Foo : public Handle<FooImpl> { - * public: - * Foo(FooImpl* = 0); - * Foo(const Foo&); - * ~Foo(); - * Foo& operator=(const Foo&); - * - * int fooDo(); // and other Foo functions... - * - * private: - * typedef FooImpl Impl; - * Impl* impl; - * friend class PrivateImplRef<Foo>; - * - * === Foo.cpp - * - * typedef PrivateImplRef<Foo> PI; - * Foo::Foo(FooImpl* p) { PI::ctor(*this, p); } - * Foo::Foo(const Foo& c) : Handle<FooImpl>() { PI::copy(*this, c); } - * Foo::~Foo() { PI::dtor(*this); } - * Foo& Foo::operator=(const Foo& c) { return PI::assign(*this, c); } - * - * int foo::fooDo() { return impl->fooDo(); } - * - */ -template <class T> class PrivateImplRef { - public: - typedef typename T::Impl Impl; - typedef boost::intrusive_ptr<Impl> intrusive_ptr; - - static intrusive_ptr get(const T& t) { return intrusive_ptr(t.impl); } - - static void set(T& t, const intrusive_ptr& p) { - if (t.impl == p) return; - if (t.impl) boost::intrusive_ptr_release(t.impl); - t.impl = p.get(); - if (t.impl) boost::intrusive_ptr_add_ref(t.impl); - } - - // Helper functions to implement the ctor, dtor, copy, assign - static void ctor(T& t, Impl* p) { t.impl = p; if (p) boost::intrusive_ptr_add_ref(p); } - static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); } - static void dtor(T& t) { if(t.impl) boost::intrusive_ptr_release(t.impl); } - static T& assign(T& t, const T& x) { set(t, get(x)); return t;} -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_PRIVATEIMPL_H*/ diff --git a/cpp/src/qpid/client/QueueOptions.cpp b/cpp/src/qpid/client/QueueOptions.cpp deleted file mode 100644 index f4c1483859..0000000000 --- a/cpp/src/qpid/client/QueueOptions.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/QueueOptions.h" - -namespace qpid { -namespace client { - -enum QueueEventGeneration {ENQUEUE_ONLY=1, ENQUEUE_AND_DEQUEUE=2}; - - -QueueOptions::QueueOptions() -{} - -const std::string QueueOptions::strMaxCountKey("qpid.max_count"); -const std::string QueueOptions::strMaxSizeKey("qpid.max_size"); -const std::string QueueOptions::strTypeKey("qpid.policy_type"); -const std::string QueueOptions::strREJECT("reject"); -const std::string QueueOptions::strFLOW_TO_DISK("flow_to_disk"); -const std::string QueueOptions::strRING("ring"); -const std::string QueueOptions::strRING_STRICT("ring_strict"); -const std::string QueueOptions::strLastValueQueue("qpid.last_value_queue"); -const std::string QueueOptions::strPersistLastNode("qpid.persist_last_node"); -const std::string QueueOptions::strLVQMatchProperty("qpid.LVQ_key"); -const std::string QueueOptions::strLastValueQueueNoBrowse("qpid.last_value_queue_no_browse"); -const std::string QueueOptions::strQueueEventMode("qpid.queue_event_generation"); - - -QueueOptions::~QueueOptions() -{} - -void QueueOptions::setSizePolicy(QueueSizePolicy sp, uint64_t maxSize, uint32_t maxCount) -{ - if (maxCount) setInt(strMaxCountKey, maxCount); - if (maxSize) setInt(strMaxSizeKey, maxSize); - if (maxSize || maxCount){ - switch (sp) - { - case REJECT: - setString(strTypeKey, strREJECT); - break; - case FLOW_TO_DISK: - setString(strTypeKey, strFLOW_TO_DISK); - break; - case RING: - setString(strTypeKey, strRING); - break; - case RING_STRICT: - setString(strTypeKey, strRING_STRICT); - break; - case NONE: - clearSizePolicy(); - break; - } - } -} - - -void QueueOptions::setPersistLastNode() -{ - setInt(strPersistLastNode, 1); -} - -void QueueOptions::setOrdering(QueueOrderingPolicy op) -{ - if (op == LVQ){ - setInt(strLastValueQueue, 1); - }else if (op == LVQ_NO_BROWSE){ - setInt(strLastValueQueueNoBrowse, 1); - }else { - clearOrdering(); - } -} - -void QueueOptions::getLVQKey(std::string& key) -{ - key.assign(strLVQMatchProperty); -} - -void QueueOptions::clearSizePolicy() -{ - erase(strMaxCountKey); - erase(strMaxSizeKey); - erase(strTypeKey); -} - -void QueueOptions::clearPersistLastNode() -{ - erase(strPersistLastNode); -} - -void QueueOptions::clearOrdering() -{ - erase(strLastValueQueue); -} - -void QueueOptions::enableQueueEvents(bool enqueueOnly) -{ - setInt(strQueueEventMode, enqueueOnly ? ENQUEUE_ONLY : ENQUEUE_AND_DEQUEUE); -} - -} -} - - diff --git a/cpp/src/qpid/client/RdmaConnector.cpp b/cpp/src/qpid/client/RdmaConnector.cpp deleted file mode 100644 index 6af607198c..0000000000 --- a/cpp/src/qpid/client/RdmaConnector.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Connector.h" - -#include "qpid/client/Bounds.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/InitiationHandler.h" -#include "qpid/sys/rdma/RdmaIO.h" -#include "qpid/sys/rdma/rdma_exception.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/Msg.h" - -#include <iostream> -#include <boost/bind.hpp> -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> - -// This stuff needs to abstracted out of here to a platform specific file -#include <netdb.h> - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; -using boost::format; -using boost::str; - -class RdmaConnector : public Connector, public sys::Codec -{ - typedef std::deque<framing::AMQFrame> Frames; - - const uint16_t maxFrameSize; - sys::Mutex lock; - Frames frames; - size_t lastEof; // Position after last EOF in frames - uint64_t currentSize; - Bounds* bounds; - - framing::ProtocolVersion version; - bool initiated; - - sys::Mutex dataConnectedLock; - bool dataConnected; - - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - framing::InitiationHandler* initialiser; - framing::OutputHandler* output; - - Rdma::AsynchIO* aio; - Rdma::Connector* acon; - sys::Poller::shared_ptr poller; - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; - - ~RdmaConnector(); - - // Callbacks - void connected(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&); - void connectionError(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, Rdma::ErrorType); - void disconnected(); - void rejected(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&); - - void readbuff(Rdma::AsynchIO&, Rdma::Buffer*); - void writebuff(Rdma::AsynchIO&); - void writeDataBlock(const framing::AMQDataBlock& data); - void dataError(Rdma::AsynchIO&); - void drained(); - void connectionStopped(Rdma::Connector* acon, Rdma::AsynchIO* aio); - void dataStopped(Rdma::AsynchIO* aio); - - std::string identifier; - - void connect(const std::string& host, int port); - void close(); - void send(framing::AMQFrame& frame); - void abort() {} // TODO: need to fix this for heartbeat timeouts to work - - void setInputHandler(framing::InputHandler* handler); - void setShutdownHandler(sys::ShutdownHandler* handler); - sys::ShutdownHandler* getShutdownHandler() const; - framing::OutputHandler* getOutputHandler(); - const std::string& getIdentifier() const; - void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>); - const qpid::sys::SecuritySettings* getSecuritySettings() { return 0; } - - size_t decode(const char* buffer, size_t size); - size_t encode(const char* buffer, size_t size); - bool canEncode(); - -public: - RdmaConnector(Poller::shared_ptr, - framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -// Static constructor which registers connector here -namespace { - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) { - return new RdmaConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - Connector::registerFactory("rdma", &create); - Connector::registerFactory("ib", &create); - }; - } init; -} - - -RdmaConnector::RdmaConnector(Poller::shared_ptr p, - ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : maxFrameSize(settings.maxFrameSize), - lastEof(0), - currentSize(0), - bounds(cimpl), - version(ver), - initiated(false), - dataConnected(false), - shutdownHandler(0), - aio(0), - acon(0), - poller(p) -{ - QPID_LOG(debug, "RdmaConnector created for " << version); -} - -namespace { - void deleteAsynchIO(Rdma::AsynchIO& aio) { - delete &aio; - } - - void deleteConnector(Rdma::ConnectionManager& con) { - delete &con; - } -} - -RdmaConnector::~RdmaConnector() { - QPID_LOG(debug, "~RdmaConnector " << identifier); - if (aio) { - aio->stop(deleteAsynchIO); - } - if (acon) { - acon->stop(deleteConnector); - } -} - -void RdmaConnector::connect(const std::string& host, int port){ - Mutex::ScopedLock l(dataConnectedLock); - assert(!dataConnected); - - acon = new Rdma::Connector( - Rdma::ConnectionParams(maxFrameSize, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(&RdmaConnector::connected, this, poller, _1, _2), - boost::bind(&RdmaConnector::connectionError, this, poller, _1, _2), - boost::bind(&RdmaConnector::disconnected, this), - boost::bind(&RdmaConnector::rejected, this, poller, _1, _2)); - - SocketAddress sa(host, boost::lexical_cast<std::string>(port)); - acon->start(poller, sa); -} - -// The following only gets run when connected -void RdmaConnector::connected(Poller::shared_ptr poller, Rdma::Connection::intrusive_ptr ci, const Rdma::ConnectionParams& cp) { - try { - Mutex::ScopedLock l(dataConnectedLock); - assert(!dataConnected); - Rdma::QueuePair::intrusive_ptr q = ci->getQueuePair(); - - aio = new Rdma::AsynchIO(ci->getQueuePair(), - cp.rdmaProtocolVersion, - cp.maxRecvBufferSize, cp.initialXmitCredit , Rdma::DEFAULT_WR_ENTRIES, - boost::bind(&RdmaConnector::readbuff, this, _1, _2), - boost::bind(&RdmaConnector::writebuff, this, _1), - 0, // write buffers full - boost::bind(&RdmaConnector::dataError, this, _1)); - - identifier = str(format("[%1% %2%]") % ci->getLocalName() % ci->getPeerName()); - ProtocolInitiation init(version); - writeDataBlock(init); - - aio->start(poller); - - dataConnected = true; - - return; - } catch (const Rdma::Exception& e) { - QPID_LOG(error, "Rdma: Cannot create new connection (Rdma exception): " << e.what()); - } catch (const std::exception& e) { - QPID_LOG(error, "Rdma: Cannot create new connection (unknown exception): " << e.what()); - } - dataConnected = false; - connectionStopped(acon, aio); -} - -void RdmaConnector::connectionError(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, Rdma::ErrorType) { - QPID_LOG(debug, "Connection Error " << identifier); - connectionStopped(acon, aio); -} - -// Bizarrely we seem to get rejected events *after* we've already got a connected event for some peer disconnects -// so we need to check whether the data connection is started or not in here -void RdmaConnector::rejected(sys::Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams& cp) { - QPID_LOG(debug, "Connection Rejected " << identifier << ": " << cp.maxRecvBufferSize); - if (dataConnected) { - disconnected(); - } else { - connectionStopped(acon, aio); - } -} - -void RdmaConnector::disconnected() { - QPID_LOG(debug, "Connection disconnected " << identifier); - { - Mutex::ScopedLock l(dataConnectedLock); - // If we're closed already then we'll get to drained() anyway - if (!dataConnected) return; - dataConnected = false; - } - // Make sure that all the disconnected actions take place on the data "thread" - aio->requestCallback(boost::bind(&RdmaConnector::drained, this)); -} - -void RdmaConnector::dataError(Rdma::AsynchIO&) { - QPID_LOG(debug, "Data Error " << identifier); - { - Mutex::ScopedLock l(dataConnectedLock); - // If we're closed already then we'll get to drained() anyway - if (!dataConnected) return; - dataConnected = false; - } - drained(); -} - -void RdmaConnector::close() { - QPID_LOG(debug, "RdmaConnector::close " << identifier); - { - Mutex::ScopedLock l(dataConnectedLock); - if (!dataConnected) return; - dataConnected = false; - } - aio->drainWriteQueue(boost::bind(&RdmaConnector::drained, this)); -} - -void RdmaConnector::drained() { - QPID_LOG(debug, "RdmaConnector::drained " << identifier); - assert(!dataConnected); - assert(aio); - Rdma::AsynchIO* a = aio; - aio = 0; - a->stop(boost::bind(&RdmaConnector::dataStopped, this, a)); -} - -void RdmaConnector::dataStopped(Rdma::AsynchIO* a) { - QPID_LOG(debug, "RdmaConnector::dataStopped " << identifier); - assert(!dataConnected); - assert(acon); - Rdma::Connector* c = acon; - acon = 0; - c->stop(boost::bind(&RdmaConnector::connectionStopped, this, c, a)); -} - -void RdmaConnector::connectionStopped(Rdma::Connector* c, Rdma::AsynchIO* a) { - QPID_LOG(debug, "RdmaConnector::connectionStopped " << identifier); - assert(!dataConnected); - aio = 0; - acon = 0; - delete a; - delete c; - if (shutdownHandler) { - ShutdownHandler* s = shutdownHandler; - shutdownHandler = 0; - s->shutdown(); - } -} - -void RdmaConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void RdmaConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -OutputHandler* RdmaConnector::getOutputHandler(){ - return this; -} - -sys::ShutdownHandler* RdmaConnector::getShutdownHandler() const { - return shutdownHandler; -} - -const std::string& RdmaConnector::getIdentifier() const { - return identifier; -} - -void RdmaConnector::send(AMQFrame& frame) { - // It is possible that we are called to write after we are already shutting down - Mutex::ScopedLock l(dataConnectedLock); - if (!dataConnected) return; - - bool notifyWrite = false; - { - Mutex::ScopedLock l(lock); - frames.push_back(frame); - //only ask to write if this is the end of a frameset or if we - //already have a buffers worth of data - currentSize += frame.encodedSize(); - if (frame.getEof()) { - lastEof = frames.size(); - notifyWrite = true; - } else { - notifyWrite = (currentSize >= maxFrameSize); - } - } - if (notifyWrite) aio->notifyPendingWrite(); -} - -// Called in IO thread. (write idle routine) -// This is NOT only called in response to previously calling notifyPendingWrite -void RdmaConnector::writebuff(Rdma::AsynchIO&) { - // It's possible to be disconnected and be writable - Mutex::ScopedLock l(dataConnectedLock); - if (!dataConnected) { - return; - } - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - if (!codec->canEncode()) { - return; - } - Rdma::Buffer* buffer = aio->getSendBuffer(); - if (buffer) { - size_t encoded = codec->encode(buffer->bytes(), buffer->byteCount()); - buffer->dataCount(encoded); - aio->queueWrite(buffer); - } -} - -bool RdmaConnector::canEncode() -{ - Mutex::ScopedLock l(lock); - //have at least one full frameset or a whole buffers worth of data - return aio->writable() && (lastEof || currentSize >= maxFrameSize); -} - -size_t RdmaConnector::encode(const char* buffer, size_t size) -{ - framing::Buffer out(const_cast<char*>(buffer), size); - size_t bytesWritten(0); - { - Mutex::ScopedLock l(lock); - while (!frames.empty() && out.available() >= frames.front().encodedSize() ) { - frames.front().encode(out); - QPID_LOG(trace, "SENT " << identifier << ": " << frames.front()); - frames.pop_front(); - if (lastEof) --lastEof; - } - bytesWritten = size - out.available(); - currentSize -= bytesWritten; - } - if (bounds) bounds->reduce(bytesWritten); - return bytesWritten; -} - -void RdmaConnector::readbuff(Rdma::AsynchIO&, Rdma::Buffer* buff) { - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - codec->decode(buff->bytes(), buff->dataCount()); -} - -size_t RdmaConnector::decode(const char* buffer, size_t size) -{ - framing::Buffer in(const_cast<char*>(buffer), size); - if (!initiated) { - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - //TODO: check the version is correct - QPID_LOG(debug, "RECV " << identifier << " INIT(" << protocolInit << ")"); - } - initiated = true; - } - AMQFrame frame; - while(frame.decode(in)){ - QPID_LOG(trace, "RECV " << identifier << ": " << frame); - input->received(frame); - } - return size - in.available(); -} - -void RdmaConnector::writeDataBlock(const AMQDataBlock& data) { - Rdma::Buffer* buff = aio->getSendBuffer(); - framing::Buffer out(buff->bytes(), buff->byteCount()); - data.encode(out); - buff->dataCount(data.encodedSize()); - aio->queueWrite(buff); -} - -void RdmaConnector::activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer> sl) -{ - securityLayer = sl; - securityLayer->init(this); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/Results.cpp b/cpp/src/qpid/client/Results.cpp deleted file mode 100644 index 0de3e8bd04..0000000000 --- a/cpp/src/qpid/client/Results.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Results.h" -#include "qpid/client/FutureResult.h" -#include "qpid/framing/SequenceSet.h" - -using namespace qpid::framing; - -namespace qpid { -namespace client { - -Results::Results() {} - -Results::~Results() { - try { close(); } catch (const std::exception& /*e*/) { assert(0); } -} - -void Results::close() -{ - for (Listeners::iterator i = listeners.begin(); i != listeners.end(); i++) { - i->second->completed(); - } - listeners.clear(); -} - -void Results::completed(const SequenceSet& set) -{ - //call complete on those listeners whose ids fall within the set - Listeners::iterator i = listeners.begin(); - while (i != listeners.end()) { - if (set.contains(i->first)) { - i->second->completed(); - listeners.erase(i++); - } else { - i++; - } - } -} - -void Results::received(const SequenceNumber& id, const std::string& result) -{ - Listeners::iterator i = listeners.find(id); - if (i != listeners.end()) { - i->second->received(result); - listeners.erase(i); - } -} - -Results::FutureResultPtr Results::listenForResult(const SequenceNumber& id) -{ - FutureResultPtr l(new FutureResult()); - listeners[id] = l; - return l; -} - -}} diff --git a/cpp/src/qpid/client/Results.h b/cpp/src/qpid/client/Results.h deleted file mode 100644 index 4c49f6b05b..0000000000 --- a/cpp/src/qpid/client/Results.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/SequenceNumber.h" -#include <map> -#include <boost/shared_ptr.hpp> - -#ifndef _Results_ -#define _Results_ - -namespace qpid { -namespace client { - -class FutureResult; - -///@internal -class Results -{ -public: - typedef boost::shared_ptr<FutureResult> FutureResultPtr; - - Results(); - ~Results(); - void completed(const framing::SequenceSet& set); - void received(const framing::SequenceNumber& id, const std::string& result); - FutureResultPtr listenForResult(const framing::SequenceNumber& point); - void close(); - -private: - typedef std::map<framing::SequenceNumber, FutureResultPtr> Listeners; - Listeners listeners; -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/client/SessionBase_0_10.cpp b/cpp/src/qpid/client/SessionBase_0_10.cpp deleted file mode 100644 index e114b7aacc..0000000000 --- a/cpp/src/qpid/client/SessionBase_0_10.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/SessionBase_0_10.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionAccess.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/Future.h" -#include "qpid/framing/all_method_bodies.h" - -namespace qpid { -namespace client { - -using namespace framing; - -SessionBase_0_10::SessionBase_0_10() {} -SessionBase_0_10::~SessionBase_0_10() {} - -void SessionBase_0_10::close() -{ - if (impl) impl->close(); -} - -void SessionBase_0_10::flush() -{ - impl->sendFlush(); -} - -void SessionBase_0_10::sync() -{ - ExecutionSyncBody b; - b.setSync(true); - impl->send(b).wait(*impl); -} - -void SessionBase_0_10::markCompleted(const framing::SequenceSet& ids, bool notifyPeer) -{ - impl->markCompleted(ids, notifyPeer); -} - -void SessionBase_0_10::markCompleted(const framing::SequenceNumber& id, bool cumulative, bool notifyPeer) -{ - impl->markCompleted(id, cumulative, notifyPeer); -} - -void SessionBase_0_10::sendCompletion() -{ - impl->sendCompletion(); -} - -uint16_t SessionBase_0_10::getChannel() const { return impl->getChannel(); } - -void SessionBase_0_10::suspend() { impl->suspend(); } -void SessionBase_0_10::resume(Connection c) { impl->resume(c.impl); } -uint32_t SessionBase_0_10::timeout(uint32_t seconds) { return impl->setTimeout(seconds); } - -SessionId SessionBase_0_10::getId() const { return impl->getId(); } - -bool SessionBase_0_10::isValid() const { return impl; } - -Connection SessionBase_0_10::getConnection() -{ - Connection c; - ConnectionAccess::setImpl(c, impl->getConnection()); - return c; -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/SessionBase_0_10Access.h b/cpp/src/qpid/client/SessionBase_0_10Access.h deleted file mode 100644 index 4d08a7ceaf..0000000000 --- a/cpp/src/qpid/client/SessionBase_0_10Access.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_CLIENT_SESSIONBASEACCESS_H -#define QPID_CLIENT_SESSIONBASEACCESS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SessionBase_0_10.h" - -/**@file @internal Internal use only */ - -namespace qpid { -namespace client { - -class SessionBase_0_10Access { - public: - SessionBase_0_10Access(SessionBase_0_10& sb_) : sb(sb_) {} - void set(const boost::shared_ptr<SessionImpl>& si) { sb.impl = si; } - boost::shared_ptr<SessionImpl> get() const { return sb.impl; } - private: - SessionBase_0_10& sb; -}; -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SESSIONBASEACCESS_H*/ diff --git a/cpp/src/qpid/client/SessionImpl.cpp b/cpp/src/qpid/client/SessionImpl.cpp deleted file mode 100644 index b507625b11..0000000000 --- a/cpp/src/qpid/client/SessionImpl.cpp +++ /dev/null @@ -1,824 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SessionImpl.h" - -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/Future.h" - -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/ClientInvoker.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MethodContent.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/IntegerTypes.h" - -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> - -namespace { const std::string EMPTY; } - -namespace qpid { -namespace client { - -using namespace qpid::framing; -using namespace qpid::framing::session; //for detach codes - -typedef sys::Monitor::ScopedLock Lock; -typedef sys::Monitor::ScopedUnlock UnLock; -typedef sys::ScopedLock<sys::Semaphore> Acquire; - - -SessionImpl::SessionImpl(const std::string& name, boost::shared_ptr<ConnectionImpl> conn) - : state(INACTIVE), - detachedLifetime(0), - maxFrameSize(conn->getNegotiatedSettings().maxFrameSize), - id(conn->getNegotiatedSettings().username, name.empty() ? Uuid(true).str() : name), - connection(conn), - ioHandler(*this), - proxy(ioHandler), - nextIn(0), - nextOut(0), - sendMsgCredit(0), - doClearDeliveryPropertiesExchange(true), - autoDetach(true) -{ - channel.next = connection.get(); -} - -SessionImpl::~SessionImpl() { - { - Lock l(state); - if (state != DETACHED && state != DETACHING) { - if (autoDetach) { - QPID_LOG(warning, "Session was not closed cleanly: " << id); - // Inform broker but don't wait for detached as that deadlocks. - // The detached will be ignored as the channel will be invalid. - try { detach(); } catch (...) {} // ignore errors. - } - setState(DETACHED); - handleClosed(); - state.waitWaiters(); - } - delete sendMsgCredit; - } - connection->erase(channel); -} - - -FrameSet::shared_ptr SessionImpl::get() // user thread -{ - // No lock here: pop does a blocking wait. - return demux.getDefault()->pop(); -} - -const SessionId SessionImpl::getId() const //user thread -{ - return id; //id is immutable -} - -void SessionImpl::open(uint32_t timeout) // user thread -{ - Lock l(state); - if (state == INACTIVE) { - setState(ATTACHING); - proxy.attach(id.getName(), false); - waitFor(ATTACHED); - //TODO: timeout will not be set locally until get response to - //confirm, should we wait for that? - setTimeout(timeout); - proxy.commandPoint(nextOut, 0); - } else { - throw Exception("Open already called for this session"); - } -} - -void SessionImpl::close() //user thread -{ - Lock l(state); - // close() must be idempotent and no-throw as it will often be called in destructors. - if (state != DETACHED && state != DETACHING) { - try { - if (detachedLifetime) setTimeout(0); - detach(); - waitFor(DETACHED); - } catch (...) {} - setState(DETACHED); - } -} - -void SessionImpl::resume(boost::shared_ptr<ConnectionImpl>) // user thread -{ - throw NotImplementedException("Resume not yet implemented by client!"); -} - -void SessionImpl::suspend() //user thread -{ - Lock l(state); - detach(); -} - -void SessionImpl::detach() //call with lock held -{ - if (state == ATTACHED) { - setState(DETACHING); - proxy.detach(id.getName()); - } -} - - -uint16_t SessionImpl::getChannel() const // user thread -{ - return channel; -} - -void SessionImpl::setChannel(uint16_t c) // user thread -{ - //channel will only ever be set when session is detached (and - //about to be resumed) - channel = c; -} - -Demux& SessionImpl::getDemux() -{ - return demux; -} - -void SessionImpl::waitForCompletion(const SequenceNumber& id) -{ - Lock l(state); - waitForCompletionImpl(id); -} - -void SessionImpl::waitForCompletionImpl(const SequenceNumber& id) //call with lock held -{ - while (incompleteOut.contains(id)) { - checkOpen(); - state.wait(); - } -} - -bool SessionImpl::isComplete(const SequenceNumber& id) -{ - Lock l(state); - return !incompleteOut.contains(id); -} - -struct IsCompleteUpTo -{ - const SequenceNumber& id; - bool result; - - IsCompleteUpTo(const SequenceNumber& _id) : id(_id), result(true) {} - void operator()(const SequenceNumber& start, const SequenceNumber&) - { - if (start <= id) result = false; - } - -}; - -bool SessionImpl::isCompleteUpTo(const SequenceNumber& id) -{ - Lock l(state); - //return false if incompleteOut contains anything less than id, - //true otherwise - IsCompleteUpTo f(id); - incompleteIn.for_each(f); - return f.result; -} - -framing::SequenceNumber SessionImpl::getCompleteUpTo() -{ - SequenceNumber firstIncomplete; - { - Lock l(state); - firstIncomplete = incompleteIn.front(); - } - return --firstIncomplete; -} - -struct MarkCompleted -{ - const SequenceNumber& id; - SequenceSet& completedIn; - - MarkCompleted(const SequenceNumber& _id, SequenceSet& set) : id(_id), completedIn(set) {} - - void operator()(const SequenceNumber& start, const SequenceNumber& end) - { - if (id >= end) { - completedIn.add(start, end); - } else if (id >= start) { - completedIn.add(start, id); - } - } - -}; - -void SessionImpl::markCompleted(const SequenceSet& ids, bool notifyPeer) -{ - Lock l(state); - incompleteIn.remove(ids); - completedIn.add(ids); - if (notifyPeer) { - sendCompletion(); - } -} - -void SessionImpl::markCompleted(const SequenceNumber& id, bool cumulative, bool notifyPeer) -{ - Lock l(state); - if (cumulative) { - //everything in incompleteIn less than or equal to id is now complete - MarkCompleted f(id, completedIn); - incompleteIn.for_each(f); - //make sure id itself is in - completedIn.add(id); - //then remove anything thats completed from the incomplete set - incompleteIn.remove(completedIn); - } else if (incompleteIn.contains(id)) { - incompleteIn.remove(id); - completedIn.add(id); - } - if (notifyPeer) { - sendCompletion(); - } -} - -void SessionImpl::setException(const sys::ExceptionHolder& ex) { - Lock l(state); - setExceptionLH(ex); -} - -void SessionImpl::setExceptionLH(const sys::ExceptionHolder& ex) { // Call with lock held. - exceptionHolder = ex; - setState(DETACHED); -} - -/** - * Called by ConnectionImpl to notify active sessions when connection - * is explictly closed - */ -void SessionImpl::connectionClosed(uint16_t code, const std::string& text) { - setException(createConnectionException(code, text)); - handleClosed(); -} - -/** - * Called by ConnectionImpl to notify active sessions when connection - * is disconnected - */ -void SessionImpl::connectionBroke(const std::string& _text) { - setException(sys::ExceptionHolder(new TransportFailure(_text))); - handleClosed(); -} - -Future SessionImpl::send(const AMQBody& command) -{ - return sendCommand(command); -} - -Future SessionImpl::send(const AMQBody& command, const MethodContent& content) -{ - return sendCommand(command, &content); -} - -namespace { -// Functor for FrameSet::map to send header + content frames but, not method frames. -struct SendContentFn { - FrameHandler& handler; - void operator()(const AMQFrame& f) { - if (!f.getMethod()) - handler(const_cast<AMQFrame&>(f)); - } - SendContentFn(FrameHandler& h) : handler(h) {} -}; - -// Adaptor to make FrameSet look like MethodContent; used in cluster update client -struct MethodContentAdaptor : MethodContent -{ - AMQHeaderBody header; - const std::string content; - - MethodContentAdaptor(const FrameSet& f) : header(*f.getHeaders()), content(f.getContent()) {} - - AMQHeaderBody getHeader() const - { - return header; - } - const std::string& getData() const - { - return content; - } -}; - -} - -Future SessionImpl::send(const AMQBody& command, const FrameSet& content, bool reframe) { - Acquire a(sendLock); - SequenceNumber id = nextOut++; - { - Lock l(state); - checkOpen(); - incompleteOut.add(id); - } - Future f(id); - if (command.getMethod()->resultExpected()) { - Lock l(state); - //result listener must be set before the command is sent - f.setFutureResult(results.listenForResult(id)); - } - AMQFrame frame(command); - frame.setEof(false); - handleOut(frame); - - if (reframe) { - MethodContentAdaptor c(content); - sendContent(c); - } else { - SendContentFn send(out); - content.map(send); - } - return f; -} - -void SessionImpl::sendRawFrame(AMQFrame& frame) { - Acquire a(sendLock); - handleOut(frame); -} - -Future SessionImpl::sendCommand(const AMQBody& command, const MethodContent* content) -{ - // Only message transfers have content - if (content && sendMsgCredit) { - sendMsgCredit->acquire(); - } - Acquire a(sendLock); - SequenceNumber id = nextOut++; - { - Lock l(state); - checkOpen(); - incompleteOut.add(id); - } - Future f(id); - if (command.getMethod()->resultExpected()) { - Lock l(state); - //result listener must be set before the command is sent - f.setFutureResult(results.listenForResult(id)); - } - AMQFrame frame(command); - if (content) { - frame.setEof(false); - } - handleOut(frame); - if (content) { - sendContent(*content); - } - return f; -} - -void SessionImpl::sendContent(const MethodContent& content) -{ - AMQFrame header(content.getHeader()); - - // doClearDeliveryPropertiesExchange is set by cluster update client so - // it can send messages with delivery-properties.exchange set. - // - if (doClearDeliveryPropertiesExchange) { - // Normal client is not allowed to set the delivery-properties.exchange - // so clear it here. - AMQHeaderBody* headerp = static_cast<AMQHeaderBody*>(header.getBody()); - if (headerp && headerp->get<DeliveryProperties>()) - headerp->get<DeliveryProperties>(true)->clearExchangeFlag(); - } - header.setFirstSegment(false); - uint64_t data_length = content.getData().length(); - if(data_length > 0){ - header.setLastSegment(false); - handleOut(header); - /*Note: end of frame marker included in overhead but not in size*/ - const uint32_t frag_size = maxFrameSize - AMQFrame::frameOverhead(); - - if(data_length < frag_size){ - AMQFrame frame((AMQContentBody(content.getData()))); - frame.setFirstSegment(false); - handleOut(frame); - }else{ - uint32_t offset = 0; - uint32_t remaining = data_length - offset; - while (remaining > 0) { - uint32_t length = remaining > frag_size ? frag_size : remaining; - string frag(content.getData().substr(offset, length)); - AMQFrame frame((AMQContentBody(frag))); - frame.setFirstSegment(false); - frame.setLastSegment(true); - if (offset > 0) { - frame.setFirstFrame(false); - } - offset += length; - remaining = data_length - offset; - if (remaining) { - frame.setLastFrame(false); - } - handleOut(frame); - } - } - } else { - handleOut(header); - } -} - - -bool isMessageMethod(AMQMethodBody* method) -{ - return method->isA<MessageTransferBody>(); -} - -bool isMessageMethod(AMQBody* body) -{ - AMQMethodBody* method=body->getMethod(); - return method && isMessageMethod(method); -} - -bool isContentFrame(AMQFrame& frame) -{ - AMQBody* body = frame.getBody(); - uint8_t type = body->type(); - return type == HEADER_BODY || type == CONTENT_BODY || isMessageMethod(body); -} - -void SessionImpl::handleIn(AMQFrame& frame) // network thread -{ - try { - if (invoke(static_cast<SessionHandler&>(*this), *frame.getBody())) { - ; - } else if (invoke(static_cast<ExecutionHandler&>(*this), *frame.getBody())) { - //make sure the command id sequence and completion - //tracking takes account of execution commands - Lock l(state); - completedIn.add(nextIn++); - } else if (invoke(static_cast<MessageHandler&>(*this), *frame.getBody())) { - ; - } else { - //if not handled by this class, its for the application: - deliver(frame); - } - } - catch (const SessionException& e) { - setException(createSessionException(e.code, e.getMessage())); - } - catch (const ChannelException& e) { - setException(createChannelException(e.code, e.getMessage())); - } -} - -void SessionImpl::handleOut(AMQFrame& frame) // user thread -{ - sendFrame(frame, true); -} - -void SessionImpl::proxyOut(AMQFrame& frame) // network thread -{ - //Note: this case is treated slightly differently that command - //frames sent by application; session controls should not be - //blocked by bounds checking on the outgoing frame queue. - sendFrame(frame, false); -} - -void SessionImpl::sendFrame(AMQFrame& frame, bool canBlock) -{ - connection->expand(frame.encodedSize(), canBlock); - channel.handle(frame); -} - -void SessionImpl::deliver(AMQFrame& frame) // network thread -{ - if (!arriving) { - arriving = FrameSet::shared_ptr(new FrameSet(nextIn++)); - } - arriving->append(frame); - if (arriving->isComplete()) { - //message.transfers will be marked completed only when 'acked' - //as completion affects flow control; other commands will be - //considered completed as soon as processed here - if (arriving->isA<MessageTransferBody>()) { - Lock l(state); - incompleteIn.add(arriving->getId()); - } else { - Lock l(state); - completedIn.add(arriving->getId()); - } - demux.handle(arriving); - arriving.reset(); - } -} - -//control handler methods (called by network thread when controls are -//received from peer): - -void SessionImpl::attach(const std::string& /*name*/, bool /*force*/) -{ - throw NotImplementedException("Client does not support attach"); -} - -void SessionImpl::attached(const std::string& _name) -{ - Lock l(state); - if (id.getName() != _name) throw InternalErrorException("Incorrect session name"); - setState(ATTACHED); -} - -void SessionImpl::detach(const std::string& _name) -{ - Lock l(state); - if (id.getName() != _name) throw InternalErrorException("Incorrect session name"); - setState(DETACHED); - QPID_LOG(info, "Session detached by peer: " << id); - proxy.detached(_name, DETACH_CODE_NORMAL); - handleClosed(); -} - -void SessionImpl::detached(const std::string& _name, uint8_t _code) { - Lock l(state); - if (id.getName() != _name) throw InternalErrorException("Incorrect session name"); - setState(DETACHED); - if (_code) { - //TODO: make sure this works with execution.exception - don't - //want to overwrite the code from that - setExceptionLH(createChannelException(_code, "Session detached by peer")); - QPID_LOG(error, exceptionHolder.what()); - } - if (detachedLifetime == 0) { - handleClosed(); -} -} - -void SessionImpl::requestTimeout(uint32_t t) -{ - Lock l(state); - detachedLifetime = t; - proxy.timeout(t); -} - -void SessionImpl::timeout(uint32_t t) -{ - Lock l(state); - detachedLifetime = t; -} - -void SessionImpl::commandPoint(const framing::SequenceNumber& id, uint64_t offset) -{ - if (offset) throw NotImplementedException("Non-zero byte offset not yet supported for command-point"); - - Lock l(state); - nextIn = id; -} - -void SessionImpl::expected(const framing::SequenceSet& commands, const framing::Array& fragments) -{ - if (!commands.empty() || fragments.encodedSize()) { - throw NotImplementedException("Session resumption not yet supported"); - } -} - -void SessionImpl::confirmed(const framing::SequenceSet& /*commands*/, const framing::Array& /*fragments*/) -{ - //don't really care too much about this yet -} - -void SessionImpl::completed(const framing::SequenceSet& commands, bool timelyReply) -{ - Lock l(state); - incompleteOut.remove(commands); - state.notifyAll();//notify any waiters of completion - completedOut.add(commands); - //notify any waiting results of completion - results.completed(commands); - - if (timelyReply) { - proxy.knownCompleted(completedOut); - completedOut.clear(); - } -} - -void SessionImpl::knownCompleted(const framing::SequenceSet& commands) -{ - Lock l(state); - completedIn.remove(commands); -} - -void SessionImpl::flush(bool expected, bool confirmed, bool completed) -{ - Lock l(state); - if (expected) { - proxy.expected(SequenceSet(nextIn), Array()); - } - if (confirmed) { - proxy.confirmed(completedIn, Array()); - } - if (completed) { - proxy.completed(completedIn, true); - } -} - -void SessionImpl::sendCompletion() -{ - Lock l(state); - sendCompletionImpl(); -} - -void SessionImpl::sendFlush() -{ - Lock l(state); - proxy.flush(false, false, true); -} - -void SessionImpl::sendCompletionImpl() -{ - proxy.completed(completedIn, completedIn.span() > 1000); -} - -void SessionImpl::gap(const framing::SequenceSet& /*commands*/) -{ - throw NotImplementedException("gap not yet supported"); -} - -void SessionImpl::sync() {} - -void SessionImpl::result(const framing::SequenceNumber& commandId, const std::string& value) -{ - Lock l(state); - results.received(commandId, value); -} - -void SessionImpl::exception(uint16_t errorCode, - const framing::SequenceNumber& commandId, - uint8_t classCode, - uint8_t commandCode, - uint8_t /*fieldIndex*/, - const std::string& description, - const framing::FieldTable& /*errorInfo*/) -{ - Lock l(state); - setExceptionLH(createSessionException(errorCode, description)); - QPID_LOG(warning, "Exception received from broker: " << exceptionHolder.what() - << " [caused by " << commandId << " " << classCode << ":" << commandCode << "]"); - - if (detachedLifetime) - setTimeout(0); -} - -// Message methods: -void SessionImpl::accept(const qpid::framing::SequenceSet&) -{ -} - -void SessionImpl::reject(const qpid::framing::SequenceSet&, uint16_t, const std::string&) -{ -} - -void SessionImpl::release(const qpid::framing::SequenceSet&, bool) -{ -} - -MessageResumeResult SessionImpl::resume(const std::string&, const std::string&) -{ - throw NotImplementedException("resuming transfers not yet supported"); -} - -namespace { - const std::string QPID_SESSION_DEST = ""; - const uint8_t FLOW_MODE_CREDIT = 0; - const uint8_t CREDIT_MODE_MSG = 0; -} - -void SessionImpl::setFlowMode(const std::string& dest, uint8_t flowMode) -{ - if ( dest != QPID_SESSION_DEST ) { - QPID_LOG(warning, "Ignoring flow control for unknown destination: " << dest); - return; - } - - if ( flowMode != FLOW_MODE_CREDIT ) { - throw NotImplementedException("window flow control mode not supported by producer"); - } - Lock l(state); - sendMsgCredit = new sys::Semaphore(0); -} - -void SessionImpl::flow(const std::string& dest, uint8_t mode, uint32_t credit) -{ - if ( dest != QPID_SESSION_DEST ) { - QPID_LOG(warning, "Ignoring flow control for unknown destination: " << dest); - return; - } - - if ( mode != CREDIT_MODE_MSG ) { - return; - } - if (sendMsgCredit) { - sendMsgCredit->release(credit); - } -} - -void SessionImpl::stop(const std::string& dest) -{ - if ( dest != QPID_SESSION_DEST ) { - QPID_LOG(warning, "Ignoring flow control for unknown destination: " << dest); - return; - } - if (sendMsgCredit) { - sendMsgCredit->forceLock(); - } -} - -//private utility methods: - -inline void SessionImpl::setState(State s) //call with lock held -{ - state = s; -} - -inline void SessionImpl::waitFor(State s) //call with lock held -{ - // We can be DETACHED at any time - if (s == DETACHED) state.waitFor(DETACHED); - else state.waitFor(States(s, DETACHED)); - check(); -} - -void SessionImpl::check() const //call with lock held. -{ - exceptionHolder.raise(); -} - -void SessionImpl::checkOpen() const //call with lock held. -{ - check(); - if (state != ATTACHED) { - throw NotAttachedException(QPID_MSG("Session " << getId() << " isn't attached")); - } -} - -void SessionImpl::assertOpen() const -{ - Lock l(state); - checkOpen(); -} - -bool SessionImpl::hasError() const -{ - Lock l(state); - return !exceptionHolder.empty(); -} - -void SessionImpl::handleClosed() -{ - demux.close(exceptionHolder.empty() ? - sys::ExceptionHolder(new ClosedException()) : exceptionHolder); - results.close(); -} - -uint32_t SessionImpl::setTimeout(uint32_t seconds) { - proxy.requestTimeout(seconds); - // FIXME aconway 2008-10-07: wait for timeout response from broker - // and use value retured by broker. - detachedLifetime = seconds; - return detachedLifetime; -} - -uint32_t SessionImpl::getTimeout() const { - return detachedLifetime; -} - -boost::shared_ptr<ConnectionImpl> SessionImpl::getConnection() -{ - return connection; -} - -void SessionImpl::disableAutoDetach() { autoDetach = false; } - -}} diff --git a/cpp/src/qpid/client/SessionImpl.h b/cpp/src/qpid/client/SessionImpl.h deleted file mode 100644 index cd7b2c123d..0000000000 --- a/cpp/src/qpid/client/SessionImpl.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _SessionImpl_ -#define _SessionImpl_ - -#include "qpid/client/Demux.h" -#include "qpid/client/Execution.h" -#include "qpid/client/Results.h" -#include "qpid/client/ClientImportExport.h" - -#include "qpid/SessionId.h" -#include "qpid/SessionState.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/ChannelHandler.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/AMQP_ClientOperations.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/sys/Semaphore.h" -#include "qpid/sys/StateMonitor.h" -#include "qpid/sys/ExceptionHolder.h" - -#include <boost/weak_ptr.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/optional.hpp> - -namespace qpid { - -namespace framing { - -class FrameSet; -class MethodContent; -class SequenceSet; - -} - -namespace client { - -class Future; -class ConnectionImpl; -class SessionHandler; - -///@internal -class SessionImpl : public framing::FrameHandler::InOutHandler, - public Execution, - private framing::AMQP_ClientOperations::SessionHandler, - private framing::AMQP_ClientOperations::ExecutionHandler, - private framing::AMQP_ClientOperations::MessageHandler -{ -public: - SessionImpl(const std::string& name, boost::shared_ptr<ConnectionImpl>); - ~SessionImpl(); - - - //NOTE: Public functions called in user thread. - framing::FrameSet::shared_ptr get(); - - const SessionId getId() const; - - uint16_t getChannel() const; - void setChannel(uint16_t channel); - - void open(uint32_t detachedLifetime); - void close(); - void resume(boost::shared_ptr<ConnectionImpl>); - void suspend(); - - QPID_CLIENT_EXTERN void assertOpen() const; - QPID_CLIENT_EXTERN bool hasError() const; - - Future send(const framing::AMQBody& command); - Future send(const framing::AMQBody& command, const framing::MethodContent& content); - /** - * This method takes the content as a FrameSet; if reframe=false, - * the caller is resposnible for ensuring that the header and - * content frames in that set are correct for this connection - * (right flags, right fragmentation etc). If reframe=true, then - * the header and content from the frameset will be copied and - * reframed correctly for the connection. - */ - QPID_CLIENT_EXTERN Future send(const framing::AMQBody& command, const framing::FrameSet& content, bool reframe=false); - void sendRawFrame(framing::AMQFrame& frame); - - Demux& getDemux(); - void markCompleted(const framing::SequenceNumber& id, bool cumulative, bool notifyPeer); - void markCompleted(const framing::SequenceSet& ids, bool notifyPeer); - bool isComplete(const framing::SequenceNumber& id); - bool isCompleteUpTo(const framing::SequenceNumber& id); - framing::SequenceNumber getCompleteUpTo(); - void waitForCompletion(const framing::SequenceNumber& id); - void sendCompletion(); - void sendFlush(); - - void setException(const sys::ExceptionHolder&); - - //NOTE: these are called by the network thread when the connection is closed or dies - void connectionClosed(uint16_t code, const std::string& text); - void connectionBroke(const std::string& text); - - /** Set timeout in seconds, returns actual timeout allowed by broker */ - uint32_t setTimeout(uint32_t requestedSeconds); - - /** Get timeout in seconds. */ - uint32_t getTimeout() const; - - /** - * get the Connection associated with this connection - */ - boost::shared_ptr<ConnectionImpl> getConnection(); - - void setDoClearDeliveryPropertiesExchange(bool b=true) { doClearDeliveryPropertiesExchange = b; } - - /** Suppress sending detach in destructor. Used by cluster to build session state */ - void disableAutoDetach(); - -private: - enum State { - INACTIVE, - ATTACHING, - ATTACHED, - DETACHING, - DETACHED - }; - typedef framing::AMQP_ClientOperations::SessionHandler SessionHandler; - typedef framing::AMQP_ClientOperations::ExecutionHandler ExecutionHandler; - typedef framing::AMQP_ClientOperations::MessageHandler MessageHandler; - typedef sys::StateMonitor<State, DETACHED> StateMonitor; - typedef StateMonitor::Set States; - - inline void setState(State s); - inline void waitFor(State); - - void setExceptionLH(const sys::ExceptionHolder&); // LH = lock held when called. - void detach(); - - void check() const; - void checkOpen() const; - void handleClosed(); - - void handleIn(framing::AMQFrame& frame); - void handleOut(framing::AMQFrame& frame); - /** - * Sends session controls. This case is treated slightly - * differently than command frames sent by the application via - * handleOut(); session controlsare not subject to bounds checking - * on the outgoing frame queue. - */ - void proxyOut(framing::AMQFrame& frame); - void sendFrame(framing::AMQFrame& frame, bool canBlock); - void deliver(framing::AMQFrame& frame); - - Future sendCommand(const framing::AMQBody&, const framing::MethodContent* = 0); - void sendContent(const framing::MethodContent&); - void waitForCompletionImpl(const framing::SequenceNumber& id); - - void sendCompletionImpl(); - - // Note: Following methods are called by network thread in - // response to session controls from the broker - void attach(const std::string& name, bool force); - void attached(const std::string& name); - void detach(const std::string& name); - void detached(const std::string& name, uint8_t detachCode); - void requestTimeout(uint32_t timeout); - void timeout(uint32_t timeout); - void commandPoint(const framing::SequenceNumber& commandId, uint64_t commandOffset); - void expected(const framing::SequenceSet& commands, const framing::Array& fragments); - void confirmed(const framing::SequenceSet& commands, const framing::Array& fragments); - void completed(const framing::SequenceSet& commands, bool timelyReply); - void knownCompleted(const framing::SequenceSet& commands); - void flush(bool expected, bool confirmed, bool completed); - void gap(const framing::SequenceSet& commands); - - // Note: Following methods are called by network thread in - // response to execution commands from the broker - void sync(); - void result(const framing::SequenceNumber& commandId, const std::string& value); - void exception(uint16_t errorCode, - const framing::SequenceNumber& commandId, - uint8_t classCode, - uint8_t commandCode, - uint8_t fieldIndex, - const std::string& description, - const framing::FieldTable& errorInfo); - - // Note: Following methods are called by network thread in - // response to message commands from the broker - // EXCEPT Message.Transfer - void accept(const qpid::framing::SequenceSet&); - void reject(const qpid::framing::SequenceSet&, uint16_t, const std::string&); - void release(const qpid::framing::SequenceSet&, bool); - qpid::framing::MessageResumeResult resume(const std::string&, const std::string&); - void setFlowMode(const std::string&, uint8_t); - void flow(const std::string&, uint8_t, uint32_t); - void stop(const std::string&); - - - sys::ExceptionHolder exceptionHolder; - mutable StateMonitor state; - mutable sys::Semaphore sendLock; - uint32_t detachedLifetime; - const uint64_t maxFrameSize; - const SessionId id; - - boost::shared_ptr<ConnectionImpl> connection; - - framing::FrameHandler::MemFunRef<SessionImpl, &SessionImpl::proxyOut> ioHandler; - framing::ChannelHandler channel; - framing::AMQP_ServerProxy::Session proxy; - - Results results; - Demux demux; - framing::FrameSet::shared_ptr arriving; - - framing::SequenceSet incompleteIn;//incoming commands that are as yet incomplete - framing::SequenceSet completedIn;//incoming commands that are have completed - framing::SequenceSet incompleteOut;//outgoing commands not yet known to be complete - framing::SequenceSet completedOut;//outgoing commands that we know to be completed - framing::SequenceNumber nextIn; - framing::SequenceNumber nextOut; - - SessionState sessionState; - - // Only keep track of message credit - sys::Semaphore* sendMsgCredit; - - bool doClearDeliveryPropertiesExchange; - - bool autoDetach; - - friend class client::SessionHandler; -}; - -}} // namespace qpid::client - -#endif diff --git a/cpp/src/qpid/client/SslConnector.cpp b/cpp/src/qpid/client/SslConnector.cpp deleted file mode 100644 index 35c7e6bdf6..0000000000 --- a/cpp/src/qpid/client/SslConnector.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Connector.h" - -#include "config.h" -#include "qpid/client/Bounds.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/InitiationHandler.h" -#include "qpid/sys/ssl/util.h" -#include "qpid/sys/ssl/SslIo.h" -#include "qpid/sys/ssl/SslSocket.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/Msg.h" - -#include <iostream> -#include <map> -#include <boost/bind.hpp> -#include <boost/format.hpp> - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::sys::ssl; -using namespace qpid::framing; -using boost::format; -using boost::str; - - -class SslConnector : public Connector -{ - struct Buff; - - /** Batch up frames for writing to aio. */ - class Writer : public framing::FrameHandler { - typedef sys::ssl::SslIOBufferBase BufferBase; - typedef std::vector<framing::AMQFrame> Frames; - - const uint16_t maxFrameSize; - sys::Mutex lock; - sys::ssl::SslIO* aio; - BufferBase* buffer; - Frames frames; - size_t lastEof; // Position after last EOF in frames - framing::Buffer encode; - size_t framesEncoded; - std::string identifier; - Bounds* bounds; - - void writeOne(); - void newBuffer(); - - public: - - Writer(uint16_t maxFrameSize, Bounds*); - ~Writer(); - void init(std::string id, sys::ssl::SslIO*); - void handle(framing::AMQFrame&); - void write(sys::ssl::SslIO&); - }; - - const uint16_t maxFrameSize; - framing::ProtocolVersion version; - bool initiated; - SecuritySettings securitySettings; - - sys::Mutex closedLock; - bool closed; - - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - framing::InitiationHandler* initialiser; - framing::OutputHandler* output; - - Writer writer; - - sys::ssl::SslSocket socket; - - sys::ssl::SslIO* aio; - Poller::shared_ptr poller; - - ~SslConnector(); - - void readbuff(qpid::sys::ssl::SslIO&, qpid::sys::ssl::SslIOBufferBase*); - void writebuff(qpid::sys::ssl::SslIO&); - void writeDataBlock(const framing::AMQDataBlock& data); - void eof(qpid::sys::ssl::SslIO&); - void disconnected(qpid::sys::ssl::SslIO&); - - std::string identifier; - - void connect(const std::string& host, int port); - void init(); - void close(); - void send(framing::AMQFrame& frame); - void abort() {} // TODO: Need to fix for heartbeat timeouts to work - - void setInputHandler(framing::InputHandler* handler); - void setShutdownHandler(sys::ShutdownHandler* handler); - sys::ShutdownHandler* getShutdownHandler() const; - framing::OutputHandler* getOutputHandler(); - const std::string& getIdentifier() const; - const SecuritySettings* getSecuritySettings(); - void socketClosed(qpid::sys::ssl::SslIO&, const qpid::sys::ssl::SslSocket&); - -public: - SslConnector(Poller::shared_ptr p, framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -struct SslConnector::Buff : public SslIO::BufferBase { - Buff(size_t size) : SslIO::BufferBase(new char[size], size) {} - ~Buff() { delete [] bytes;} -}; - -// Static constructor which registers connector here -namespace { - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) { - return new SslConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - try { - SslOptions options; - options.parse (0, 0, QPIDC_CONF_FILE, true); - if (options.certDbPath.empty()) { - QPID_LOG(info, "SSL connector not enabled, you must set QPID_SSL_CERT_DB to enable it."); - } else { - initNSS(options); - Connector::registerFactory("ssl", &create); - } - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL connector: " << e.what()); - } - }; - - ~StaticInit() { shutdownNSS(); } - } init; -} - -SslConnector::SslConnector(Poller::shared_ptr p, - ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : maxFrameSize(settings.maxFrameSize), - version(ver), - initiated(false), - closed(true), - shutdownHandler(0), - writer(maxFrameSize, cimpl), - aio(0), - poller(p) -{ - QPID_LOG(debug, "SslConnector created for " << version.toString()); - - if (settings.sslCertName != "") { - QPID_LOG(debug, "ssl-cert-name = " << settings.sslCertName); - socket.setCertName(settings.sslCertName); - } -} - -SslConnector::~SslConnector() { - close(); -} - -void SslConnector::connect(const std::string& host, int port){ - Mutex::ScopedLock l(closedLock); - assert(closed); - try { - socket.connect(host, port); - } catch (const std::exception& e) { - socket.close(); - throw ConnectionException(framing::connection::CLOSE_CODE_FRAMING_ERROR, e.what()); - } - - identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress()); - closed = false; - aio = new SslIO(socket, - boost::bind(&SslConnector::readbuff, this, _1, _2), - boost::bind(&SslConnector::eof, this, _1), - boost::bind(&SslConnector::disconnected, this, _1), - boost::bind(&SslConnector::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&SslConnector::writebuff, this, _1)); - writer.init(identifier, aio); -} - -void SslConnector::init(){ - Mutex::ScopedLock l(closedLock); - ProtocolInitiation init(version); - writeDataBlock(init); - for (int i = 0; i < 32; i++) { - aio->queueReadBuffer(new Buff(maxFrameSize)); - } - aio->start(poller); -} - -void SslConnector::close() { - Mutex::ScopedLock l(closedLock); - if (!closed) { - closed = true; - if (aio) - aio->queueWriteClose(); - } -} - -void SslConnector::socketClosed(SslIO&, const SslSocket&) { - if (aio) - aio->queueForDeletion(); - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void SslConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void SslConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -OutputHandler* SslConnector::getOutputHandler() { - return this; -} - -sys::ShutdownHandler* SslConnector::getShutdownHandler() const { - return shutdownHandler; -} - -const std::string& SslConnector::getIdentifier() const { - return identifier; -} - -void SslConnector::send(AMQFrame& frame) { - writer.handle(frame); -} - -SslConnector::Writer::Writer(uint16_t s, Bounds* b) : maxFrameSize(s), aio(0), buffer(0), lastEof(0), bounds(b) -{ -} - -SslConnector::Writer::~Writer() { delete buffer; } - -void SslConnector::Writer::init(std::string id, sys::ssl::SslIO* a) { - Mutex::ScopedLock l(lock); - identifier = id; - aio = a; - newBuffer(); -} -void SslConnector::Writer::handle(framing::AMQFrame& frame) { - Mutex::ScopedLock l(lock); - frames.push_back(frame); - if (frame.getEof() || (bounds && bounds->getCurrentSize() >= maxFrameSize)) { - lastEof = frames.size(); - aio->notifyPendingWrite(); - } - QPID_LOG(trace, "SENT " << identifier << ": " << frame); -} - -void SslConnector::Writer::writeOne() { - assert(buffer); - framesEncoded = 0; - - buffer->dataStart = 0; - buffer->dataCount = encode.getPosition(); - aio->queueWrite(buffer); - newBuffer(); -} - -void SslConnector::Writer::newBuffer() { - buffer = aio->getQueuedBuffer(); - if (!buffer) buffer = new Buff(maxFrameSize); - encode = framing::Buffer(buffer->bytes, buffer->byteCount); - framesEncoded = 0; -} - -// Called in IO thread. -void SslConnector::Writer::write(sys::ssl::SslIO&) { - Mutex::ScopedLock l(lock); - assert(buffer); - size_t bytesWritten(0); - for (size_t i = 0; i < lastEof; ++i) { - AMQFrame& frame = frames[i]; - uint32_t size = frame.encodedSize(); - if (size > encode.available()) writeOne(); - assert(size <= encode.available()); - frame.encode(encode); - ++framesEncoded; - bytesWritten += size; - } - frames.erase(frames.begin(), frames.begin()+lastEof); - lastEof = 0; - if (bounds) bounds->reduce(bytesWritten); - if (encode.getPosition() > 0) writeOne(); -} - -void SslConnector::readbuff(SslIO& aio, SslIO::BufferBase* buff) { - framing::Buffer in(buff->bytes+buff->dataStart, buff->dataCount); - - if (!initiated) { - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - //TODO: check the version is correct - QPID_LOG(debug, "RECV " << identifier << " INIT(" << protocolInit << ")"); - } - initiated = true; - } - AMQFrame frame; - while(frame.decode(in)){ - QPID_LOG(trace, "RECV " << identifier << ": " << frame); - input->received(frame); - } - // TODO: unreading needs to go away, and when we can cope - // with multiple sub-buffers in the general buffer scheme, it will - if (in.available() != 0) { - // Adjust buffer for used bytes and then "unread them" - buff->dataStart += buff->dataCount-in.available(); - buff->dataCount = in.available(); - aio.unread(buff); - } else { - // Give whole buffer back to aio subsystem - aio.queueReadBuffer(buff); - } -} - -void SslConnector::writebuff(SslIO& aio_) { - writer.write(aio_); -} - -void SslConnector::writeDataBlock(const AMQDataBlock& data) { - SslIO::BufferBase* buff = new Buff(maxFrameSize); - framing::Buffer out(buff->bytes, buff->byteCount); - data.encode(out); - buff->dataCount = data.encodedSize(); - aio->queueWrite(buff); -} - -void SslConnector::eof(SslIO&) { - close(); -} - -void SslConnector::disconnected(SslIO&) { - close(); - socketClosed(*aio, socket); -} - -const SecuritySettings* SslConnector::getSecuritySettings() -{ - securitySettings.ssf = socket.getKeyLen(); - securitySettings.authid = "dummy";//set to non-empty string to enable external authentication - return &securitySettings; -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/StateManager.cpp b/cpp/src/qpid/client/StateManager.cpp deleted file mode 100644 index 839d92abdc..0000000000 --- a/cpp/src/qpid/client/StateManager.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/StateManager.h" -#include "qpid/framing/amqp_framing.h" - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; - -StateManager::StateManager(int s) : state(s) {} - -void StateManager::waitForStateChange(int current) -{ - Monitor::ScopedLock l(stateLock); - while (state == current) { - stateLock.wait(); - } -} - -void StateManager::waitFor(int desired) -{ - Monitor::ScopedLock l(stateLock); - while (state != desired) { - stateLock.wait(); - } -} - -void StateManager::waitFor(std::set<int> desired) -{ - Monitor::ScopedLock l(stateLock); - while (desired.find(state) == desired.end()) { - stateLock.wait(); - } -} - -bool StateManager::waitFor(int desired, qpid::sys::Duration timeout) -{ - AbsTime end(now(), timeout); - Monitor::ScopedLock l(stateLock); - while (state != desired && now() < end) { - stateLock.wait(end); - } - return state == desired; -} - -bool StateManager::waitFor(std::set<int> desired, qpid::sys::Duration timeout) -{ - AbsTime end(now(), timeout); - Monitor::ScopedLock l(stateLock); - while (desired.find(state) == desired.end() && now() < end) { - stateLock.wait(end); - } - return desired.find(state) != desired.end(); -} - - -void StateManager::setState(int s) -{ - Monitor::ScopedLock l(stateLock); - state = s; - stateLock.notifyAll(); -} - -bool StateManager::setState(int s, int expected) -{ - Monitor::ScopedLock l(stateLock); - if (state == expected) { - state = s; - stateLock.notifyAll(); - return true; - } else { - return false; - } -} - -int StateManager::getState() const -{ - Monitor::ScopedLock l(stateLock); - return state; -} - diff --git a/cpp/src/qpid/client/StateManager.h b/cpp/src/qpid/client/StateManager.h deleted file mode 100644 index f06dbc493c..0000000000 --- a/cpp/src/qpid/client/StateManager.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _StateManager_ -#define _StateManager_ - -#include <set> -#include "qpid/sys/Monitor.h" - -namespace qpid { -namespace client { - -///@internal -class StateManager -{ - int state; - mutable sys::Monitor stateLock; - -public: - StateManager(int initial); - void setState(int state); - bool setState(int state, int expected); - int getState() const ; - void waitForStateChange(int current); - void waitFor(std::set<int> states); - void waitFor(int state); - bool waitFor(std::set<int> states, qpid::sys::Duration); - bool waitFor(int state, qpid::sys::Duration); -}; - -}} - -#endif diff --git a/cpp/src/qpid/client/Subscription.cpp b/cpp/src/qpid/client/Subscription.cpp deleted file mode 100644 index 988f372604..0000000000 --- a/cpp/src/qpid/client/Subscription.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/Subscription.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/CompletionImpl.h" -#include "qpid/client/PrivateImplRef.h" -#include "qpid/framing/enum.h" - -namespace qpid { -namespace client { - -typedef PrivateImplRef<Subscription> PI; -Subscription::Subscription(SubscriptionImpl* p) { PI::ctor(*this, p); } -Subscription::~Subscription() { PI::dtor(*this); } -Subscription::Subscription(const Subscription& c) : Handle<SubscriptionImpl>() { PI::copy(*this, c); } -Subscription& Subscription::operator=(const Subscription& c) { return PI::assign(*this, c); } - - -std::string Subscription::getName() const { return impl->getName(); } -std::string Subscription::getQueue() const { return impl->getQueue(); } -const SubscriptionSettings& Subscription::getSettings() const { return impl->getSettings(); } -void Subscription::setFlowControl(const FlowControl& f) { impl->setFlowControl(f); } -void Subscription::setAutoAck(unsigned int n) { impl->setAutoAck(n); } -SequenceSet Subscription::getUnacquired() const { return impl->getUnacquired(); } -SequenceSet Subscription::getUnaccepted() const { return impl->getUnaccepted(); } -void Subscription::acquire(const SequenceSet& messageIds) { impl->acquire(messageIds); } -void Subscription::accept(const SequenceSet& messageIds) { impl->accept(messageIds); } -void Subscription::release(const SequenceSet& messageIds) { impl->release(messageIds); } -Session Subscription::getSession() const { return impl->getSession(); } -SubscriptionManager Subscription::getSubscriptionManager() { return impl->getSubscriptionManager(); } -void Subscription::cancel() { impl->cancel(); } -void Subscription::grantMessageCredit(uint32_t value) { impl->grantCredit(framing::message::CREDIT_UNIT_MESSAGE, value); } -void Subscription::grantByteCredit(uint32_t value) { impl->grantCredit(framing::message::CREDIT_UNIT_BYTE, value); } -}} // namespace qpid::client - - diff --git a/cpp/src/qpid/client/SubscriptionImpl.cpp b/cpp/src/qpid/client/SubscriptionImpl.cpp deleted file mode 100644 index a8a0b47d94..0000000000 --- a/cpp/src/qpid/client/SubscriptionImpl.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/SubscriptionManagerImpl.h" -#include "qpid/client/MessageImpl.h" -#include "qpid/client/CompletionImpl.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/SubscriptionSettings.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/client/PrivateImplRef.h" - -namespace qpid { -namespace client { - -using sys::Mutex; -using framing::MessageAcquireResult; - -SubscriptionImpl::SubscriptionImpl(SubscriptionManager m, const std::string& q, const SubscriptionSettings& s, const std::string& n, MessageListener* l) - : manager(*PrivateImplRef<SubscriptionManager>::get(m)), name(n), queue(q), settings(s), listener(l) -{} - -void SubscriptionImpl::subscribe() -{ - async(manager.getSession()).messageSubscribe( - arg::queue=queue, - arg::destination=name, - arg::acceptMode=settings.acceptMode, - arg::acquireMode=settings.acquireMode, - arg::exclusive=settings.exclusive); - setFlowControl(settings.flowControl); -} - -std::string SubscriptionImpl::getName() const { return name; } - -std::string SubscriptionImpl::getQueue() const { return queue; } - -const SubscriptionSettings& SubscriptionImpl::getSettings() const { - Mutex::ScopedLock l(lock); - return settings; -} - -void SubscriptionImpl::setFlowControl(const FlowControl& f) { - Mutex::ScopedLock l(lock); - AsyncSession s=manager.getSession(); - if (&settings.flowControl != &f) settings.flowControl = f; - s.messageSetFlowMode(name, f.window); - s.messageFlow(name, CREDIT_UNIT_MESSAGE, f.messages); - s.messageFlow(name, CREDIT_UNIT_BYTE, f.bytes); - s.sync(); -} - -void SubscriptionImpl::grantCredit(framing::message::CreditUnit unit, uint32_t value) { - async(manager.getSession()).messageFlow(name, unit, value); -} - -void SubscriptionImpl::setAutoAck(size_t n) { - Mutex::ScopedLock l(lock); - settings.autoAck = n; -} - -SequenceSet SubscriptionImpl::getUnacquired() const { Mutex::ScopedLock l(lock); return unacquired; } -SequenceSet SubscriptionImpl::getUnaccepted() const { Mutex::ScopedLock l(lock); return unaccepted; } - -void SubscriptionImpl::acquire(const SequenceSet& messageIds) { - Mutex::ScopedLock l(lock); - MessageAcquireResult result = manager.getSession().messageAcquire(messageIds); - unacquired.remove(result.getTransfers()); - if (settings.acceptMode == ACCEPT_MODE_EXPLICIT) - unaccepted.add(result.getTransfers()); -} - -void SubscriptionImpl::accept(const SequenceSet& messageIds) { - Mutex::ScopedLock l(lock); - manager.getSession().messageAccept(messageIds); - unaccepted.remove(messageIds); - switch (settings.completionMode) { - case COMPLETE_ON_ACCEPT: - manager.getSession().markCompleted(messageIds, true); - break; - case COMPLETE_ON_DELIVERY: - manager.getSession().sendCompletion(); - break; - default://do nothing - break; - } -} - -void SubscriptionImpl::release(const SequenceSet& messageIds) { - Mutex::ScopedLock l(lock); - manager.getSession().messageRelease(messageIds); - if (settings.acceptMode == ACCEPT_MODE_EXPLICIT) - unaccepted.remove(messageIds); -} - -Session SubscriptionImpl::getSession() const { return manager.getSession(); } - -SubscriptionManager SubscriptionImpl::getSubscriptionManager() { return SubscriptionManager(&manager); } - -void SubscriptionImpl::cancel() { manager.cancel(name); } - -void SubscriptionImpl::received(Message& m) { - Mutex::ScopedLock l(lock); - MessageImpl& mi = *MessageImpl::get(m); - if (mi.getMethod().getAcquireMode() == ACQUIRE_MODE_NOT_ACQUIRED) - unacquired.add(m.getId()); - else if (mi.getMethod().getAcceptMode() == ACCEPT_MODE_EXPLICIT) - unaccepted.add(m.getId()); - - if (listener) { - Mutex::ScopedUnlock u(lock); - listener->received(m); - } - - if (settings.completionMode == COMPLETE_ON_DELIVERY) { - manager.getSession().markCompleted(m.getId(), false, false); - } - if (settings.autoAck) { - if (unaccepted.size() >= settings.autoAck) { - async(manager.getSession()).messageAccept(unaccepted); - switch (settings.completionMode) { - case COMPLETE_ON_ACCEPT: - manager.getSession().markCompleted(unaccepted, true); - break; - case COMPLETE_ON_DELIVERY: - manager.getSession().sendCompletion(); - break; - default://do nothing - break; - } - unaccepted.clear(); - } - } -} - -Demux::QueuePtr SubscriptionImpl::divert() -{ - Session session(manager.getSession()); - Demux& demux = SessionBase_0_10Access(session).get()->getDemux(); - demuxRule = std::auto_ptr<ScopedDivert>(new ScopedDivert(name, demux)); - return demuxRule->getQueue(); -} - -void SubscriptionImpl::cancelDiversion() { - demuxRule.reset(); -} - -}} // namespace qpid::client - diff --git a/cpp/src/qpid/client/SubscriptionImpl.h b/cpp/src/qpid/client/SubscriptionImpl.h deleted file mode 100644 index da77213423..0000000000 --- a/cpp/src/qpid/client/SubscriptionImpl.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef QPID_CLIENT_SUBSCRIPTIONIMPL_H -#define QPID_CLIENT_SUBSCRIPTIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SubscriptionSettings.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/Session.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/Demux.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/Mutex.h" -#include "qpid/RefCounted.h" -#include "qpid/client/ClientImportExport.h" -#include <memory> - -namespace qpid { -namespace client { - -class SubscriptionManager; -class SubscriptionManagerImpl; - -class SubscriptionImpl : public RefCounted, public MessageListener { - public: - QPID_CLIENT_EXTERN SubscriptionImpl(SubscriptionManager, const std::string& queue, - const SubscriptionSettings&, const std::string& name, MessageListener* =0); - - /** The name of the subsctription, used as the "destination" for messages from the broker. - * Usually the same as the queue name but can be set differently. - */ - QPID_CLIENT_EXTERN std::string getName() const; - - /** Name of the queue this subscription subscribes to */ - QPID_CLIENT_EXTERN std::string getQueue() const; - - /** Get the flow control and acknowledgement settings for this subscription */ - QPID_CLIENT_EXTERN const SubscriptionSettings& getSettings() const; - - /** Set the flow control parameters */ - QPID_CLIENT_EXTERN void setFlowControl(const FlowControl&); - - /** Automatically acknowledge (acquire and accept) batches of n messages. - * You can disable auto-acknowledgement by setting n=0, and use acquire() and accept() - * to manually acquire and accept messages. - */ - QPID_CLIENT_EXTERN void setAutoAck(size_t n); - - /** Get the set of ID's for messages received by this subscription but not yet acquired. - * This will always be empty if acquireMode=ACQUIRE_MODE_PRE_ACQUIRED - */ - QPID_CLIENT_EXTERN SequenceSet getUnacquired() const; - - /** Get the set of ID's for messages acquired by this subscription but not yet accepted. */ - QPID_CLIENT_EXTERN SequenceSet getUnaccepted() const; - - /** Acquire messageIds and remove them from the un-acquired set for the session. */ - QPID_CLIENT_EXTERN void acquire(const SequenceSet& messageIds); - - /** Accept messageIds and remove them from the un-accepted set for the session. */ - QPID_CLIENT_EXTERN void accept(const SequenceSet& messageIds); - - /** Release messageIds and remove them from the un-accepted set for the session. */ - QPID_CLIENT_EXTERN void release(const SequenceSet& messageIds); - - /** Get the session associated with this subscription */ - QPID_CLIENT_EXTERN Session getSession() const; - - /** Get the subscription manager associated with this subscription */ - QPID_CLIENT_EXTERN SubscriptionManager getSubscriptionManager(); - - /** Send subscription request and issue appropriate flow control commands. */ - QPID_CLIENT_EXTERN void subscribe(); - - /** Cancel the subscription. */ - QPID_CLIENT_EXTERN void cancel(); - - /** Grant specified credit for this subscription **/ - QPID_CLIENT_EXTERN void grantCredit(framing::message::CreditUnit unit, uint32_t value); - - QPID_CLIENT_EXTERN void received(Message&); - - /** - * Set up demux diversion for messages sent to this subscription - */ - Demux::QueuePtr divert(); - /** - * Cancel any demux diversion that may have been setup for this - * subscription - */ - QPID_CLIENT_EXTERN void cancelDiversion(); - - private: - - mutable sys::Mutex lock; - SubscriptionManagerImpl& manager; - std::string name, queue; - SubscriptionSettings settings; - framing::SequenceSet unacquired, unaccepted; - MessageListener* listener; - std::auto_ptr<ScopedDivert> demuxRule; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SUBSCRIPTIONIMPL_H*/ diff --git a/cpp/src/qpid/client/SubscriptionManager.cpp b/cpp/src/qpid/client/SubscriptionManager.cpp deleted file mode 100644 index 485361d577..0000000000 --- a/cpp/src/qpid/client/SubscriptionManager.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/SubscriptionManagerImpl.h" -#include "qpid/client/PrivateImplRef.h" - - -namespace qpid { -namespace client { - -typedef PrivateImplRef<SubscriptionManager> PI; - -SubscriptionManager::SubscriptionManager(const Session& s) { PI::ctor(*this, new SubscriptionManagerImpl(s)); } -SubscriptionManager::SubscriptionManager(SubscriptionManagerImpl* i) { PI::ctor(*this, i); } -SubscriptionManager::SubscriptionManager(const SubscriptionManager& x) : Runnable(), Handle<SubscriptionManagerImpl>() { PI::copy(*this, x); } -SubscriptionManager::~SubscriptionManager() { PI::dtor(*this); } -SubscriptionManager& SubscriptionManager::operator=(const SubscriptionManager& x) { return PI::assign(*this, x); } - -Subscription SubscriptionManager::subscribe( - MessageListener& listener, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ return impl->subscribe(listener, q, ss, n); } - -Subscription SubscriptionManager::subscribe( - LocalQueue& lq, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ return impl->subscribe(lq, q, ss, n); } - - -Subscription SubscriptionManager::subscribe( - MessageListener& listener, const std::string& q, const std::string& n) -{ return impl->subscribe(listener, q, n); } - - -Subscription SubscriptionManager::subscribe( - LocalQueue& lq, const std::string& q, const std::string& n) -{ return impl->subscribe(lq, q, n); } - -void SubscriptionManager::cancel(const std::string& dest) { return impl->cancel(dest); } - -void SubscriptionManager::setAutoStop(bool set) { impl->setAutoStop(set); } - -void SubscriptionManager::run() { impl->run(); } - -void SubscriptionManager::start() { impl->start(); } - -void SubscriptionManager::wait() { impl->wait(); } - -void SubscriptionManager::stop() { impl->stop(); } - -bool SubscriptionManager::get(Message& result, const std::string& queue, sys::Duration timeout) { - return impl->get(result, queue, timeout); -} - -Message SubscriptionManager::get(const std::string& queue, sys::Duration timeout) { - return impl->get(queue, timeout); -} - -Session SubscriptionManager::getSession() const { return impl->getSession(); } - -Subscription SubscriptionManager::getSubscription(const std::string& name) const { - return impl->getSubscription(name); -} -void SubscriptionManager::registerFailoverHandler (boost::function<void ()> fh) { - impl->registerFailoverHandler(fh); -} - -void SubscriptionManager::setFlowControl(const std::string& name, const FlowControl& flow) { - impl->setFlowControl(name, flow); -} - -void SubscriptionManager::setDefaultSettings(const SubscriptionSettings& s){ - impl->setDefaultSettings(s); -} - -void SubscriptionManager::setFlowControl(const std::string& name, uint32_t messages, uint32_t bytes, bool window) { - impl->setFlowControl(name, FlowControl(messages, bytes, window)); -} - -void SubscriptionManager::setFlowControl(uint32_t messages, uint32_t bytes, bool window) { - impl->setFlowControl(messages, bytes, window); -} - -void SubscriptionManager::setAcceptMode(AcceptMode mode) { impl->setAcceptMode(mode); } -void SubscriptionManager::setAcquireMode(AcquireMode mode) { impl->setAcquireMode(mode); } - -}} // namespace qpid::client - - diff --git a/cpp/src/qpid/client/SubscriptionManagerImpl.cpp b/cpp/src/qpid/client/SubscriptionManagerImpl.cpp deleted file mode 100644 index a558d90be8..0000000000 --- a/cpp/src/qpid/client/SubscriptionManagerImpl.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/SubscriptionManagerImpl.h" -#include "qpid/client/SubscriptionImpl.h" -#include "qpid/client/LocalQueueImpl.h" -#include "qpid/client/PrivateImplRef.h" -#include <qpid/client/Dispatcher.h> -#include <qpid/client/Session.h> -#include <qpid/client/MessageListener.h> -#include <qpid/framing/Uuid.h> -#include <set> -#include <sstream> - - -namespace qpid { -namespace client { - -SubscriptionManagerImpl::SubscriptionManagerImpl(const Session& s) - : dispatcher(s), session(s), autoStop(true) -{} - -Subscription SubscriptionManagerImpl::subscribe( - MessageListener& listener, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ - sys::Mutex::ScopedLock l(lock); - std::string name=n.empty() ? q:n; - boost::intrusive_ptr<SubscriptionImpl> si = new SubscriptionImpl(SubscriptionManager(this), q, ss, name, &listener); - dispatcher.listen(si); - //issue subscription request after listener is registered with dispatcher - si->subscribe(); - return subscriptions[name] = Subscription(si.get()); -} - -Subscription SubscriptionManagerImpl::subscribe( - LocalQueue& lq, const std::string& q, const SubscriptionSettings& ss, const std::string& n) -{ - sys::Mutex::ScopedLock l(lock); - std::string name=n.empty() ? q:n; - boost::intrusive_ptr<SubscriptionImpl> si = new SubscriptionImpl(SubscriptionManager(this), q, ss, name, 0); - boost::intrusive_ptr<LocalQueueImpl> lqi = PrivateImplRef<LocalQueue>::get(lq); - lqi->queue=si->divert(); - si->subscribe(); - lqi->subscription = Subscription(si.get()); - return subscriptions[name] = lqi->subscription; -} - -Subscription SubscriptionManagerImpl::subscribe( - MessageListener& listener, const std::string& q, const std::string& n) -{ - return subscribe(listener, q, defaultSettings, n); -} - -Subscription SubscriptionManagerImpl::subscribe( - LocalQueue& lq, const std::string& q, const std::string& n) -{ - return subscribe(lq, q, defaultSettings, n); -} - -void SubscriptionManagerImpl::cancel(const std::string& dest) -{ - sys::Mutex::ScopedLock l(lock); - std::map<std::string, Subscription>::iterator i = subscriptions.find(dest); - if (i != subscriptions.end()) { - sync(session).messageCancel(dest); - dispatcher.cancel(dest); - Subscription s = i->second; - if (s.isValid()) - PrivateImplRef<Subscription>::get(s)->cancelDiversion(); - subscriptions.erase(i); - } -} - -void SubscriptionManagerImpl::setAutoStop(bool set) { autoStop=set; } - -void SubscriptionManagerImpl::run() -{ - dispatcher.setAutoStop(autoStop); - dispatcher.run(); -} - -void SubscriptionManagerImpl::start() -{ - dispatcher.setAutoStop(autoStop); - dispatcher.start(); -} - -void SubscriptionManagerImpl::wait() -{ - dispatcher.wait(); -} - -void SubscriptionManagerImpl::stop() -{ - dispatcher.stop(); -} - -bool SubscriptionManagerImpl::get(Message& result, const std::string& queue, sys::Duration timeout) { - LocalQueue lq; - std::string unique = framing::Uuid(true).str(); - subscribe(lq, queue, SubscriptionSettings(FlowControl::messageCredit(1)), unique); - SubscriptionManager sm(this); - AutoCancel ac(sm, unique); - //first wait for message to be delivered if a timeout has been specified - if (timeout && lq.get(result, timeout)) - return true; - //make sure message is not on queue before final check - sync(session).messageFlush(unique); - return lq.get(result, 0); -} - -Message SubscriptionManagerImpl::get(const std::string& queue, sys::Duration timeout) { - Message result; - if (!get(result, queue, timeout)) - throw Exception("Timed out waiting for a message"); - return result; -} - -Session SubscriptionManagerImpl::getSession() const { return session; } - -Subscription SubscriptionManagerImpl::getSubscription(const std::string& name) const { - sys::Mutex::ScopedLock l(lock); - std::map<std::string, Subscription>::const_iterator i = subscriptions.find(name); - if (i == subscriptions.end()) - throw Exception(QPID_MSG("Subscription not found: " << name)); - return i->second; -} - -void SubscriptionManagerImpl::registerFailoverHandler (boost::function<void ()> fh) { - dispatcher.registerFailoverHandler(fh); -} - -void SubscriptionManagerImpl::setFlowControl(const std::string& name, const FlowControl& flow) { - getSubscription(name).setFlowControl(flow); -} - -void SubscriptionManagerImpl::setFlowControl(const std::string& name, uint32_t messages, uint32_t bytes, bool window) { - setFlowControl(name, FlowControl(messages, bytes, window)); -} - -}} // namespace qpid::client - - diff --git a/cpp/src/qpid/client/SubscriptionManagerImpl.h b/cpp/src/qpid/client/SubscriptionManagerImpl.h deleted file mode 100644 index 6376a05c45..0000000000 --- a/cpp/src/qpid/client/SubscriptionManagerImpl.h +++ /dev/null @@ -1,278 +0,0 @@ -#ifndef QPID_CLIENT_SUBSCRIPTIONMANAGERIMPL_H -#define QPID_CLIENT_SUBSCRIPTIONMANAGERIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Mutex.h" -#include <qpid/client/Dispatcher.h> -#include <qpid/client/Completion.h> -#include <qpid/client/Session.h> -#include <qpid/client/AsyncSession.h> -#include <qpid/client/MessageListener.h> -#include <qpid/client/LocalQueue.h> -#include <qpid/client/Subscription.h> -#include <qpid/sys/Runnable.h> -#include <qpid/RefCounted.h> -#include <set> -#include <sstream> - -namespace qpid { -namespace client { - -/** - * A class to help create and manage subscriptions. - * - * Set up your subscriptions, then call run() to have messages - * delivered. - * - * \ingroup clientapi - * - * \details - * - * <h2>Subscribing and canceling subscriptions</h2> - * - * <ul> - * <li> - * <p>subscribe()</p> - * <pre> SubscriptionManager subscriptions(session); - * Listener listener(subscriptions); - * subscriptions.subscribe(listener, myQueue);</pre> - * <pre> SubscriptionManager subscriptions(session); - * LocalQueue local_queue; - * subscriptions.subscribe(local_queue, string("message_queue"));</pre></li> - * <li> - * <p>cancel()</p> - * <pre>subscriptions.cancel();</pre></li> - * </ul> - * - * <h2>Waiting for messages (and returning)</h2> - * - * <ul> - * <li> - * <p>run()</p> - * <pre> // Give up control to receive messages - * subscriptions.run();</pre></li> - * <li> - * <p>stop()</p> - * <pre>.// Use this code in a listener to return from run() - * subscriptions.stop();</pre></li> - * <li> - * <p>setAutoStop()</p> - * <pre>.// Return from subscriptions.run() when last subscription is cancelled - *.subscriptions.setAutoStop(true); - *.subscriptons.run(); - * </pre></li> - * <li> - * <p>Ending a subscription in a listener</p> - * <pre> - * void Listener::received(Message& message) { - * - * if (message.getData() == "That's all, folks!") { - * subscriptions.cancel(message.getDestination()); - * } - * } - * </pre> - * </li> - * </ul> - * - */ -class SubscriptionManagerImpl : public sys::Runnable, public RefCounted -{ - public: - /** Create a new SubscriptionManagerImpl associated with a session */ - SubscriptionManagerImpl(const Session& session); - - /** - * Subscribe a MessagesListener to receive messages from queue. - * - * Provide your own subclass of MessagesListener to process - * incoming messages. It will be called for each message received. - * - *@param listener Listener object to receive messages. - *@param queue Name of the queue to subscribe to. - *@param settings settings for the subscription. - *@param name unique destination name for the subscription, defaults to queue name. - */ - Subscription subscribe(MessageListener& listener, - const std::string& queue, - const SubscriptionSettings& settings, - const std::string& name=std::string()); - - /** - * Subscribe a LocalQueue to receive messages from queue. - * - * Incoming messages are stored in the queue for you to retrieve. - * - *@param queue Name of the queue to subscribe to. - *@param flow initial FlowControl for the subscription. - *@param name unique destination name for the subscription, defaults to queue name. - * If not specified, the queue name is used. - */ - Subscription subscribe(LocalQueue& localQueue, - const std::string& queue, - const SubscriptionSettings& settings, - const std::string& name=std::string()); - - /** - * Subscribe a MessagesListener to receive messages from queue. - * - * Provide your own subclass of MessagesListener to process - * incoming messages. It will be called for each message received. - * - *@param listener Listener object to receive messages. - *@param queue Name of the queue to subscribe to. - *@param name unique destination name for the subscription, defaults to queue name. - * If not specified, the queue name is used. - */ - Subscription subscribe(MessageListener& listener, - const std::string& queue, - const std::string& name=std::string()); - - /** - * Subscribe a LocalQueue to receive messages from queue. - * - * Incoming messages are stored in the queue for you to retrieve. - * - *@param queue Name of the queue to subscribe to. - *@param name unique destination name for the subscription, defaults to queue name. - * If not specified, the queue name is used. - */ - Subscription subscribe(LocalQueue& localQueue, - const std::string& queue, - const std::string& name=std::string()); - - - /** Get a single message from a queue. - *@param result is set to the message from the queue. - *@param timeout wait up this timeout for a message to appear. - *@return true if result was set, false if no message available after timeout. - */ - bool get(Message& result, const std::string& queue, sys::Duration timeout=0); - - /** Get a single message from a queue. - *@param timeout wait up this timeout for a message to appear. - *@return message from the queue. - *@throw Exception if the timeout is exceeded. - */ - Message get(const std::string& queue, sys::Duration timeout=sys::TIME_INFINITE); - - /** Get a subscription by name. - *@throw Exception if not found. - */ - Subscription getSubscription(const std::string& name) const; - - /** Cancel a subscription. See also: Subscription.cancel() */ - void cancel(const std::string& name); - - /** Deliver messages in the current thread until stop() is called. - * Only one thread may be running in a SubscriptionManager at a time. - * @see run - */ - void run(); - - /** Start a new thread to deliver messages. - * Only one thread may be running in a SubscriptionManager at a time. - * @see start - */ - void start(); - - /** - * Wait for the thread started by a call to start() to complete. - */ - void wait(); - - /** If set true, run() will stop when all subscriptions - * are cancelled. If false, run will only stop when stop() - * is called. True by default. - */ - void setAutoStop(bool set=true); - - /** Stop delivery. Causes run() to return, or the thread started with start() to exit. */ - void stop(); - - static const uint32_t UNLIMITED=0xFFFFFFFF; - - /** Set the flow control for a subscription. */ - void setFlowControl(const std::string& name, const FlowControl& flow); - - /** Set the flow control for a subscription. - *@param name: name of the subscription. - *@param messages: message credit. - *@param bytes: byte credit. - *@param window: if true use window-based flow control. - */ - void setFlowControl(const std::string& name, uint32_t messages, uint32_t bytes, bool window=true); - - /** Set the default settings for subscribe() calls that don't - * include a SubscriptionSettings parameter. - */ - void setDefaultSettings(const SubscriptionSettings& s) { defaultSettings = s; } - - /** Get the default settings for subscribe() calls that don't - * include a SubscriptionSettings parameter. - */ - const SubscriptionSettings& getDefaultSettings() const { return defaultSettings; } - - /** Get the default settings for subscribe() calls that don't - * include a SubscriptionSettings parameter. - */ - SubscriptionSettings& getDefaultSettings() { return defaultSettings; } - - /** - * Set the default flow control settings for subscribe() calls - * that don't include a SubscriptionSettings parameter. - * - *@param messages: message credit. - *@param bytes: byte credit. - *@param window: if true use window-based flow control. - */ - void setFlowControl(uint32_t messages, uint32_t bytes, bool window=true) { - defaultSettings.flowControl = FlowControl(messages, bytes, window); - } - - /** - *Set the default accept-mode for subscribe() calls that don't - *include a SubscriptionSettings parameter. - */ - void setAcceptMode(AcceptMode mode) { defaultSettings.acceptMode = mode; } - - /** - * Set the default acquire-mode subscribe()s that don't specify SubscriptionSettings. - */ - void setAcquireMode(AcquireMode mode) { defaultSettings.acquireMode = mode; } - - void registerFailoverHandler ( boost::function<void ()> fh ); - - Session getSession() const; - - private: - mutable sys::Mutex lock; - qpid::client::Dispatcher dispatcher; - qpid::client::AsyncSession session; - bool autoStop; - SubscriptionSettings defaultSettings; - std::map<std::string, Subscription> subscriptions; -}; - - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_SUBSCRIPTIONMANAGERIMPL_H*/ diff --git a/cpp/src/qpid/client/TCPConnector.cpp b/cpp/src/qpid/client/TCPConnector.cpp deleted file mode 100644 index d90781b365..0000000000 --- a/cpp/src/qpid/client/TCPConnector.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/TCPConnector.h" - -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Codec.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/InitiationHandler.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/Msg.h" - -#include <iostream> -#include <boost/bind.hpp> -#include <boost/format.hpp> - -namespace qpid { -namespace client { - -using namespace qpid::sys; -using namespace qpid::framing; -using boost::format; -using boost::str; - -struct TCPConnector::Buff : public AsynchIO::BufferBase { - Buff(size_t size) : AsynchIO::BufferBase(new char[size], size) {} - ~Buff() { delete [] bytes;} -}; - -// Static constructor which registers connector here -namespace { - Connector* create(Poller::shared_ptr p, framing::ProtocolVersion v, const ConnectionSettings& s, ConnectionImpl* c) { - return new TCPConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - Connector::registerFactory("tcp", &create); - }; - } init; -} - -TCPConnector::TCPConnector(Poller::shared_ptr p, - ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : maxFrameSize(settings.maxFrameSize), - lastEof(0), - currentSize(0), - bounds(cimpl), - version(ver), - initiated(false), - closed(true), - shutdownHandler(0), - connector(0), - aio(0), - poller(p) -{ - QPID_LOG(debug, "TCPConnector created for " << version); - settings.configureSocket(socket); -} - -TCPConnector::~TCPConnector() { - close(); -} - -void TCPConnector::connect(const std::string& host, int port) { - Mutex::ScopedLock l(lock); - assert(closed); - connector = AsynchConnector::create( - socket, - host, port, - boost::bind(&TCPConnector::connected, this, _1), - boost::bind(&TCPConnector::connectFailed, this, _3)); - closed = false; - - connector->start(poller); -} - -void TCPConnector::connected(const Socket&) { - connector = 0; - aio = AsynchIO::create(socket, - boost::bind(&TCPConnector::readbuff, this, _1, _2), - boost::bind(&TCPConnector::eof, this, _1), - boost::bind(&TCPConnector::disconnected, this, _1), - boost::bind(&TCPConnector::socketClosed, this, _1, _2), - 0, // nobuffs - boost::bind(&TCPConnector::writebuff, this, _1)); - start(aio); - initAmqp(); - aio->start(poller); -} - -void TCPConnector::start(sys::AsynchIO* aio_) { - aio = aio_; - for (int i = 0; i < 4; i++) { - aio->queueReadBuffer(new Buff(maxFrameSize)); - } - - identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress()); -} - -void TCPConnector::initAmqp() { - ProtocolInitiation init(version); - writeDataBlock(init); -} - -void TCPConnector::connectFailed(const std::string& msg) { - connector = 0; - QPID_LOG(warning, "Connect failed: " << msg); - socket.close(); - if (!closed) - closed = true; - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void TCPConnector::close() { - Mutex::ScopedLock l(lock); - if (!closed) { - closed = true; - if (aio) - aio->queueWriteClose(); - } -} - -void TCPConnector::socketClosed(AsynchIO&, const Socket&) { - if (aio) - aio->queueForDeletion(); - if (shutdownHandler) - shutdownHandler->shutdown(); -} - -void TCPConnector::abort() { - // Can't abort a closed connection - if (!closed) { - if (aio) { - // Established connection - aio->requestCallback(boost::bind(&TCPConnector::eof, this, _1)); - } else if (connector) { - // We're still connecting - connector->stop(); - connectFailed("Connection timedout"); - } - } -} - -void TCPConnector::setInputHandler(InputHandler* handler){ - input = handler; -} - -void TCPConnector::setShutdownHandler(ShutdownHandler* handler){ - shutdownHandler = handler; -} - -OutputHandler* TCPConnector::getOutputHandler() { - return this; -} - -sys::ShutdownHandler* TCPConnector::getShutdownHandler() const { - return shutdownHandler; -} - -const std::string& TCPConnector::getIdentifier() const { - return identifier; -} - -void TCPConnector::send(AMQFrame& frame) { - bool notifyWrite = false; - { - Mutex::ScopedLock l(lock); - frames.push_back(frame); - //only ask to write if this is the end of a frameset or if we - //already have a buffers worth of data - currentSize += frame.encodedSize(); - if (frame.getEof()) { - lastEof = frames.size(); - notifyWrite = true; - } else { - notifyWrite = (currentSize >= maxFrameSize); - } - /* - NOTE: Moving the following line into this mutex block - is a workaround for BZ 570168, in which the test - testConcurrentSenders causes a hang about 1.5% - of the time. ( To see the hang much more frequently - leave this line out of the mutex block, and put a - small usleep just before it.) - - TODO mgoulish - fix the underlying cause and then - move this call back outside the mutex. - */ - if (notifyWrite && !closed) aio->notifyPendingWrite(); - } -} - -void TCPConnector::writebuff(AsynchIO& /*aio*/) -{ - // It's possible to be disconnected and be writable - if (closed) - return; - - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - if (codec->canEncode()) { - std::auto_ptr<AsynchIO::BufferBase> buffer = std::auto_ptr<AsynchIO::BufferBase>(aio->getQueuedBuffer()); - if (!buffer.get()) buffer = std::auto_ptr<AsynchIO::BufferBase>(new Buff(maxFrameSize)); - - size_t encoded = codec->encode(buffer->bytes, buffer->byteCount); - - buffer->dataStart = 0; - buffer->dataCount = encoded; - aio->queueWrite(buffer.release()); - } -} - -// Called in IO thread. -bool TCPConnector::canEncode() -{ - Mutex::ScopedLock l(lock); - //have at least one full frameset or a whole buffers worth of data - return lastEof || currentSize >= maxFrameSize; -} - -// Called in IO thread. -size_t TCPConnector::encode(const char* buffer, size_t size) -{ - framing::Buffer out(const_cast<char*>(buffer), size); - size_t bytesWritten(0); - { - Mutex::ScopedLock l(lock); - while (!frames.empty() && out.available() >= frames.front().encodedSize() ) { - frames.front().encode(out); - QPID_LOG(trace, "SENT " << identifier << ": " << frames.front()); - frames.pop_front(); - if (lastEof) --lastEof; - } - bytesWritten = size - out.available(); - currentSize -= bytesWritten; - } - if (bounds) bounds->reduce(bytesWritten); - return bytesWritten; -} - -bool TCPConnector::readbuff(AsynchIO& aio, AsynchIO::BufferBase* buff) -{ - Codec* codec = securityLayer.get() ? (Codec*) securityLayer.get() : (Codec*) this; - int32_t decoded = codec->decode(buff->bytes+buff->dataStart, buff->dataCount); - // TODO: unreading needs to go away, and when we can cope - // with multiple sub-buffers in the general buffer scheme, it will - if (decoded < buff->dataCount) { - // Adjust buffer for used bytes and then "unread them" - buff->dataStart += decoded; - buff->dataCount -= decoded; - aio.unread(buff); - } else { - // Give whole buffer back to aio subsystem - aio.queueReadBuffer(buff); - } - return true; -} - -size_t TCPConnector::decode(const char* buffer, size_t size) -{ - framing::Buffer in(const_cast<char*>(buffer), size); - if (!initiated) { - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - QPID_LOG(debug, "RECV " << identifier << " INIT(" << protocolInit << ")"); - if(!(protocolInit==version)){ - throw Exception(QPID_MSG("Unsupported version: " << protocolInit - << " supported version " << version)); - } - } - initiated = true; - } - AMQFrame frame; - while(frame.decode(in)){ - QPID_LOG(trace, "RECV " << identifier << ": " << frame); - input->received(frame); - } - return size - in.available(); -} - -void TCPConnector::writeDataBlock(const AMQDataBlock& data) { - AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); - framing::Buffer out(buff->bytes, buff->byteCount); - data.encode(out); - buff->dataCount = data.encodedSize(); - aio->queueWrite(buff); -} - -void TCPConnector::eof(AsynchIO&) { - close(); -} - -void TCPConnector::disconnected(AsynchIO&) { - close(); - socketClosed(*aio, socket); -} - -void TCPConnector::activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer> sl) -{ - securityLayer = sl; - securityLayer->init(this); -} - -}} // namespace qpid::client diff --git a/cpp/src/qpid/client/TCPConnector.h b/cpp/src/qpid/client/TCPConnector.h deleted file mode 100644 index c756469182..0000000000 --- a/cpp/src/qpid/client/TCPConnector.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifndef _TCPConnector_ -#define _TCPConnector_ - -#include "Connector.h" -#include "qpid/client/Bounds.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Codec.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/Thread.h" - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> -#include <deque> -#include <string> - -namespace qpid { - -namespace framing { - class InitiationHandler; -} - -namespace client { - -class TCPConnector : public Connector, public sys::Codec -{ - typedef std::deque<framing::AMQFrame> Frames; - struct Buff; - - const uint16_t maxFrameSize; - - sys::Mutex lock; - Frames frames; // Outgoing frame queue - size_t lastEof; // Position after last EOF in frames - uint64_t currentSize; - Bounds* bounds; - - framing::ProtocolVersion version; - bool initiated; - bool closed; - - sys::ShutdownHandler* shutdownHandler; - framing::InputHandler* input; - framing::InitiationHandler* initialiser; - framing::OutputHandler* output; - - sys::Socket socket; - - sys::AsynchConnector* connector; - sys::AsynchIO* aio; - std::string identifier; - boost::shared_ptr<sys::Poller> poller; - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; - - virtual void connected(const sys::Socket&); - void writeDataBlock(const framing::AMQDataBlock& data); - - void close(); - void send(framing::AMQFrame& frame); - void abort(); - - void setInputHandler(framing::InputHandler* handler); - void setShutdownHandler(sys::ShutdownHandler* handler); - sys::ShutdownHandler* getShutdownHandler() const; - framing::OutputHandler* getOutputHandler(); - const std::string& getIdentifier() const; - void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>); - const qpid::sys::SecuritySettings* getSecuritySettings() { return 0; } - - size_t decode(const char* buffer, size_t size); - size_t encode(const char* buffer, size_t size); - bool canEncode(); - -protected: - virtual ~TCPConnector(); - void connect(const std::string& host, int port); - void start(sys::AsynchIO* aio_); - void initAmqp(); - virtual void connectFailed(const std::string& msg); - bool readbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*); - void writebuff(qpid::sys::AsynchIO&); - void eof(qpid::sys::AsynchIO&); - void disconnected(qpid::sys::AsynchIO&); - void socketClosed(qpid::sys::AsynchIO&, const qpid::sys::Socket&); - -public: - TCPConnector(boost::shared_ptr<sys::Poller>, - framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); -}; - -}} // namespace qpid::client - -#endif /* _TCPConnector_ */ diff --git a/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp b/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp deleted file mode 100644 index bfb20118b5..0000000000 --- a/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "AcceptTracker.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -void AcceptTracker::State::accept() -{ - unconfirmed.add(unaccepted); - unaccepted.clear(); -} - -void AcceptTracker::State::accept(qpid::framing::SequenceNumber id) -{ - if (unaccepted.contains(id)) { - unaccepted.remove(id); - unconfirmed.add(id); - } -} - -void AcceptTracker::State::release() -{ - unaccepted.clear(); -} - -uint32_t AcceptTracker::State::acceptsPending() -{ - return unconfirmed.size(); -} - -void AcceptTracker::State::completed(qpid::framing::SequenceSet& set) -{ - unconfirmed.remove(set); -} - -void AcceptTracker::delivered(const std::string& destination, const qpid::framing::SequenceNumber& id) -{ - aggregateState.unaccepted.add(id); - destinationState[destination].unaccepted.add(id); -} - -void AcceptTracker::accept(qpid::client::AsyncSession& session) -{ - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.accept(); - } - Record record; - record.status = session.messageAccept(aggregateState.unaccepted); - record.accepted = aggregateState.unaccepted; - pending.push_back(record); - aggregateState.accept(); -} - -void AcceptTracker::accept(qpid::framing::SequenceNumber id, qpid::client::AsyncSession& session) -{ - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.accept(id); - } - Record record; - record.accepted.add(id); - record.status = session.messageAccept(record.accepted); - pending.push_back(record); - aggregateState.accept(id); -} - -void AcceptTracker::release(qpid::client::AsyncSession& session) -{ - session.messageRelease(aggregateState.unaccepted); - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.release(); - } - aggregateState.release(); -} - -uint32_t AcceptTracker::acceptsPending() -{ - checkPending(); - return aggregateState.acceptsPending(); -} - -uint32_t AcceptTracker::acceptsPending(const std::string& destination) -{ - checkPending(); - return destinationState[destination].acceptsPending(); -} - -void AcceptTracker::reset() -{ - destinationState.clear(); - aggregateState.unaccepted.clear(); - aggregateState.unconfirmed.clear(); - pending.clear(); -} - -void AcceptTracker::checkPending() -{ - while (!pending.empty() && pending.front().status.isComplete()) { - completed(pending.front().accepted); - pending.pop_front(); - } -} - -void AcceptTracker::completed(qpid::framing::SequenceSet& set) -{ - for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) { - i->second.completed(set); - } - aggregateState.completed(set); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/AcceptTracker.h b/cpp/src/qpid/client/amqp0_10/AcceptTracker.h deleted file mode 100644 index 87890e41cc..0000000000 --- a/cpp/src/qpid/client/amqp0_10/AcceptTracker.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_ACCEPTTRACKER_H -#define QPID_CLIENT_AMQP0_10_ACCEPTTRACKER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/AsyncSession.h" -#include "qpid/client/Completion.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceSet.h" -#include <deque> -#include <map> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -/** - * Tracks the set of messages requiring acceptance, and those for - * which an accept has been issued but is yet to be confirmed - * complete. - */ -class AcceptTracker -{ - public: - void delivered(const std::string& destination, const qpid::framing::SequenceNumber& id); - void accept(qpid::client::AsyncSession&); - void accept(qpid::framing::SequenceNumber, qpid::client::AsyncSession&); - void release(qpid::client::AsyncSession&); - uint32_t acceptsPending(); - uint32_t acceptsPending(const std::string& destination); - void reset(); - private: - struct State - { - /** - * ids of messages that have been delivered but not yet - * accepted - */ - qpid::framing::SequenceSet unaccepted; - /** - * ids of messages for which an accept has been issued but not - * yet confirmed as completed - */ - qpid::framing::SequenceSet unconfirmed; - - void accept(); - void accept(qpid::framing::SequenceNumber); - void release(); - uint32_t acceptsPending(); - void completed(qpid::framing::SequenceSet&); - }; - typedef std::map<std::string, State> StateMap; - struct Record - { - qpid::client::Completion status; - qpid::framing::SequenceSet accepted; - }; - typedef std::deque<Record> Records; - - State aggregateState; - StateMap destinationState; - Records pending; - - void checkPending(); - void completed(qpid::framing::SequenceSet&); -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_ACCEPTTRACKER_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp b/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp deleted file mode 100644 index f1295a3b66..0000000000 --- a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp +++ /dev/null @@ -1,966 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/client/amqp0_10/MessageSource.h" -#include "qpid/client/amqp0_10/MessageSink.h" -#include "qpid/client/amqp0_10/OutgoingMessage.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/types/Variant.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/ExchangeBoundResult.h" -#include "qpid/framing/ExchangeQueryResult.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/QueueQueryResult.h" -#include "qpid/framing/ReplyTo.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/Uuid.h" -#include <boost/assign.hpp> -#include <boost/format.hpp> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::Exception; -using qpid::messaging::Address; -using qpid::messaging::AddressError; -using qpid::messaging::MalformedAddress; -using qpid::messaging::ResolutionError; -using qpid::messaging::NotFound; -using qpid::messaging::AssertionFailed; -using qpid::framing::ExchangeBoundResult; -using qpid::framing::ExchangeQueryResult; -using qpid::framing::FieldTable; -using qpid::framing::QueueQueryResult; -using qpid::framing::ReplyTo; -using qpid::framing::Uuid; -using namespace qpid::types; -using namespace qpid::framing::message; -using namespace qpid::amqp_0_10; -using namespace boost::assign; - -class Verifier -{ - public: - Verifier(); - void verify(const Address& address) const; - private: - Variant::Map defined; - void verify(const Variant::Map& allowed, const Variant::Map& actual) const; -}; - -namespace{ -const Variant EMPTY_VARIANT; -const FieldTable EMPTY_FIELD_TABLE; -const Variant::List EMPTY_LIST; -const std::string EMPTY_STRING; - -//policy types -const std::string CREATE("create"); -const std::string ASSERT("assert"); -const std::string DELETE("delete"); - -//option names -const std::string NODE("node"); -const std::string LINK("link"); -const std::string MODE("mode"); -const std::string RELIABILITY("reliability"); -const std::string NAME("name"); -const std::string DURABLE("durable"); -const std::string X_DECLARE("x-declare"); -const std::string X_SUBSCRIBE("x-subscribe"); -const std::string X_BINDINGS("x-bindings"); -const std::string EXCHANGE("exchange"); -const std::string QUEUE("queue"); -const std::string KEY("key"); -const std::string ARGUMENTS("arguments"); -const std::string ALTERNATE_EXCHANGE("alternate-exchange"); -const std::string TYPE("type"); -const std::string EXCLUSIVE("exclusive"); -const std::string AUTO_DELETE("auto-delete"); - -//policy values -const std::string ALWAYS("always"); -const std::string NEVER("never"); -const std::string RECEIVER("receiver"); -const std::string SENDER("sender"); - -//address types -const std::string QUEUE_ADDRESS("queue"); -const std::string TOPIC_ADDRESS("topic"); - -//reliability options: -const std::string UNRELIABLE("unreliable"); -const std::string AT_MOST_ONCE("at-most-once"); -const std::string AT_LEAST_ONCE("at-least-once"); -const std::string EXACTLY_ONCE("exactly-once"); - -//receiver modes: -const std::string BROWSE("browse"); -const std::string CONSUME("consume"); - -//0-10 exchange types: -const std::string TOPIC_EXCHANGE("topic"); -const std::string FANOUT_EXCHANGE("fanout"); -const std::string DIRECT_EXCHANGE("direct"); -const std::string HEADERS_EXCHANGE("headers"); -const std::string XML_EXCHANGE("xml"); -const std::string WILDCARD_ANY("#"); - -const Verifier verifier; -} - -struct Binding -{ - Binding(const Variant::Map&); - Binding(const std::string& exchange, const std::string& queue, const std::string& key); - - std::string exchange; - std::string queue; - std::string key; - FieldTable arguments; -}; - -struct Bindings : std::vector<Binding> -{ - void add(const Variant::List& bindings); - void setDefaultExchange(const std::string&); - void setDefaultQueue(const std::string&); - void bind(qpid::client::AsyncSession& session); - void unbind(qpid::client::AsyncSession& session); - void check(qpid::client::AsyncSession& session); -}; - -class Node -{ - protected: - enum CheckMode {FOR_RECEIVER, FOR_SENDER}; - - Node(const Address& address); - - const std::string name; - Variant createPolicy; - Variant assertPolicy; - Variant deletePolicy; - Bindings nodeBindings; - Bindings linkBindings; - - static bool enabled(const Variant& policy, CheckMode mode); - static bool createEnabled(const Address& address, CheckMode mode); - static void convert(const Variant& option, FieldTable& arguments); - static std::vector<std::string> RECEIVER_MODES; - static std::vector<std::string> SENDER_MODES; -}; - - -class Queue : protected Node -{ - public: - Queue(const Address& address); - protected: - void checkCreate(qpid::client::AsyncSession&, CheckMode); - void checkAssert(qpid::client::AsyncSession&, CheckMode); - void checkDelete(qpid::client::AsyncSession&, CheckMode); - private: - const bool durable; - const bool autoDelete; - const bool exclusive; - const std::string alternateExchange; - FieldTable arguments; -}; - -class Exchange : protected Node -{ - public: - Exchange(const Address& address); - protected: - void checkCreate(qpid::client::AsyncSession&, CheckMode); - void checkAssert(qpid::client::AsyncSession&, CheckMode); - void checkDelete(qpid::client::AsyncSession&, CheckMode); - - protected: - const std::string specifiedType; - private: - const bool durable; - const bool autoDelete; - const std::string alternateExchange; - FieldTable arguments; -}; - -class QueueSource : public Queue, public MessageSource -{ - public: - QueueSource(const Address& address); - void subscribe(qpid::client::AsyncSession& session, const std::string& destination); - void cancel(qpid::client::AsyncSession& session, const std::string& destination); - private: - const AcceptMode acceptMode; - const AcquireMode acquireMode; - bool exclusive; - FieldTable options; -}; - -class Subscription : public Exchange, public MessageSource -{ - public: - Subscription(const Address&, const std::string& actualType); - void subscribe(qpid::client::AsyncSession& session, const std::string& destination); - void cancel(qpid::client::AsyncSession& session, const std::string& destination); - private: - const std::string queue; - const bool reliable; - const bool durable; - const std::string actualType; - FieldTable queueOptions; - FieldTable subscriptionOptions; - Bindings bindings; - - void bindSubject(const std::string& subject); - void bindAll(); - void add(const std::string& exchange, const std::string& key); - static std::string getSubscriptionName(const std::string& base, const std::string& name); -}; - -class ExchangeSink : public Exchange, public MessageSink -{ - public: - ExchangeSink(const Address& name); - void declare(qpid::client::AsyncSession& session, const std::string& name); - void send(qpid::client::AsyncSession& session, const std::string& name, OutgoingMessage& message); - void cancel(qpid::client::AsyncSession& session, const std::string& name); - private: -}; - -class QueueSink : public Queue, public MessageSink -{ - public: - QueueSink(const Address& name); - void declare(qpid::client::AsyncSession& session, const std::string& name); - void send(qpid::client::AsyncSession& session, const std::string& name, OutgoingMessage& message); - void cancel(qpid::client::AsyncSession& session, const std::string& name); - private: -}; -bool isQueue(qpid::client::Session session, const qpid::messaging::Address& address); -bool isTopic(qpid::client::Session session, const qpid::messaging::Address& address); - -bool in(const Variant& value, const std::vector<std::string>& choices) -{ - if (!value.isVoid()) { - for (std::vector<std::string>::const_iterator i = choices.begin(); i != choices.end(); ++i) { - if (value.asString() == *i) return true; - } - } - return false; -} - -const Variant& getOption(const Variant::Map& options, const std::string& name) -{ - Variant::Map::const_iterator j = options.find(name); - if (j == options.end()) { - return EMPTY_VARIANT; - } else { - return j->second; - } -} - -const Variant& getOption(const Address& address, const std::string& name) -{ - return getOption(address.getOptions(), name); -} - -bool getReceiverPolicy(const Address& address, const std::string& key) -{ - return in(getOption(address, key), list_of<std::string>(ALWAYS)(RECEIVER)); -} - -bool getSenderPolicy(const Address& address, const std::string& key) -{ - return in(getOption(address, key), list_of<std::string>(ALWAYS)(SENDER)); -} - -struct Opt -{ - Opt(const Address& address); - Opt(const Variant::Map& base); - Opt& operator/(const std::string& name); - operator bool() const; - std::string str() const; - const Variant::List& asList() const; - void collect(qpid::framing::FieldTable& args) const; - - const Variant::Map* options; - const Variant* value; -}; - -Opt::Opt(const Address& address) : options(&(address.getOptions())), value(0) {} -Opt::Opt(const Variant::Map& base) : options(&base), value(0) {} -Opt& Opt::operator/(const std::string& name) -{ - if (options) { - Variant::Map::const_iterator j = options->find(name); - if (j == options->end()) { - value = 0; - options = 0; - } else { - value = &(j->second); - if (value->getType() == VAR_MAP) options = &(value->asMap()); - else options = 0; - } - } - return *this; -} - - -Opt::operator bool() const -{ - return value && !value->isVoid() && value->asBool(); -} - -std::string Opt::str() const -{ - if (value) return value->asString(); - else return EMPTY_STRING; -} - -const Variant::List& Opt::asList() const -{ - if (value) return value->asList(); - else return EMPTY_LIST; -} - -void Opt::collect(qpid::framing::FieldTable& args) const -{ - if (value) { - translate(value->asMap(), args); - } -} - -bool AddressResolution::is_unreliable(const Address& address) -{ - - return in((Opt(address)/LINK/RELIABILITY).str(), - list_of<std::string>(UNRELIABLE)(AT_MOST_ONCE)); -} - -bool AddressResolution::is_reliable(const Address& address) -{ - return in((Opt(address)/LINK/RELIABILITY).str(), - list_of<std::string>(AT_LEAST_ONCE)(EXACTLY_ONCE)); -} - -std::string checkAddressType(qpid::client::Session session, const Address& address) -{ - verifier.verify(address); - if (address.getName().empty()) { - throw MalformedAddress("Name cannot be null"); - } - std::string type = (Opt(address)/NODE/TYPE).str(); - if (type.empty()) { - ExchangeBoundResult result = session.exchangeBound(arg::exchange=address.getName(), arg::queue=address.getName()); - if (result.getQueueNotFound() && result.getExchangeNotFound()) { - //neither a queue nor an exchange exists with that name; treat it as a queue - type = QUEUE_ADDRESS; - } else if (result.getExchangeNotFound()) { - //name refers to a queue - type = QUEUE_ADDRESS; - } else if (result.getQueueNotFound()) { - //name refers to an exchange - type = TOPIC_ADDRESS; - } else { - //both a queue and exchange exist for that name - throw ResolutionError("Ambiguous address, please specify queue or topic as node type"); - } - } - return type; -} - -std::auto_ptr<MessageSource> AddressResolution::resolveSource(qpid::client::Session session, - const Address& address) -{ - std::string type = checkAddressType(session, address); - if (type == TOPIC_ADDRESS) { - std::string exchangeType = sync(session).exchangeQuery(address.getName()).getType(); - std::auto_ptr<MessageSource> source(new Subscription(address, exchangeType)); - QPID_LOG(debug, "treating source address as topic: " << address); - return source; - } else if (type == QUEUE_ADDRESS) { - std::auto_ptr<MessageSource> source(new QueueSource(address)); - QPID_LOG(debug, "treating source address as queue: " << address); - return source; - } else { - throw ResolutionError("Unrecognised type: " + type); - } -} - - -std::auto_ptr<MessageSink> AddressResolution::resolveSink(qpid::client::Session session, - const qpid::messaging::Address& address) -{ - std::string type = checkAddressType(session, address); - if (type == TOPIC_ADDRESS) { - std::auto_ptr<MessageSink> sink(new ExchangeSink(address)); - QPID_LOG(debug, "treating target address as topic: " << address); - return sink; - } else if (type == QUEUE_ADDRESS) { - std::auto_ptr<MessageSink> sink(new QueueSink(address)); - QPID_LOG(debug, "treating target address as queue: " << address); - return sink; - } else { - throw ResolutionError("Unrecognised type: " + type); - } -} - -bool isBrowse(const Address& address) -{ - const Variant& mode = getOption(address, MODE); - if (!mode.isVoid()) { - std::string value = mode.asString(); - if (value == BROWSE) return true; - else if (value != CONSUME) throw ResolutionError("Invalid mode"); - } - return false; -} - -QueueSource::QueueSource(const Address& address) : - Queue(address), - acceptMode(AddressResolution::is_unreliable(address) ? ACCEPT_MODE_NONE : ACCEPT_MODE_EXPLICIT), - acquireMode(isBrowse(address) ? ACQUIRE_MODE_NOT_ACQUIRED : ACQUIRE_MODE_PRE_ACQUIRED), - exclusive(false) -{ - //extract subscription arguments from address options (nb: setting - //of accept-mode/acquire-mode/destination controlled though other - //options) - exclusive = Opt(address)/LINK/X_SUBSCRIBE/EXCLUSIVE; - (Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(options); -} - -void QueueSource::subscribe(qpid::client::AsyncSession& session, const std::string& destination) -{ - checkCreate(session, FOR_RECEIVER); - checkAssert(session, FOR_RECEIVER); - linkBindings.bind(session); - session.messageSubscribe(arg::queue=name, - arg::destination=destination, - arg::acceptMode=acceptMode, - arg::acquireMode=acquireMode, - arg::exclusive=exclusive, - arg::arguments=options); -} - -void QueueSource::cancel(qpid::client::AsyncSession& session, const std::string& destination) -{ - linkBindings.unbind(session); - session.messageCancel(destination); - checkDelete(session, FOR_RECEIVER); -} - -std::string Subscription::getSubscriptionName(const std::string& base, const std::string& name) -{ - if (name.empty()) { - return (boost::format("%1%_%2%") % base % Uuid(true).str()).str(); - } else { - return (boost::format("%1%_%2%") % base % name).str(); - } -} - -Subscription::Subscription(const Address& address, const std::string& type) - : Exchange(address), - queue(getSubscriptionName(name, (Opt(address)/LINK/NAME).str())), - reliable(AddressResolution::is_reliable(address)), - durable(Opt(address)/LINK/DURABLE), - actualType(type.empty() ? (specifiedType.empty() ? TOPIC_EXCHANGE : specifiedType) : type) -{ - (Opt(address)/LINK/X_DECLARE/ARGUMENTS).collect(queueOptions); - (Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(subscriptionOptions); - - if (!address.getSubject().empty()) bindSubject(address.getSubject()); - else if (linkBindings.empty()) bindAll(); -} - -void Subscription::bindSubject(const std::string& subject) -{ - if (actualType == HEADERS_EXCHANGE) { - Binding b(name, queue, subject); - b.arguments.setString("qpid.subject", subject); - b.arguments.setString("x-match", "all"); - bindings.push_back(b); - } else if (actualType == XML_EXCHANGE) { - Binding b(name, queue, subject); - std::string query = (boost::format("declare variable $qpid.subject external; $qpid.subject = '%1%'") - % subject).str(); - b.arguments.setString("xquery", query); - bindings.push_back(b); - } else { - //Note: the fanout exchange doesn't support any filtering, so - //the subject is ignored in that case - add(name, subject); - } -} - -void Subscription::bindAll() -{ - if (actualType == TOPIC_EXCHANGE) { - add(name, WILDCARD_ANY); - } else if (actualType == FANOUT_EXCHANGE) { - add(name, queue); - } else if (actualType == HEADERS_EXCHANGE) { - Binding b(name, queue, "match-all"); - b.arguments.setString("x-match", "all"); - bindings.push_back(b); - } else if (actualType == XML_EXCHANGE) { - Binding b(name, queue, EMPTY_STRING); - b.arguments.setString("xquery", "true()"); - bindings.push_back(b); - } else { - add(name, EMPTY_STRING); - } -} - -void Subscription::add(const std::string& exchange, const std::string& key) -{ - bindings.push_back(Binding(exchange, queue, key)); -} - -void Subscription::subscribe(qpid::client::AsyncSession& session, const std::string& destination) -{ - //create exchange if required and specified by policy: - checkCreate(session, FOR_RECEIVER); - checkAssert(session, FOR_RECEIVER); - - //create subscription queue: - session.queueDeclare(arg::queue=queue, arg::exclusive=true, - arg::autoDelete=!reliable, arg::durable=durable, arg::arguments=queueOptions); - //'default' binding: - bindings.bind(session); - //any explicit bindings: - linkBindings.setDefaultQueue(queue); - linkBindings.bind(session); - //subscribe to subscription queue: - AcceptMode accept = reliable ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE; - session.messageSubscribe(arg::queue=queue, arg::destination=destination, - arg::exclusive=true, arg::acceptMode=accept, arg::arguments=subscriptionOptions); -} - -void Subscription::cancel(qpid::client::AsyncSession& session, const std::string& destination) -{ - linkBindings.unbind(session); - session.messageCancel(destination); - session.queueDelete(arg::queue=queue); - checkDelete(session, FOR_RECEIVER); -} - -ExchangeSink::ExchangeSink(const Address& address) : Exchange(address) {} - -void ExchangeSink::declare(qpid::client::AsyncSession& session, const std::string&) -{ - checkCreate(session, FOR_SENDER); - checkAssert(session, FOR_SENDER); - linkBindings.bind(session); -} - -void ExchangeSink::send(qpid::client::AsyncSession& session, const std::string&, OutgoingMessage& m) -{ - m.message.getDeliveryProperties().setRoutingKey(m.getSubject()); - m.status = session.messageTransfer(arg::destination=name, arg::content=m.message); -} - -void ExchangeSink::cancel(qpid::client::AsyncSession& session, const std::string&) -{ - linkBindings.unbind(session); - checkDelete(session, FOR_SENDER); -} - -QueueSink::QueueSink(const Address& address) : Queue(address) {} - -void QueueSink::declare(qpid::client::AsyncSession& session, const std::string&) -{ - checkCreate(session, FOR_SENDER); - checkAssert(session, FOR_SENDER); - linkBindings.bind(session); -} -void QueueSink::send(qpid::client::AsyncSession& session, const std::string&, OutgoingMessage& m) -{ - m.message.getDeliveryProperties().setRoutingKey(name); - m.status = session.messageTransfer(arg::content=m.message); -} - -void QueueSink::cancel(qpid::client::AsyncSession& session, const std::string&) -{ - linkBindings.unbind(session); - checkDelete(session, FOR_SENDER); -} - -Address AddressResolution::convert(const qpid::framing::ReplyTo& rt) -{ - Address address; - if (rt.getExchange().empty()) {//if default exchange, treat as queue - address.setName(rt.getRoutingKey()); - address.setType(QUEUE_ADDRESS); - } else { - address.setName(rt.getExchange()); - address.setSubject(rt.getRoutingKey()); - address.setType(TOPIC_ADDRESS); - } - return address; -} - -qpid::framing::ReplyTo AddressResolution::convert(const Address& address) -{ - if (address.getType() == QUEUE_ADDRESS || address.getType().empty()) { - return ReplyTo(EMPTY_STRING, address.getName()); - } else if (address.getType() == TOPIC_ADDRESS) { - return ReplyTo(address.getName(), address.getSubject()); - } else { - QPID_LOG(notice, "Unrecognised type for reply-to: " << address.getType()); - return ReplyTo(EMPTY_STRING, address.getName());//treat as queue - } -} - -bool isQueue(qpid::client::Session session, const qpid::messaging::Address& address) -{ - return address.getType() == QUEUE_ADDRESS || - (address.getType().empty() && session.queueQuery(address.getName()).getQueue() == address.getName()); -} - -bool isTopic(qpid::client::Session session, const qpid::messaging::Address& address) -{ - if (address.getType().empty()) { - return !session.exchangeQuery(address.getName()).getNotFound(); - } else if (address.getType() == TOPIC_ADDRESS) { - return true; - } else { - return false; - } -} - -Node::Node(const Address& address) : name(address.getName()), - createPolicy(getOption(address, CREATE)), - assertPolicy(getOption(address, ASSERT)), - deletePolicy(getOption(address, DELETE)) -{ - nodeBindings.add((Opt(address)/NODE/X_BINDINGS).asList()); - linkBindings.add((Opt(address)/LINK/X_BINDINGS).asList()); -} - -Queue::Queue(const Address& a) : Node(a), - durable(Opt(a)/NODE/DURABLE), - autoDelete(Opt(a)/NODE/X_DECLARE/AUTO_DELETE), - exclusive(Opt(a)/NODE/X_DECLARE/EXCLUSIVE), - alternateExchange((Opt(a)/NODE/X_DECLARE/ALTERNATE_EXCHANGE).str()) -{ - (Opt(a)/NODE/X_DECLARE/ARGUMENTS).collect(arguments); - nodeBindings.setDefaultQueue(name); - linkBindings.setDefaultQueue(name); -} - -void Queue::checkCreate(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(createPolicy, mode)) { - QPID_LOG(debug, "Auto-creating queue '" << name << "'"); - try { - session.queueDeclare(arg::queue=name, - arg::durable=durable, - arg::autoDelete=autoDelete, - arg::exclusive=exclusive, - arg::alternateExchange=alternateExchange, - arg::arguments=arguments); - nodeBindings.bind(session); - session.sync(); - } catch (const qpid::framing::ResourceLockedException& e) { - throw ResolutionError((boost::format("Creation failed for queue %1%; %2%") % name % e.what()).str()); - } catch (const qpid::framing::NotAllowedException& e) { - throw ResolutionError((boost::format("Creation failed for queue %1%; %2%") % name % e.what()).str()); - } catch (const qpid::framing::NotFoundException& e) {//may be thrown when creating bindings - throw ResolutionError((boost::format("Creation failed for queue %1%; %2%") % name % e.what()).str()); - } - } else { - try { - sync(session).queueDeclare(arg::queue=name, arg::passive=true); - } catch (const qpid::framing::NotFoundException& /*e*/) { - throw NotFound((boost::format("Queue %1% does not exist") % name).str()); - } - } -} - -void Queue::checkDelete(qpid::client::AsyncSession& session, CheckMode mode) -{ - //Note: queue-delete will cause a session exception if the queue - //does not exist, the query here prevents obvious cases of this - //but there is a race whenever two deletions are made concurrently - //so careful use of the delete policy is recommended at present - if (enabled(deletePolicy, mode) && sync(session).queueQuery(name).getQueue() == name) { - QPID_LOG(debug, "Auto-deleting queue '" << name << "'"); - sync(session).queueDelete(arg::queue=name); - } -} - -void Queue::checkAssert(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(assertPolicy, mode)) { - QueueQueryResult result = sync(session).queueQuery(name); - if (result.getQueue() != name) { - throw NotFound((boost::format("Queue not found: %1%") % name).str()); - } else { - if (durable && !result.getDurable()) { - throw AssertionFailed((boost::format("Queue not durable: %1%") % name).str()); - } - if (autoDelete && !result.getAutoDelete()) { - throw AssertionFailed((boost::format("Queue not set to auto-delete: %1%") % name).str()); - } - if (exclusive && !result.getExclusive()) { - throw AssertionFailed((boost::format("Queue not exclusive: %1%") % name).str()); - } - if (!alternateExchange.empty() && result.getAlternateExchange() != alternateExchange) { - throw AssertionFailed((boost::format("Alternate exchange does not match for %1%, expected %2%, got %3%") - % name % alternateExchange % result.getAlternateExchange()).str()); - } - for (FieldTable::ValueMap::const_iterator i = arguments.begin(); i != arguments.end(); ++i) { - FieldTable::ValuePtr v = result.getArguments().get(i->first); - if (!v) { - throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str()); - } else if (*i->second != *v) { - throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%") - % i->first % name % *(i->second) % *v).str()); - } - } - nodeBindings.check(session); - } - } -} - -Exchange::Exchange(const Address& a) : Node(a), - specifiedType((Opt(a)/NODE/X_DECLARE/TYPE).str()), - durable(Opt(a)/NODE/DURABLE), - autoDelete(Opt(a)/NODE/X_DECLARE/AUTO_DELETE), - alternateExchange((Opt(a)/NODE/X_DECLARE/ALTERNATE_EXCHANGE).str()) -{ - (Opt(a)/NODE/X_DECLARE/ARGUMENTS).collect(arguments); - nodeBindings.setDefaultExchange(name); - linkBindings.setDefaultExchange(name); -} - -void Exchange::checkCreate(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(createPolicy, mode)) { - try { - std::string type = specifiedType; - if (type.empty()) type = TOPIC_EXCHANGE; - session.exchangeDeclare(arg::exchange=name, - arg::type=type, - arg::durable=durable, - arg::autoDelete=autoDelete, - arg::alternateExchange=alternateExchange, - arg::arguments=arguments); - nodeBindings.bind(session); - session.sync(); - } catch (const qpid::framing::NotAllowedException& e) { - throw ResolutionError((boost::format("Create failed for exchange %1%; %2%") % name % e.what()).str()); - } catch (const qpid::framing::NotFoundException& e) {//can be caused when creating bindings - throw ResolutionError((boost::format("Create failed for exchange %1%; %2%") % name % e.what()).str()); - } - } else { - try { - sync(session).exchangeDeclare(arg::exchange=name, arg::passive=true); - } catch (const qpid::framing::NotFoundException& /*e*/) { - throw NotFound((boost::format("Exchange %1% does not exist") % name).str()); - } - } -} - -void Exchange::checkDelete(qpid::client::AsyncSession& session, CheckMode mode) -{ - //Note: exchange-delete will cause a session exception if the - //exchange does not exist, the query here prevents obvious cases - //of this but there is a race whenever two deletions are made - //concurrently so careful use of the delete policy is recommended - //at present - if (enabled(deletePolicy, mode) && !sync(session).exchangeQuery(name).getNotFound()) { - sync(session).exchangeDelete(arg::exchange=name); - } -} - -void Exchange::checkAssert(qpid::client::AsyncSession& session, CheckMode mode) -{ - if (enabled(assertPolicy, mode)) { - ExchangeQueryResult result = sync(session).exchangeQuery(name); - if (result.getNotFound()) { - throw NotFound((boost::format("Exchange not found: %1%") % name).str()); - } else { - if (specifiedType.size() && result.getType() != specifiedType) { - throw AssertionFailed((boost::format("Exchange %1% is of incorrect type, expected %2% but got %3%") - % name % specifiedType % result.getType()).str()); - } - if (durable && !result.getDurable()) { - throw AssertionFailed((boost::format("Exchange not durable: %1%") % name).str()); - } - //Note: Can't check auto-delete or alternate-exchange via - //exchange-query-result as these are not returned - //TODO: could use a passive declare to check alternate-exchange - for (FieldTable::ValueMap::const_iterator i = arguments.begin(); i != arguments.end(); ++i) { - FieldTable::ValuePtr v = result.getArguments().get(i->first); - if (!v) { - throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str()); - } else if (i->second != v) { - throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%") - % i->first % name % *(i->second) % *v).str()); - } - } - nodeBindings.check(session); - } - } -} - -Binding::Binding(const Variant::Map& b) : - exchange((Opt(b)/EXCHANGE).str()), - queue((Opt(b)/QUEUE).str()), - key((Opt(b)/KEY).str()) -{ - (Opt(b)/ARGUMENTS).collect(arguments); -} - -Binding::Binding(const std::string& e, const std::string& q, const std::string& k) : exchange(e), queue(q), key(k) {} - - -void Bindings::add(const Variant::List& list) -{ - for (Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) { - push_back(Binding(i->asMap())); - } -} - -void Bindings::setDefaultExchange(const std::string& exchange) -{ - for (Bindings::iterator i = begin(); i != end(); ++i) { - if (i->exchange.empty()) i->exchange = exchange; - } -} - -void Bindings::setDefaultQueue(const std::string& queue) -{ - for (Bindings::iterator i = begin(); i != end(); ++i) { - if (i->queue.empty()) i->queue = queue; - } -} - -void Bindings::bind(qpid::client::AsyncSession& session) -{ - for (Bindings::const_iterator i = begin(); i != end(); ++i) { - session.exchangeBind(arg::queue=i->queue, - arg::exchange=i->exchange, - arg::bindingKey=i->key, - arg::arguments=i->arguments); - } -} - -void Bindings::unbind(qpid::client::AsyncSession& session) -{ - for (Bindings::const_iterator i = begin(); i != end(); ++i) { - session.exchangeUnbind(arg::queue=i->queue, - arg::exchange=i->exchange, - arg::bindingKey=i->key); - } -} - -void Bindings::check(qpid::client::AsyncSession& session) -{ - for (Bindings::const_iterator i = begin(); i != end(); ++i) { - ExchangeBoundResult result = sync(session).exchangeBound(arg::queue=i->queue, - arg::exchange=i->exchange, - arg::bindingKey=i->key); - if (result.getQueueNotMatched() || result.getKeyNotMatched()) { - throw AssertionFailed((boost::format("No such binding [exchange=%1%, queue=%2%, key=%3%]") - % i->exchange % i->queue % i->key).str()); - } - } -} - -bool Node::enabled(const Variant& policy, CheckMode mode) -{ - bool result = false; - switch (mode) { - case FOR_RECEIVER: - result = in(policy, RECEIVER_MODES); - break; - case FOR_SENDER: - result = in(policy, SENDER_MODES); - break; - } - return result; -} - -bool Node::createEnabled(const Address& address, CheckMode mode) -{ - const Variant& policy = getOption(address, CREATE); - return enabled(policy, mode); -} - -void Node::convert(const Variant& options, FieldTable& arguments) -{ - if (!options.isVoid()) { - translate(options.asMap(), arguments); - } -} -std::vector<std::string> Node::RECEIVER_MODES = list_of<std::string>(ALWAYS) (RECEIVER); -std::vector<std::string> Node::SENDER_MODES = list_of<std::string>(ALWAYS) (SENDER); - -Verifier::Verifier() -{ - defined[CREATE] = true; - defined[ASSERT] = true; - defined[DELETE] = true; - defined[MODE] = true; - Variant::Map node; - node[TYPE] = true; - node[DURABLE] = true; - node[X_DECLARE] = true; - node[X_BINDINGS] = true; - defined[NODE] = node; - Variant::Map link; - link[NAME] = true; - link[DURABLE] = true; - link[RELIABILITY] = true; - link[X_SUBSCRIBE] = true; - link[X_DECLARE] = true; - link[X_BINDINGS] = true; - defined[LINK] = link; -} -void Verifier::verify(const Address& address) const -{ - verify(defined, address.getOptions()); -} - -void Verifier::verify(const Variant::Map& allowed, const Variant::Map& actual) const -{ - for (Variant::Map::const_iterator i = actual.begin(); i != actual.end(); ++i) { - Variant::Map::const_iterator option = allowed.find(i->first); - if (option == allowed.end()) { - throw AddressError((boost::format("Unrecognised option: %1%") % i->first).str()); - } else if (option->second.getType() == qpid::types::VAR_MAP) { - verify(option->second.asMap(), i->second.asMap()); - } - } -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/AddressResolution.h b/cpp/src/qpid/client/amqp0_10/AddressResolution.h deleted file mode 100644 index fc8f1a1d18..0000000000 --- a/cpp/src/qpid/client/amqp0_10/AddressResolution.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_ADDRESSRESOLUTION_H -#define QPID_CLIENT_AMQP0_10_ADDRESSRESOLUTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Session.h" - -namespace qpid { - -namespace framing{ -class ReplyTo; -} - -namespace messaging { -class Address; -} - -namespace client { -namespace amqp0_10 { - -class MessageSource; -class MessageSink; - -/** - * Maps from a generic Address and optional Filter to an AMQP 0-10 - * MessageSource which will then be used by a ReceiverImpl instance - * created for the address. - */ -class AddressResolution -{ - public: - std::auto_ptr<MessageSource> resolveSource(qpid::client::Session session, - const qpid::messaging::Address& address); - - std::auto_ptr<MessageSink> resolveSink(qpid::client::Session session, - const qpid::messaging::Address& address); - - static qpid::messaging::Address convert(const qpid::framing::ReplyTo&); - static qpid::framing::ReplyTo convert(const qpid::messaging::Address&); - static bool is_unreliable(const qpid::messaging::Address& address); - static bool is_reliable(const qpid::messaging::Address& address); - private: -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_ADDRESSRESOLUTION_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp deleted file mode 100644 index a87a8dea67..0000000000 --- a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "ConnectionImpl.h" -#include "SessionImpl.h" -#include "SimpleUrlParser.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/PrivateImplRef.h" -#include "qpid/framing/Uuid.h" -#include "qpid/log/Statement.h" -#include "qpid/Url.h" -#include <boost/intrusive_ptr.hpp> -#include <vector> -#include <sstream> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::types::Variant; -using qpid::types::VAR_LIST; -using qpid::framing::Uuid; - -namespace { -void convert(const Variant::List& from, std::vector<std::string>& to) -{ - for (Variant::List::const_iterator i = from.begin(); i != from.end(); ++i) { - to.push_back(i->asString()); - } -} - -std::string asString(const std::vector<std::string>& v) { - std::stringstream os; - os << "["; - for(std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i ) { - if (i != v.begin()) os << ", "; - os << *i; - } - os << "]"; - return os.str(); -} -} - -ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& options) : - reconnect(false), timeout(-1), limit(-1), - minReconnectInterval(3), maxReconnectInterval(60), - retries(0), reconnectOnLimitExceeded(true) -{ - setOptions(options); - urls.insert(urls.begin(), url); - QPID_LOG(debug, "Created connection " << url << " with " << options); -} - -void ConnectionImpl::setOptions(const Variant::Map& options) -{ - for (Variant::Map::const_iterator i = options.begin(); i != options.end(); ++i) { - setOption(i->first, i->second); - } -} - -void ConnectionImpl::setOption(const std::string& name, const Variant& value) -{ - sys::Mutex::ScopedLock l(lock); - if (name == "reconnect") { - reconnect = value; - } else if (name == "reconnect-timeout" || name == "reconnect_timeout") { - timeout = value; - } else if (name == "reconnect-limit" || name == "reconnect_limit") { - limit = value; - } else if (name == "reconnect-interval" || name == "reconnect_interval") { - maxReconnectInterval = minReconnectInterval = value; - } else if (name == "reconnect-interval-min" || name == "reconnect_interval_min") { - minReconnectInterval = value; - } else if (name == "reconnect-interval-max" || name == "reconnect_interval_max") { - maxReconnectInterval = value; - } else if (name == "reconnect-urls" || name == "reconnect_urls") { - if (value.getType() == VAR_LIST) { - convert(value.asList(), urls); - } else { - urls.push_back(value.asString()); - } - } else if (name == "username") { - settings.username = value.asString(); - } else if (name == "password") { - settings.password = value.asString(); - } else if (name == "sasl-mechanism" || name == "sasl_mechanism" || - name == "sasl-mechanisms" || name == "sasl_mechanisms") { - settings.mechanism = value.asString(); - } else if (name == "sasl-service" || name == "sasl_service") { - settings.service = value.asString(); - } else if (name == "sasl-min-ssf" || name == "sasl_min_ssf") { - settings.minSsf = value; - } else if (name == "sasl-max-ssf" || name == "sasl_max_ssf") { - settings.maxSsf = value; - } else if (name == "heartbeat") { - settings.heartbeat = value; - } else if (name == "tcp-nodelay" || name == "tcp_nodelay") { - settings.tcpNoDelay = value; - } else if (name == "locale") { - settings.locale = value.asString(); - } else if (name == "max-channels" || name == "max_channels") { - settings.maxChannels = value; - } else if (name == "max-frame-size" || name == "max_frame_size") { - settings.maxFrameSize = value; - } else if (name == "bounds") { - settings.bounds = value; - } else if (name == "transport") { - settings.protocol = value.asString(); - } else if (name == "ssl-cert-name" || name == "ssl_cert_name") { - settings.sslCertName = value.asString(); - } else { - throw qpid::messaging::MessagingException(QPID_MSG("Invalid option: " << name << " not recognised")); - } -} - - -void ConnectionImpl::close() -{ - while(true) { - messaging::Session session; - { - qpid::sys::Mutex::ScopedLock l(lock); - if (sessions.empty()) break; - session = sessions.begin()->second; - } - session.close(); - } - detach(); -} - -void ConnectionImpl::detach() -{ - qpid::sys::Mutex::ScopedLock l(lock); - connection.close(); -} - -bool ConnectionImpl::isOpen() const -{ - qpid::sys::Mutex::ScopedLock l(lock); - return connection.isOpen(); -} - -boost::intrusive_ptr<SessionImpl> getImplPtr(qpid::messaging::Session& session) -{ - return boost::dynamic_pointer_cast<SessionImpl>( - qpid::messaging::PrivateImplRef<qpid::messaging::Session>::get(session) - ); -} - -void ConnectionImpl::closed(SessionImpl& s) -{ - qpid::sys::Mutex::ScopedLock l(lock); - for (Sessions::iterator i = sessions.begin(); i != sessions.end(); ++i) { - if (getImplPtr(i->second).get() == &s) { - sessions.erase(i); - break; - } - } -} - -qpid::messaging::Session ConnectionImpl::getSession(const std::string& name) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - Sessions::const_iterator i = sessions.find(name); - if (i == sessions.end()) { - throw qpid::messaging::KeyError("No such session: " + name); - } else { - return i->second; - } -} - -qpid::messaging::Session ConnectionImpl::newSession(bool transactional, const std::string& n) -{ - std::string name = n.empty() ? Uuid(true).str() : n; - qpid::messaging::Session impl(new SessionImpl(*this, transactional)); - while (true) { - try { - getImplPtr(impl)->setSession(connection.newSession(name)); - qpid::sys::Mutex::ScopedLock l(lock); - sessions[name] = impl; - break; - } catch (const qpid::TransportFailure&) { - open(); - } catch (const qpid::SessionException& e) { - throw qpid::messaging::SessionError(e.what()); - } catch (const std::exception& e) { - throw qpid::messaging::MessagingException(e.what()); - } - } - return impl; -} - -void ConnectionImpl::open() -{ - qpid::sys::AbsTime start = qpid::sys::now(); - qpid::sys::ScopedLock<qpid::sys::Semaphore> l(semaphore); - try { - if (!connection.isOpen()) connect(start); - } - catch (const types::Exception&) { throw; } - catch (const qpid::Exception& e) { throw messaging::ConnectionError(e.what()); } -} - -bool expired(const qpid::sys::AbsTime& start, int64_t timeout) -{ - if (timeout == 0) return true; - if (timeout < 0) return false; - qpid::sys::Duration used(start, qpid::sys::now()); - qpid::sys::Duration allowed = timeout * qpid::sys::TIME_SEC; - return allowed < used; -} - -void ConnectionImpl::connect(const qpid::sys::AbsTime& started) -{ - for (int64_t i = minReconnectInterval; !tryConnect(); i = std::min(i * 2, maxReconnectInterval)) { - if (!reconnect) { - throw qpid::messaging::TransportFailure("Failed to connect (reconnect disabled)"); - } - if (limit >= 0 && retries++ >= limit) { - throw qpid::messaging::TransportFailure("Failed to connect within reconnect limit"); - } - if (expired(started, timeout)) { - throw qpid::messaging::TransportFailure("Failed to connect within reconnect timeout"); - } - else qpid::sys::sleep(i); - } - retries = 0; -} - -void ConnectionImpl::mergeUrls(const std::vector<Url>& more, const sys::Mutex::ScopedLock&) { - if (more.size()) { - for (size_t i = 0; i < more.size(); ++i) { - if (std::find(urls.begin(), urls.end(), more[i].str()) == urls.end()) { - urls.push_back(more[i].str()); - } - } - QPID_LOG(debug, "Added known-hosts, reconnect-urls=" << asString(urls)); - } -} - -bool ConnectionImpl::tryConnect() -{ - sys::Mutex::ScopedLock l(lock); - for (std::vector<std::string>::const_iterator i = urls.begin(); i != urls.end(); ++i) { - try { - QPID_LOG(info, "Trying to connect to " << *i << "..."); - //TODO: when url support is more complete can avoid this test here - if (i->find("amqp:") == 0) { - Url url(*i); - connection.open(url, settings); - } else { - SimpleUrlParser::parse(*i, settings); - connection.open(settings); - } - QPID_LOG(info, "Connected to " << *i); - mergeUrls(connection.getInitialBrokers(), l); - return resetSessions(l); - } catch (const qpid::ConnectionException& e) { - //TODO: need to fix timeout on - //qpid::client::Connection::open() so that it throws - //TransportFailure rather than a ConnectionException - QPID_LOG(info, "Failed to connect to " << *i << ": " << e.what()); - } - } - return false; -} - -bool ConnectionImpl::resetSessions(const sys::Mutex::ScopedLock& ) -{ - try { - qpid::sys::Mutex::ScopedLock l(lock); - for (Sessions::iterator i = sessions.begin(); i != sessions.end(); ++i) { - getImplPtr(i->second)->setSession(connection.newSession(i->first)); - } - return true; - } catch (const qpid::TransportFailure&) { - QPID_LOG(debug, "Connection failed while re-initialising sessions"); - return false; - } catch (const qpid::framing::ResourceLimitExceededException& e) { - if (reconnectOnLimitExceeded) { - QPID_LOG(debug, "Detaching and reconnecting due to: " << e.what()); - detach(); - return false; - } else { - throw qpid::messaging::TargetCapacityExceeded(e.what()); - } - } -} - -bool ConnectionImpl::backoff() -{ - if (reconnectOnLimitExceeded) { - detach(); - open(); - return true; - } else { - return false; - } -} -std::string ConnectionImpl::getAuthenticatedUsername() -{ - return connection.getNegotiatedSettings().username; -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h deleted file mode 100644 index 09f2038312..0000000000 --- a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_CONNECTIONIMPL_H -#define QPID_CLIENT_AMQP0_10_CONNECTIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/ConnectionImpl.h" -#include "qpid/types/Variant.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Semaphore.h" -#include <map> -#include <vector> - -namespace qpid { -struct Url; - -namespace client { -namespace amqp0_10 { - -class SessionImpl; - -class ConnectionImpl : public qpid::messaging::ConnectionImpl -{ - public: - ConnectionImpl(const std::string& url, const qpid::types::Variant::Map& options); - void open(); - bool isOpen() const; - void close(); - qpid::messaging::Session newSession(bool transactional, const std::string& name); - qpid::messaging::Session getSession(const std::string& name) const; - void closed(SessionImpl&); - void detach(); - void setOption(const std::string& name, const qpid::types::Variant& value); - bool backoff(); - std::string getAuthenticatedUsername(); - private: - typedef std::map<std::string, qpid::messaging::Session> Sessions; - - mutable qpid::sys::Mutex lock;//used to protect data structures - qpid::sys::Semaphore semaphore;//used to coordinate reconnection - Sessions sessions; - qpid::client::Connection connection; - std::vector<std::string> urls; - qpid::client::ConnectionSettings settings; - bool reconnect; - int64_t timeout; - int32_t limit; - int64_t minReconnectInterval; - int64_t maxReconnectInterval; - int32_t retries; - bool reconnectOnLimitExceeded; - - void setOptions(const qpid::types::Variant::Map& options); - void connect(const qpid::sys::AbsTime& started); - bool tryConnect(); - bool resetSessions(const sys::Mutex::ScopedLock&); // dummy parameter indicates call with lock held. - void mergeUrls(const std::vector<Url>& more, const sys::Mutex::ScopedLock&); -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_CONNECTIONIMPL_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp b/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp deleted file mode 100644 index 71e89bdba1..0000000000 --- a/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/amqp0_10/IncomingMessages.h" -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/types/Variant.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/enum.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using namespace qpid::framing; -using namespace qpid::framing::message; -using namespace qpid::amqp_0_10; -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::messaging::MessageImplAccess; -using qpid::types::Variant; - -namespace { -const std::string EMPTY_STRING; - - -struct GetNone : IncomingMessages::Handler -{ - bool accept(IncomingMessages::MessageTransfer&) { return false; } -}; - -struct GetAny : IncomingMessages::Handler -{ - bool accept(IncomingMessages::MessageTransfer& transfer) - { - transfer.retrieve(0); - return true; - } -}; - -struct MatchAndTrack -{ - const std::string destination; - SequenceSet ids; - - MatchAndTrack(const std::string& d) : destination(d) {} - - bool operator()(boost::shared_ptr<qpid::framing::FrameSet> command) - { - if (command->as<MessageTransferBody>()->getDestination() == destination) { - ids.add(command->getId()); - return true; - } else { - return false; - } - } -}; - -struct Match -{ - const std::string destination; - uint32_t matched; - - Match(const std::string& d) : destination(d), matched(0) {} - - bool operator()(boost::shared_ptr<qpid::framing::FrameSet> command) - { - if (command->as<MessageTransferBody>()->getDestination() == destination) { - ++matched; - return true; - } else { - return false; - } - } -}; -} - -void IncomingMessages::setSession(qpid::client::AsyncSession s) -{ - sys::Mutex::ScopedLock l(lock); - session = s; - incoming = SessionBase_0_10Access(session).get()->getDemux().getDefault(); - acceptTracker.reset(); -} - -bool IncomingMessages::get(Handler& handler, Duration timeout) -{ - { - sys::Mutex::ScopedLock l(lock); - //search through received list for any transfer of interest: - for (FrameSetQueue::iterator i = received.begin(); i != received.end(); i++) - { - MessageTransfer transfer(*i, *this); - if (handler.accept(transfer)) { - received.erase(i); - return true; - } - } - } - //none found, check incoming: - return process(&handler, timeout); -} - -bool IncomingMessages::getNextDestination(std::string& destination, Duration timeout) -{ - sys::Mutex::ScopedLock l(lock); - //if there is not already a received message, we must wait for one - if (received.empty() && !wait(timeout)) return false; - //else we have a message in received; return the corresponding destination - destination = received.front()->as<MessageTransferBody>()->getDestination(); - return true; -} - -void IncomingMessages::accept() -{ - sys::Mutex::ScopedLock l(lock); - acceptTracker.accept(session); -} - -void IncomingMessages::accept(qpid::framing::SequenceNumber id) -{ - sys::Mutex::ScopedLock l(lock); - acceptTracker.accept(id, session); -} - - -void IncomingMessages::releaseAll() -{ - { - //first process any received messages... - sys::Mutex::ScopedLock l(lock); - while (!received.empty()) { - retrieve(received.front(), 0); - received.pop_front(); - } - } - //then pump out any available messages from incoming queue... - GetAny handler; - while (process(&handler, 0)) ; - //now release all messages - sys::Mutex::ScopedLock l(lock); - acceptTracker.release(session); -} - -void IncomingMessages::releasePending(const std::string& destination) -{ - //first pump all available messages from incoming to received... - while (process(0, 0)) ; - - //now remove all messages for this destination from received list, recording their ids... - sys::Mutex::ScopedLock l(lock); - MatchAndTrack match(destination); - for (FrameSetQueue::iterator i = received.begin(); i != received.end(); i = match(*i) ? received.erase(i) : ++i) ; - //now release those messages - session.messageRelease(match.ids); -} - -/** - * Get a frameset that is accepted by the specified handler from - * session queue, waiting for up to the specified duration and - * returning true if this could be achieved, false otherwise. Messages - * that are not accepted by the handler are pushed onto received queue - * for later retrieval. - */ -bool IncomingMessages::process(Handler* handler, qpid::sys::Duration duration) -{ - AbsTime deadline(AbsTime::now(), duration); - FrameSet::shared_ptr content; - try { - for (Duration timeout = duration; incoming->pop(content, timeout); timeout = Duration(AbsTime::now(), deadline)) { - if (content->isA<MessageTransferBody>()) { - MessageTransfer transfer(content, *this); - if (handler && handler->accept(transfer)) { - QPID_LOG(debug, "Delivered " << *content->getMethod()); - return true; - } else { - //received message for another destination, keep for later - QPID_LOG(debug, "Pushed " << *content->getMethod() << " to received queue"); - sys::Mutex::ScopedLock l(lock); - received.push_back(content); - } - } else { - //TODO: handle other types of commands (e.g. message-accept, message-flow etc) - } - } - } - catch (const qpid::ClosedException&) {} // Just return false if queue closed. - return false; -} - -bool IncomingMessages::wait(qpid::sys::Duration duration) -{ - AbsTime deadline(AbsTime::now(), duration); - FrameSet::shared_ptr content; - for (Duration timeout = duration; incoming->pop(content, timeout); timeout = Duration(AbsTime::now(), deadline)) { - if (content->isA<MessageTransferBody>()) { - QPID_LOG(debug, "Pushed " << *content->getMethod() << " to received queue"); - sys::Mutex::ScopedLock l(lock); - received.push_back(content); - return true; - } else { - //TODO: handle other types of commands (e.g. message-accept, message-flow etc) - } - } - return false; -} - -uint32_t IncomingMessages::pendingAccept() -{ - sys::Mutex::ScopedLock l(lock); - return acceptTracker.acceptsPending(); -} -uint32_t IncomingMessages::pendingAccept(const std::string& destination) -{ - sys::Mutex::ScopedLock l(lock); - return acceptTracker.acceptsPending(destination); -} - -uint32_t IncomingMessages::available() -{ - //first pump all available messages from incoming to received... - while (process(0, 0)) {} - //return the count of received messages - sys::Mutex::ScopedLock l(lock); - return received.size(); -} - -uint32_t IncomingMessages::available(const std::string& destination) -{ - //first pump all available messages from incoming to received... - while (process(0, 0)) {} - - //count all messages for this destination from received list - sys::Mutex::ScopedLock l(lock); - return std::for_each(received.begin(), received.end(), Match(destination)).matched; -} - -void populate(qpid::messaging::Message& message, FrameSet& command); - -/** - * Called when message is retrieved; records retrieval for subsequent - * acceptance, marks the command as completed and converts command to - * message if message is required - */ -void IncomingMessages::retrieve(FrameSetPtr command, qpid::messaging::Message* message) -{ - if (message) { - populate(*message, *command); - } - const MessageTransferBody* transfer = command->as<MessageTransferBody>(); - if (transfer->getAcquireMode() == ACQUIRE_MODE_PRE_ACQUIRED && transfer->getAcceptMode() == ACCEPT_MODE_EXPLICIT) { - acceptTracker.delivered(transfer->getDestination(), command->getId()); - } - session.markCompleted(command->getId(), false, false); -} - -IncomingMessages::MessageTransfer::MessageTransfer(FrameSetPtr c, IncomingMessages& p) : content(c), parent(p) {} - -const std::string& IncomingMessages::MessageTransfer::getDestination() -{ - return content->as<MessageTransferBody>()->getDestination(); -} -void IncomingMessages::MessageTransfer::retrieve(qpid::messaging::Message* message) -{ - parent.retrieve(content, message); -} - - -namespace { -//TODO: unify conversion to and from 0-10 message that is currently -//split between IncomingMessages and OutgoingMessage -const std::string SUBJECT("qpid.subject"); - -const std::string X_APP_ID("x-amqp-0-10.app-id"); -const std::string X_ROUTING_KEY("x-amqp-0-10.routing-key"); -const std::string X_CONTENT_ENCODING("x-amqp-0-10.content-encoding"); -} - -void populateHeaders(qpid::messaging::Message& message, - const DeliveryProperties* deliveryProperties, - const MessageProperties* messageProperties) -{ - if (deliveryProperties) { - message.setTtl(qpid::messaging::Duration(deliveryProperties->getTtl())); - message.setDurable(deliveryProperties->getDeliveryMode() == DELIVERY_MODE_PERSISTENT); - message.setPriority(deliveryProperties->getPriority()); - message.setRedelivered(deliveryProperties->getRedelivered()); - } - if (messageProperties) { - message.setContentType(messageProperties->getContentType()); - if (messageProperties->hasReplyTo()) { - message.setReplyTo(AddressResolution::convert(messageProperties->getReplyTo())); - } - message.setSubject(messageProperties->getApplicationHeaders().getAsString(SUBJECT)); - message.getProperties().clear(); - translate(messageProperties->getApplicationHeaders(), message.getProperties()); - message.setCorrelationId(messageProperties->getCorrelationId()); - message.setUserId(messageProperties->getUserId()); - if (messageProperties->hasMessageId()) { - message.setMessageId(messageProperties->getMessageId().str()); - } - //expose 0-10 specific items through special properties: - // app-id, content-encoding - if (messageProperties->hasAppId()) { - message.getProperties()[X_APP_ID] = messageProperties->getAppId(); - } - if (messageProperties->hasContentEncoding()) { - message.getProperties()[X_CONTENT_ENCODING] = messageProperties->getContentEncoding(); - } - // routing-key, others? - if (deliveryProperties && deliveryProperties->hasRoutingKey()) { - message.getProperties()[X_ROUTING_KEY] = deliveryProperties->getRoutingKey(); - } - } -} - -void populateHeaders(qpid::messaging::Message& message, const AMQHeaderBody* headers) -{ - populateHeaders(message, headers->get<DeliveryProperties>(), headers->get<MessageProperties>()); -} - -void populate(qpid::messaging::Message& message, FrameSet& command) -{ - //need to be able to link the message back to the transfer it was delivered by - //e.g. for rejecting. - MessageImplAccess::get(message).setInternalId(command.getId()); - - message.setContent(command.getContent()); - - populateHeaders(message, command.getHeaders()); -} - - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/IncomingMessages.h b/cpp/src/qpid/client/amqp0_10/IncomingMessages.h deleted file mode 100644 index f6a291bc68..0000000000 --- a/cpp/src/qpid/client/amqp0_10/IncomingMessages.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_INCOMINGMESSAGES_H -#define QPID_CLIENT_AMQP0_10_INCOMINGMESSAGES_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include <boost/shared_ptr.hpp> -#include "qpid/client/AsyncSession.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/sys/Time.h" -#include "qpid/client/amqp0_10/AcceptTracker.h" - -namespace qpid { - -namespace framing{ -class FrameSet; -} - -namespace messaging { -class Message; -} - -namespace client { -namespace amqp0_10 { - -/** - * Queue of incoming messages. - */ -class IncomingMessages -{ - public: - typedef boost::shared_ptr<qpid::framing::FrameSet> FrameSetPtr; - class MessageTransfer - { - public: - const std::string& getDestination(); - void retrieve(qpid::messaging::Message* message); - private: - FrameSetPtr content; - IncomingMessages& parent; - - MessageTransfer(FrameSetPtr, IncomingMessages&); - friend class IncomingMessages; - }; - - struct Handler - { - virtual ~Handler() {} - virtual bool accept(MessageTransfer& transfer) = 0; - }; - - void setSession(qpid::client::AsyncSession session); - bool get(Handler& handler, qpid::sys::Duration timeout); - bool getNextDestination(std::string& destination, qpid::sys::Duration timeout); - void accept(); - void accept(qpid::framing::SequenceNumber id); - void releaseAll(); - void releasePending(const std::string& destination); - - uint32_t pendingAccept(); - uint32_t pendingAccept(const std::string& destination); - - uint32_t available(); - uint32_t available(const std::string& destination); - private: - typedef std::deque<FrameSetPtr> FrameSetQueue; - - sys::Mutex lock; - qpid::client::AsyncSession session; - boost::shared_ptr< sys::BlockingQueue<FrameSetPtr> > incoming; - FrameSetQueue received; - AcceptTracker acceptTracker; - - bool process(Handler*, qpid::sys::Duration); - bool wait(qpid::sys::Duration); - void retrieve(FrameSetPtr, qpid::messaging::Message*); - -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_INCOMINGMESSAGES_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/MessageSink.h b/cpp/src/qpid/client/amqp0_10/MessageSink.h deleted file mode 100644 index 8d87a3c7bb..0000000000 --- a/cpp/src/qpid/client/amqp0_10/MessageSink.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_MESSAGESINK_H -#define QPID_CLIENT_AMQP0_10_MESSAGESINK_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include "qpid/client/AsyncSession.h" - -namespace qpid { - -namespace messaging { -class Message; -} - -namespace client { -namespace amqp0_10 { - -struct OutgoingMessage; - -/** - * - */ -class MessageSink -{ - public: - virtual ~MessageSink() {} - virtual void declare(qpid::client::AsyncSession& session, const std::string& name) = 0; - virtual void send(qpid::client::AsyncSession& session, const std::string& name, OutgoingMessage& message) = 0; - virtual void cancel(qpid::client::AsyncSession& session, const std::string& name) = 0; - private: -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_MESSAGESINK_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/MessageSource.h b/cpp/src/qpid/client/amqp0_10/MessageSource.h deleted file mode 100644 index 74f2732f59..0000000000 --- a/cpp/src/qpid/client/amqp0_10/MessageSource.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_MESSAGESOURCE_H -#define QPID_CLIENT_AMQP0_10_MESSAGESOURCE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include "qpid/client/AsyncSession.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -/** - * Abstraction behind which the AMQP 0-10 commands required to - * establish (and tear down) an incoming stream of messages from a - * given address are hidden. - */ -class MessageSource -{ - public: - virtual ~MessageSource() {} - virtual void subscribe(qpid::client::AsyncSession& session, const std::string& destination) = 0; - virtual void cancel(qpid::client::AsyncSession& session, const std::string& destination) = 0; - - private: -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_MESSAGESOURCE_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp deleted file mode 100644 index d93416da75..0000000000 --- a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/amqp0_10/OutgoingMessage.h" -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/types/Variant.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/framing/enum.h" -#include <sstream> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::messaging::Address; -using qpid::messaging::MessageImplAccess; -using qpid::types::Variant; -using namespace qpid::framing::message; -using namespace qpid::amqp_0_10; - -namespace { -//TODO: unify conversion to and from 0-10 message that is currently -//split between IncomingMessages and OutgoingMessage -const std::string SUBJECT("qpid.subject"); -const std::string X_APP_ID("x-amqp-0-10.app-id"); -const std::string X_ROUTING_KEY("x-amqp-0-10.routing-key"); -const std::string X_CONTENT_ENCODING("x-amqp-0-10.content-encoding"); -} - -void OutgoingMessage::convert(const qpid::messaging::Message& from) -{ - //TODO: need to avoid copying as much as possible - message.setData(from.getContent()); - message.getMessageProperties().setContentType(from.getContentType()); - message.getMessageProperties().setCorrelationId(from.getCorrelationId()); - message.getMessageProperties().setUserId(from.getUserId()); - const Address& address = from.getReplyTo(); - if (address) { - message.getMessageProperties().setReplyTo(AddressResolution::convert(address)); - } - translate(from.getProperties(), message.getMessageProperties().getApplicationHeaders()); - if (from.getTtl().getMilliseconds()) { - message.getDeliveryProperties().setTtl(from.getTtl().getMilliseconds()); - } - if (from.getDurable()) { - message.getDeliveryProperties().setDeliveryMode(DELIVERY_MODE_PERSISTENT); - } - if (from.getRedelivered()) { - message.getDeliveryProperties().setRedelivered(true); - } - if (from.getPriority()) message.getDeliveryProperties().setPriority(from.getPriority()); - - //allow certain 0-10 specific items to be set through special properties: - // message-id, app-id, content-encoding - if (from.getMessageId().size()) { - qpid::framing::Uuid uuid; - std::istringstream data(from.getMessageId()); - data >> uuid; - message.getMessageProperties().setMessageId(uuid); - } - Variant::Map::const_iterator i; - i = from.getProperties().find(X_APP_ID); - if (i != from.getProperties().end()) { - message.getMessageProperties().setAppId(i->second.asString()); - } - i = from.getProperties().find(X_CONTENT_ENCODING); - if (i != from.getProperties().end()) { - message.getMessageProperties().setContentEncoding(i->second.asString()); - } -} - -void OutgoingMessage::setSubject(const std::string& subject) -{ - if (!subject.empty()) { - message.getMessageProperties().getApplicationHeaders().setString(SUBJECT, subject); - } -} - -std::string OutgoingMessage::getSubject() const -{ - return message.getMessageProperties().getApplicationHeaders().getAsString(SUBJECT); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h deleted file mode 100644 index 0cdd2a2336..0000000000 --- a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_OUTGOINGMESSAGE_H -#define QPID_CLIENT_AMQP0_10_OUTGOINGMESSAGE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Completion.h" -#include "qpid/client/Message.h" - -namespace qpid { -namespace messaging { -class Message; -} -namespace client { -namespace amqp0_10 { - -struct OutgoingMessage -{ - qpid::client::Message message; - qpid::client::Completion status; - - void convert(const qpid::messaging::Message&); - void setSubject(const std::string& subject); - std::string getSubject() const; -}; - - - -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_OUTGOINGMESSAGE_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp b/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp deleted file mode 100644 index 030b804143..0000000000 --- a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "ReceiverImpl.h" -#include "AddressResolution.h" -#include "MessageSource.h" -#include "SessionImpl.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Session.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -using qpid::messaging::NoMessageAvailable; -using qpid::messaging::Receiver; -using qpid::messaging::Duration; - -void ReceiverImpl::received(qpid::messaging::Message&) -{ - //TODO: should this be configurable - sys::Mutex::ScopedLock l(lock); - if (capacity && --window <= capacity/2) { - session.sendCompletion(); - window = capacity; - } -} - -qpid::messaging::Message ReceiverImpl::get(qpid::messaging::Duration timeout) -{ - qpid::messaging::Message result; - if (!get(result, timeout)) throw NoMessageAvailable(); - return result; -} - -qpid::messaging::Message ReceiverImpl::fetch(qpid::messaging::Duration timeout) -{ - qpid::messaging::Message result; - if (!fetch(result, timeout)) throw NoMessageAvailable(); - return result; -} - -bool ReceiverImpl::get(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - Get f(*this, message, timeout); - while (!parent->execute(f)) {} - return f.result; -} - -bool ReceiverImpl::fetch(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - Fetch f(*this, message, timeout); - while (!parent->execute(f)) {} - return f.result; -} - -void ReceiverImpl::close() -{ - execute<Close>(); -} - -void ReceiverImpl::start() -{ - sys::Mutex::ScopedLock l(lock); - if (state == STOPPED) { - state = STARTED; - startFlow(l); - } -} - -void ReceiverImpl::stop() -{ - sys::Mutex::ScopedLock l(lock); - state = STOPPED; - session.messageStop(destination); -} - -void ReceiverImpl::setCapacity(uint32_t c) -{ - execute1<SetCapacity>(c); -} - -void ReceiverImpl::startFlow(const sys::Mutex::ScopedLock&) -{ - if (capacity > 0) { - session.messageSetFlowMode(destination, FLOW_MODE_WINDOW); - session.messageFlow(destination, CREDIT_UNIT_MESSAGE, capacity); - session.messageFlow(destination, CREDIT_UNIT_BYTE, byteCredit); - window = capacity; - } -} - -void ReceiverImpl::init(qpid::client::AsyncSession s, AddressResolution& resolver) -{ - sys::Mutex::ScopedLock l(lock); - session = s; - if (state == CANCELLED) return; - if (state == UNRESOLVED) { - source = resolver.resolveSource(session, address); - assert(source.get()); - state = STARTED; - } - source->subscribe(session, destination); - startFlow(l); -} - -const std::string& ReceiverImpl::getName() const { - sys::Mutex::ScopedLock l(lock); - return destination; -} - -uint32_t ReceiverImpl::getCapacity() -{ - sys::Mutex::ScopedLock l(lock); - return capacity; -} - -uint32_t ReceiverImpl::getAvailable() -{ - return parent->getReceivable(destination); -} - -uint32_t ReceiverImpl::getUnsettled() -{ - return parent->getUnsettledAcks(destination); -} - -ReceiverImpl::ReceiverImpl(SessionImpl& p, const std::string& name, - const qpid::messaging::Address& a) : - - parent(&p), destination(name), address(a), byteCredit(0xFFFFFFFF), - state(UNRESOLVED), capacity(0), window(0) {} - -bool ReceiverImpl::getImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - { - sys::Mutex::ScopedLock l(lock); - if (state == CANCELLED) return false; - } - return parent->get(*this, message, timeout); -} - -bool ReceiverImpl::fetchImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - { - sys::Mutex::ScopedLock l(lock); - if (state == CANCELLED) return false; - - if (capacity == 0 || state != STARTED) { - session.messageSetFlowMode(destination, FLOW_MODE_CREDIT); - session.messageFlow(destination, CREDIT_UNIT_MESSAGE, 1); - session.messageFlow(destination, CREDIT_UNIT_BYTE, 0xFFFFFFFF); - } - } - if (getImpl(message, timeout)) { - return true; - } else { - qpid::client::Session s; - { - sys::Mutex::ScopedLock l(lock); - if (state == CANCELLED) return false; // Might have been closed during get. - s = sync(session); - } - s.messageFlush(destination); - { - sys::Mutex::ScopedLock l(lock); - startFlow(l); //reallocate credit - } - return getImpl(message, Duration::IMMEDIATE); - } -} - -void ReceiverImpl::closeImpl() -{ - sys::Mutex::ScopedLock l(lock); - if (state != CANCELLED) { - state = CANCELLED; - sync(session).messageStop(destination); - parent->releasePending(destination); - source->cancel(session, destination); - parent->receiverCancelled(destination); - } -} - -bool ReceiverImpl::isClosed() const { - sys::Mutex::ScopedLock l(lock); - return state == CANCELLED; -} - -void ReceiverImpl::setCapacityImpl(uint32_t c) -{ - sys::Mutex::ScopedLock l(lock); - if (c != capacity) { - capacity = c; - if (state == STARTED) { - session.messageStop(destination); - startFlow(l); - } - } -} - -qpid::messaging::Session ReceiverImpl::getSession() const -{ - return qpid::messaging::Session(parent.get()); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h b/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h deleted file mode 100644 index 5693b7b71f..0000000000 --- a/cpp/src/qpid/client/amqp0_10/ReceiverImpl.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_RECEIVERIMPL_H -#define QPID_CLIENT_AMQP0_10_RECEIVERIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/ReceiverImpl.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/amqp0_10/SessionImpl.h" -#include "qpid/messaging/Duration.h" -#include "qpid/sys/Mutex.h" -#include <boost/intrusive_ptr.hpp> -#include <memory> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -class AddressResolution; -class MessageSource; - -/** - * A receiver implementation based on an AMQP 0-10 subscription. - */ -class ReceiverImpl : public qpid::messaging::ReceiverImpl -{ - public: - - enum State {UNRESOLVED, STOPPED, STARTED, CANCELLED}; - - ReceiverImpl(SessionImpl& parent, const std::string& name, - const qpid::messaging::Address& address); - - void init(qpid::client::AsyncSession session, AddressResolution& resolver); - bool get(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - qpid::messaging::Message get(qpid::messaging::Duration timeout); - bool fetch(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - qpid::messaging::Message fetch(qpid::messaging::Duration timeout); - void close(); - void start(); - void stop(); - const std::string& getName() const; - void setCapacity(uint32_t); - uint32_t getCapacity(); - uint32_t getAvailable(); - uint32_t getUnsettled(); - void received(qpid::messaging::Message& message); - qpid::messaging::Session getSession() const; - bool isClosed() const; - - private: - mutable sys::Mutex lock; - boost::intrusive_ptr<SessionImpl> parent; - const std::string destination; - const qpid::messaging::Address address; - const uint32_t byteCredit; - State state; - - std::auto_ptr<MessageSource> source; - uint32_t capacity; - qpid::client::AsyncSession session; - qpid::messaging::MessageListener* listener; - uint32_t window; - - void startFlow(const sys::Mutex::ScopedLock&); // Dummy param, call with lock held - //implementation of public facing methods - bool fetchImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - bool getImpl(qpid::messaging::Message& message, qpid::messaging::Duration timeout); - void closeImpl(); - void setCapacityImpl(uint32_t); - - //functors for public facing methods. - struct Command - { - ReceiverImpl& impl; - - Command(ReceiverImpl& i) : impl(i) {} - }; - - struct Get : Command - { - qpid::messaging::Message& message; - qpid::messaging::Duration timeout; - bool result; - - Get(ReceiverImpl& i, qpid::messaging::Message& m, qpid::messaging::Duration t) : - Command(i), message(m), timeout(t), result(false) {} - void operator()() { result = impl.getImpl(message, timeout); } - }; - - struct Fetch : Command - { - qpid::messaging::Message& message; - qpid::messaging::Duration timeout; - bool result; - - Fetch(ReceiverImpl& i, qpid::messaging::Message& m, qpid::messaging::Duration t) : - Command(i), message(m), timeout(t), result(false) {} - void operator()() { result = impl.fetchImpl(message, timeout); } - }; - - struct Close : Command - { - Close(ReceiverImpl& i) : Command(i) {} - void operator()() { impl.closeImpl(); } - }; - - struct SetCapacity : Command - { - uint32_t capacity; - - SetCapacity(ReceiverImpl& i, uint32_t c) : Command(i), capacity(c) {} - void operator()() { impl.setCapacityImpl(capacity); } - }; - - //helper templates for some common patterns - template <class F> void execute() - { - F f(*this); - parent->execute(f); - } - - template <class F, class P> void execute1(P p) - { - F f(*this, p); - parent->execute(f); - } -}; - -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_RECEIVERIMPL_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp b/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp deleted file mode 100644 index f2f0f1a9e5..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "SenderImpl.h" -#include "MessageSink.h" -#include "SessionImpl.h" -#include "AddressResolution.h" -#include "OutgoingMessage.h" -#include "qpid/messaging/Session.h" - -namespace qpid { -namespace client { -namespace amqp0_10 { - -SenderImpl::SenderImpl(SessionImpl& _parent, const std::string& _name, - const qpid::messaging::Address& _address) : - parent(&_parent), name(_name), address(_address), state(UNRESOLVED), - capacity(50), window(0), flushed(false), unreliable(AddressResolution::is_unreliable(address)) {} - -void SenderImpl::send(const qpid::messaging::Message& message, bool sync) -{ - if (unreliable) { // immutable, don't need lock - UnreliableSend f(*this, &message); - parent->execute(f); - } else { - Send f(*this, &message); - while (f.repeat) parent->execute(f); - } - if (sync) parent->sync(true); -} - -void SenderImpl::close() -{ - execute<Close>(); -} - -void SenderImpl::setCapacity(uint32_t c) -{ - bool flush; - { - sys::Mutex::ScopedLock l(lock); - flush = c < capacity; - capacity = c; - } - execute1<CheckPendingSends>(flush); -} - -uint32_t SenderImpl::getCapacity() { - sys::Mutex::ScopedLock l(lock); - return capacity; -} - -uint32_t SenderImpl::getUnsettled() -{ - CheckPendingSends f(*this, false); - parent->execute(f); - return f.pending; -} - -void SenderImpl::init(qpid::client::AsyncSession s, AddressResolution& resolver) -{ - sys::Mutex::ScopedLock l(lock); - session = s; - if (state == UNRESOLVED) { - sink = resolver.resolveSink(session, address); - state = ACTIVE; - } - if (state == CANCELLED) { - sink->cancel(session, name); - sys::Mutex::ScopedUnlock u(lock); - parent->senderCancelled(name); - } else { - sink->declare(session, name); - replay(l); - } -} - -void SenderImpl::waitForCapacity() -{ - sys::Mutex::ScopedLock l(lock); - //TODO: add option to throw exception rather than blocking? - if (!unreliable && capacity <= - (flushed ? checkPendingSends(false, l) : outgoing.size())) - { - //Initial implementation is very basic. As outgoing is - //currently only reduced on receiving completions and we are - //blocking anyway we may as well sync(). If successful that - //should clear all outstanding sends. - session.sync(); - checkPendingSends(false, l); - } - //flush periodically and check for conmpleted sends - if (++window > (capacity / 4)) {//TODO: make this configurable? - checkPendingSends(true, l); - window = 0; - } -} - -void SenderImpl::sendImpl(const qpid::messaging::Message& m) -{ - sys::Mutex::ScopedLock l(lock); - std::auto_ptr<OutgoingMessage> msg(new OutgoingMessage()); - msg->convert(m); - msg->setSubject(m.getSubject().empty() ? address.getSubject() : m.getSubject()); - outgoing.push_back(msg.release()); - sink->send(session, name, outgoing.back()); -} - -void SenderImpl::sendUnreliable(const qpid::messaging::Message& m) -{ - sys::Mutex::ScopedLock l(lock); - OutgoingMessage msg; - msg.convert(m); - msg.setSubject(m.getSubject().empty() ? address.getSubject() : m.getSubject()); - sink->send(session, name, msg); -} - -void SenderImpl::replay(const sys::Mutex::ScopedLock&) -{ - for (OutgoingMessages::iterator i = outgoing.begin(); i != outgoing.end(); ++i) { - i->message.setRedelivered(true); - sink->send(session, name, *i); - } -} - -uint32_t SenderImpl::checkPendingSends(bool flush) { - sys::Mutex::ScopedLock l(lock); - return checkPendingSends(flush, l); -} - -uint32_t SenderImpl::checkPendingSends(bool flush, const sys::Mutex::ScopedLock&) -{ - if (flush) { - session.flush(); - flushed = true; - } else { - flushed = false; - } - while (!outgoing.empty() && outgoing.front().status.isComplete()) { - outgoing.pop_front(); - } - return outgoing.size(); -} - -void SenderImpl::closeImpl() -{ - sys::Mutex::ScopedLock l(lock); - state = CANCELLED; - sink->cancel(session, name); - parent->senderCancelled(name); -} - -const std::string& SenderImpl::getName() const -{ - sys::Mutex::ScopedLock l(lock); - return name; -} - -qpid::messaging::Session SenderImpl::getSession() const -{ - sys::Mutex::ScopedLock l(lock); - return qpid::messaging::Session(parent.get()); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/SenderImpl.h b/cpp/src/qpid/client/amqp0_10/SenderImpl.h deleted file mode 100644 index c10c77ae18..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SenderImpl.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_SENDERIMPL_H -#define QPID_CLIENT_AMQP0_10_SENDERIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/SenderImpl.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/amqp0_10/SessionImpl.h" -#include <memory> -#include <boost/intrusive_ptr.hpp> -#include <boost/ptr_container/ptr_deque.hpp> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -class AddressResolution; -class MessageSink; -struct OutgoingMessage; - -/** - * - */ -class SenderImpl : public qpid::messaging::SenderImpl -{ - public: - enum State {UNRESOLVED, ACTIVE, CANCELLED}; - - SenderImpl(SessionImpl& parent, const std::string& name, - const qpid::messaging::Address& address); - void send(const qpid::messaging::Message&, bool sync); - void close(); - void setCapacity(uint32_t); - uint32_t getCapacity(); - uint32_t getUnsettled(); - void init(qpid::client::AsyncSession, AddressResolution&); - const std::string& getName() const; - qpid::messaging::Session getSession() const; - - private: - mutable sys::Mutex lock; - boost::intrusive_ptr<SessionImpl> parent; - const std::string name; - const qpid::messaging::Address address; - State state; - std::auto_ptr<MessageSink> sink; - - qpid::client::AsyncSession session; - std::string destination; - std::string routingKey; - - typedef boost::ptr_deque<OutgoingMessage> OutgoingMessages; - OutgoingMessages outgoing; - uint32_t capacity; - uint32_t window; - bool flushed; - const bool unreliable; - - uint32_t checkPendingSends(bool flush); - // Dummy ScopedLock parameter means call with lock held - uint32_t checkPendingSends(bool flush, const sys::Mutex::ScopedLock&); - void replay(const sys::Mutex::ScopedLock&); - void waitForCapacity(); - - //logic for application visible methods: - void sendImpl(const qpid::messaging::Message&); - void sendUnreliable(const qpid::messaging::Message&); - void closeImpl(); - - - //functors for application visible methods (allowing locking and - //retry to be centralised): - struct Command - { - SenderImpl& impl; - - Command(SenderImpl& i) : impl(i) {} - }; - - struct Send : Command - { - const qpid::messaging::Message* message; - bool repeat; - - Send(SenderImpl& i, const qpid::messaging::Message* m) : Command(i), message(m), repeat(true) {} - void operator()() - { - impl.waitForCapacity(); - //from this point message will be recorded if there is any - //failure (and replayed) so need not repeat the call - repeat = false; - impl.sendImpl(*message); - } - }; - - struct UnreliableSend : Command - { - const qpid::messaging::Message* message; - - UnreliableSend(SenderImpl& i, const qpid::messaging::Message* m) : Command(i), message(m) {} - void operator()() - { - //TODO: ideally want to put messages on the outbound - //queue and pull them off in io thread, but the old - //0-10 client doesn't support that option so for now - //we simply don't queue unreliable messages - impl.sendUnreliable(*message); - } - }; - - struct Close : Command - { - Close(SenderImpl& i) : Command(i) {} - void operator()() { impl.closeImpl(); } - }; - - struct CheckPendingSends : Command - { - bool flush; - uint32_t pending; - CheckPendingSends(SenderImpl& i, bool f) : Command(i), flush(f), pending(0) {} - void operator()() { pending = impl.checkPendingSends(flush); } - }; - - //helper templates for some common patterns - template <class F> void execute() - { - F f(*this); - parent->execute(f); - } - - template <class F, class P> bool execute1(P p) - { - F f(*this, p); - return parent->execute(f); - } -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_SENDERIMPL_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp b/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp deleted file mode 100644 index 75a71997fd..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp +++ /dev/null @@ -1,525 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/amqp0_10/SessionImpl.h" -#include "qpid/client/amqp0_10/ConnectionImpl.h" -#include "qpid/client/amqp0_10/ReceiverImpl.h" -#include "qpid/client/amqp0_10/SenderImpl.h" -#include "qpid/client/amqp0_10/MessageSource.h" -#include "qpid/client/amqp0_10/MessageSink.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/messaging/PrivateImplRef.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Session.h" -#include <boost/format.hpp> -#include <boost/function.hpp> -#include <boost/intrusive_ptr.hpp> - -using qpid::messaging::KeyError; -using qpid::messaging::NoMessageAvailable; -using qpid::messaging::MessagingException; -using qpid::messaging::TransactionAborted; -using qpid::messaging::SessionError; -using qpid::messaging::MessageImplAccess; -using qpid::messaging::Sender; -using qpid::messaging::Receiver; - -namespace qpid { -namespace client { -namespace amqp0_10 { - -typedef qpid::sys::Mutex::ScopedLock ScopedLock; -typedef qpid::sys::Mutex::ScopedUnlock ScopedUnlock; - -SessionImpl::SessionImpl(ConnectionImpl& c, bool t) : connection(&c), transactional(t) {} - -void SessionImpl::checkError() -{ - qpid::client::SessionBase_0_10Access s(session); - s.get()->assertOpen(); -} - -bool SessionImpl::hasError() -{ - qpid::client::SessionBase_0_10Access s(session); - return s.get()->hasError(); -} - -void SessionImpl::sync(bool block) -{ - if (block) retry<Sync>(); - else execute<NonBlockingSync>(); -} - -void SessionImpl::commit() -{ - if (!execute<Commit>()) { - throw TransactionAborted("Transaction aborted due to transport failure"); - } -} - -void SessionImpl::rollback() -{ - //If the session fails during this operation, the transaction will - //be rolled back anyway. - execute<Rollback>(); -} - -void SessionImpl::acknowledge(bool sync_) -{ - //Should probably throw an exception on failure here, or indicate - //it through a return type at least. Failure means that the - //message may be redelivered; i.e. the application cannot delete - //any state necessary for preventing reprocessing of the message - execute<Acknowledge>(); - sync(sync_); -} - -void SessionImpl::reject(qpid::messaging::Message& m) -{ - //Possibly want to somehow indicate failure here as well. Less - //clear need as compared to acknowledge however. - execute1<Reject>(m); -} - -void SessionImpl::release(qpid::messaging::Message& m) -{ - execute1<Release>(m); -} - -void SessionImpl::acknowledge(qpid::messaging::Message& m) -{ - //Should probably throw an exception on failure here, or indicate - //it through a return type at least. Failure means that the - //message may be redelivered; i.e. the application cannot delete - //any state necessary for preventing reprocessing of the message - execute1<Acknowledge1>(m); -} - -void SessionImpl::close() -{ - if (hasError()) { - ScopedLock l(lock); - senders.clear(); - receivers.clear(); - } else { - while (true) { - Sender s; - { - ScopedLock l(lock); - if (senders.empty()) break; - s = senders.begin()->second; - } - s.close(); // outside the lock, will call senderCancelled - } - while (true) { - Receiver r; - { - ScopedLock l(lock); - if (receivers.empty()) break; - r = receivers.begin()->second; - } - r.close(); // outside the lock, will call receiverCancelled - } - } - connection->closed(*this); - if (!hasError()) session.close(); -} - -template <class T, class S> boost::intrusive_ptr<S> getImplPtr(T& t) -{ - return boost::dynamic_pointer_cast<S>(qpid::messaging::PrivateImplRef<T>::get(t)); -} - -template <class T> void getFreeKey(std::string& key, T& map) -{ - std::string name = key; - int count = 1; - for (typename T::const_iterator i = map.find(name); i != map.end(); i = map.find(name)) { - name = (boost::format("%1%_%2%") % key % ++count).str(); - } - key = name; -} - - -void SessionImpl::setSession(qpid::client::Session s) -{ - ScopedLock l(lock); - session = s; - incoming.setSession(session); - if (transactional) session.txSelect(); - for (Receivers::iterator i = receivers.begin(); i != receivers.end(); ++i) { - getImplPtr<Receiver, ReceiverImpl>(i->second)->init(session, resolver); - } - for (Senders::iterator i = senders.begin(); i != senders.end(); ++i) { - getImplPtr<Sender, SenderImpl>(i->second)->init(session, resolver); - } - session.sync(); -} - -struct SessionImpl::CreateReceiver : Command -{ - qpid::messaging::Receiver result; - const qpid::messaging::Address& address; - - CreateReceiver(SessionImpl& i, const qpid::messaging::Address& a) : - Command(i), address(a) {} - void operator()() { result = impl.createReceiverImpl(address); } -}; - -Receiver SessionImpl::createReceiver(const qpid::messaging::Address& address) -{ - return get1<CreateReceiver, Receiver>(address); -} - -Receiver SessionImpl::createReceiverImpl(const qpid::messaging::Address& address) -{ - ScopedLock l(lock); - std::string name = address.getName(); - getFreeKey(name, receivers); - Receiver receiver(new ReceiverImpl(*this, name, address)); - getImplPtr<Receiver, ReceiverImpl>(receiver)->init(session, resolver); - receivers[name] = receiver; - return receiver; -} - -struct SessionImpl::CreateSender : Command -{ - qpid::messaging::Sender result; - const qpid::messaging::Address& address; - - CreateSender(SessionImpl& i, const qpid::messaging::Address& a) : - Command(i), address(a) {} - void operator()() { result = impl.createSenderImpl(address); } -}; - -Sender SessionImpl::createSender(const qpid::messaging::Address& address) -{ - return get1<CreateSender, Sender>(address); -} - -Sender SessionImpl::createSenderImpl(const qpid::messaging::Address& address) -{ - ScopedLock l(lock); - std::string name = address.getName(); - getFreeKey(name, senders); - Sender sender(new SenderImpl(*this, name, address)); - getImplPtr<Sender, SenderImpl>(sender)->init(session, resolver); - senders[name] = sender; - return sender; -} - -Sender SessionImpl::getSender(const std::string& name) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - Senders::const_iterator i = senders.find(name); - if (i == senders.end()) { - throw KeyError(name); - } else { - return i->second; - } -} - -Receiver SessionImpl::getReceiver(const std::string& name) const -{ - qpid::sys::Mutex::ScopedLock l(lock); - Receivers::const_iterator i = receivers.find(name); - if (i == receivers.end()) { - throw KeyError(name); - } else { - return i->second; - } -} - -SessionImpl& SessionImpl::convert(qpid::messaging::Session& s) -{ - boost::intrusive_ptr<SessionImpl> impl = getImplPtr<qpid::messaging::Session, SessionImpl>(s); - if (!impl) { - throw SessionError(QPID_MSG("Configuration error; require qpid::client::amqp0_10::SessionImpl")); - } - return *impl; -} - -namespace { - -struct IncomingMessageHandler : IncomingMessages::Handler -{ - typedef boost::function1<bool, IncomingMessages::MessageTransfer&> Callback; - Callback callback; - - IncomingMessageHandler(Callback c) : callback(c) {} - - bool accept(IncomingMessages::MessageTransfer& transfer) - { - return callback(transfer); - } -}; - -} - - -bool SessionImpl::getNextReceiver(Receiver* receiver, IncomingMessages::MessageTransfer& transfer) -{ - ScopedLock l(lock); - Receivers::const_iterator i = receivers.find(transfer.getDestination()); - if (i == receivers.end()) { - QPID_LOG(error, "Received message for unknown destination " << transfer.getDestination()); - return false; - } else { - *receiver = i->second; - return true; - } -} - -bool SessionImpl::accept(ReceiverImpl* receiver, - qpid::messaging::Message* message, - IncomingMessages::MessageTransfer& transfer) -{ - if (receiver->getName() == transfer.getDestination()) { - transfer.retrieve(message); - receiver->received(*message); - return true; - } else { - return false; - } -} - -qpid::sys::Duration adjust(qpid::messaging::Duration timeout) -{ - uint64_t ms = timeout.getMilliseconds(); - if (ms < (uint64_t) (qpid::sys::TIME_INFINITE/qpid::sys::TIME_MSEC)) { - return ms * qpid::sys::TIME_MSEC; - } else { - return qpid::sys::TIME_INFINITE; - } -} - -bool SessionImpl::getIncoming(IncomingMessages::Handler& handler, qpid::messaging::Duration timeout) -{ - return incoming.get(handler, adjust(timeout)); -} - -bool SessionImpl::get(ReceiverImpl& receiver, qpid::messaging::Message& message, qpid::messaging::Duration timeout) -{ - IncomingMessageHandler handler(boost::bind(&SessionImpl::accept, this, &receiver, &message, _1)); - return getIncoming(handler, timeout); -} - -bool SessionImpl::nextReceiver(qpid::messaging::Receiver& receiver, qpid::messaging::Duration timeout) -{ - while (true) { - try { - std::string destination; - if (incoming.getNextDestination(destination, adjust(timeout))) { - qpid::sys::Mutex::ScopedLock l(lock); - Receivers::const_iterator i = receivers.find(destination); - if (i == receivers.end()) { - throw qpid::messaging::ReceiverError(QPID_MSG("Received message for unknown destination " << destination)); - } else { - receiver = i->second; - } - return true; - } else { - return false; - } - } catch (TransportFailure&) { - reconnect(); - } catch (const qpid::framing::ResourceLimitExceededException& e) { - if (backoff()) return false; - else throw qpid::messaging::TargetCapacityExceeded(e.what()); - } catch (const qpid::framing::UnauthorizedAccessException& e) { - throw qpid::messaging::UnauthorizedAccess(e.what()); - } catch (const qpid::SessionException& e) { - throw qpid::messaging::SessionError(e.what()); - } catch (const qpid::ConnectionException& e) { - throw qpid::messaging::ConnectionError(e.what()); - } catch (const qpid::ChannelException& e) { - throw qpid::messaging::MessagingException(e.what()); - } - } -} - -qpid::messaging::Receiver SessionImpl::nextReceiver(qpid::messaging::Duration timeout) -{ - qpid::messaging::Receiver receiver; - if (!nextReceiver(receiver, timeout)) throw NoMessageAvailable(); - if (!receiver) throw SessionError("Bad receiver returned!"); - return receiver; -} - -uint32_t SessionImpl::getReceivable() -{ - return get1<Receivable, uint32_t>((const std::string*) 0); -} -uint32_t SessionImpl::getReceivable(const std::string& destination) -{ - return get1<Receivable, uint32_t>(&destination); -} - -struct SessionImpl::Receivable : Command -{ - const std::string* destination; - uint32_t result; - - Receivable(SessionImpl& i, const std::string* d) : Command(i), destination(d), result(0) {} - void operator()() { result = impl.getReceivableImpl(destination); } -}; - -uint32_t SessionImpl::getReceivableImpl(const std::string* destination) -{ - ScopedLock l(lock); - if (destination) { - return incoming.available(*destination); - } else { - return incoming.available(); - } -} - -uint32_t SessionImpl::getUnsettledAcks() -{ - return get1<UnsettledAcks, uint32_t>((const std::string*) 0); -} - -uint32_t SessionImpl::getUnsettledAcks(const std::string& destination) -{ - return get1<UnsettledAcks, uint32_t>(&destination); -} - -struct SessionImpl::UnsettledAcks : Command -{ - const std::string* destination; - uint32_t result; - - UnsettledAcks(SessionImpl& i, const std::string* d) : Command(i), destination(d), result(0) {} - void operator()() { result = impl.getUnsettledAcksImpl(destination); } -}; - -uint32_t SessionImpl::getUnsettledAcksImpl(const std::string* destination) -{ - ScopedLock l(lock); - if (destination) { - return incoming.pendingAccept(*destination); - } else { - return incoming.pendingAccept(); - } -} - -void SessionImpl::syncImpl(bool block) -{ - if (block) session.sync(); - else session.flush(); - //cleanup unconfirmed accept records: - incoming.pendingAccept(); -} - -void SessionImpl::commitImpl() -{ - ScopedLock l(lock); - incoming.accept(); - session.txCommit(); -} - -void SessionImpl::rollbackImpl() -{ - ScopedLock l(lock); - for (Receivers::iterator i = receivers.begin(); i != receivers.end(); ++i) { - getImplPtr<Receiver, ReceiverImpl>(i->second)->stop(); - } - //ensure that stop has been processed and all previously sent - //messages are available for release: - session.sync(); - incoming.releaseAll(); - session.txRollback(); - - for (Receivers::iterator i = receivers.begin(); i != receivers.end(); ++i) { - getImplPtr<Receiver, ReceiverImpl>(i->second)->start(); - } -} - -void SessionImpl::acknowledgeImpl() -{ - ScopedLock l(lock); - if (!transactional) incoming.accept(); -} - -void SessionImpl::acknowledgeImpl(qpid::messaging::Message& m) -{ - ScopedLock l(lock); - if (!transactional) incoming.accept(MessageImplAccess::get(m).getInternalId()); -} - -void SessionImpl::rejectImpl(qpid::messaging::Message& m) -{ - SequenceSet set; - set.add(MessageImplAccess::get(m).getInternalId()); - session.messageReject(set); -} - -void SessionImpl::releaseImpl(qpid::messaging::Message& m) -{ - SequenceSet set; - set.add(MessageImplAccess::get(m).getInternalId()); - session.messageRelease(set); -} - -void SessionImpl::receiverCancelled(const std::string& name) -{ - ScopedLock l(lock); - receivers.erase(name); - session.sync(); - incoming.releasePending(name); -} - -void SessionImpl::releasePending(const std::string& name) -{ - ScopedLock l(lock); - incoming.releasePending(name); -} - -void SessionImpl::senderCancelled(const std::string& name) -{ - ScopedLock l(lock); - senders.erase(name); -} - -void SessionImpl::reconnect() -{ - connection->open(); -} - -bool SessionImpl::backoff() -{ - return connection->backoff(); -} - -qpid::messaging::Connection SessionImpl::getConnection() const -{ - return qpid::messaging::Connection(connection.get()); -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/SessionImpl.h b/cpp/src/qpid/client/amqp0_10/SessionImpl.h deleted file mode 100644 index 2a2aa47df6..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SessionImpl.h +++ /dev/null @@ -1,247 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_SESSIONIMPL_H -#define QPID_CLIENT_AMQP0_10_SESSIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/SessionImpl.h" -#include "qpid/messaging/Duration.h" -#include "qpid/messaging/exceptions.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/amqp0_10/AddressResolution.h" -#include "qpid/client/amqp0_10/IncomingMessages.h" -#include "qpid/sys/Mutex.h" -#include "qpid/framing/reply_exceptions.h" -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - -namespace messaging { -class Address; -class Connection; -class Message; -class Receiver; -class Sender; -class Session; -} - -namespace client { -namespace amqp0_10 { - -class ConnectionImpl; -class ReceiverImpl; -class SenderImpl; - -/** - * Implementation of the protocol independent Session interface using - * AMQP 0-10. - */ -class SessionImpl : public qpid::messaging::SessionImpl -{ - public: - SessionImpl(ConnectionImpl&, bool transactional); - void commit(); - void rollback(); - void acknowledge(bool sync); - void reject(qpid::messaging::Message&); - void release(qpid::messaging::Message&); - void acknowledge(qpid::messaging::Message& msg); - void close(); - void sync(bool block); - qpid::messaging::Sender createSender(const qpid::messaging::Address& address); - qpid::messaging::Receiver createReceiver(const qpid::messaging::Address& address); - - qpid::messaging::Sender getSender(const std::string& name) const; - qpid::messaging::Receiver getReceiver(const std::string& name) const; - - bool nextReceiver(qpid::messaging::Receiver& receiver, qpid::messaging::Duration timeout); - qpid::messaging::Receiver nextReceiver(qpid::messaging::Duration timeout); - - qpid::messaging::Connection getConnection() const; - void checkError(); - bool hasError(); - - bool get(ReceiverImpl& receiver, qpid::messaging::Message& message, qpid::messaging::Duration timeout); - - void releasePending(const std::string& destination); - void receiverCancelled(const std::string& name); - void senderCancelled(const std::string& name); - - uint32_t getReceivable(); - uint32_t getReceivable(const std::string& destination); - - uint32_t getUnsettledAcks(); - uint32_t getUnsettledAcks(const std::string& destination); - - void setSession(qpid::client::Session); - - template <class T> bool execute(T& f) - { - try { - f(); - return true; - } catch (const qpid::TransportFailure&) { - reconnect(); - return false; - } catch (const qpid::framing::ResourceLimitExceededException& e) { - if (backoff()) return false; - else throw qpid::messaging::TargetCapacityExceeded(e.what()); - } catch (const qpid::framing::UnauthorizedAccessException& e) { - throw qpid::messaging::UnauthorizedAccess(e.what()); - } catch (const qpid::SessionException& e) { - throw qpid::messaging::SessionError(e.what()); - } catch (const qpid::ConnectionException& e) { - throw qpid::messaging::ConnectionError(e.what()); - } catch (const qpid::ChannelException& e) { - throw qpid::messaging::MessagingException(e.what()); - } - } - - static SessionImpl& convert(qpid::messaging::Session&); - - private: - typedef std::map<std::string, qpid::messaging::Receiver> Receivers; - typedef std::map<std::string, qpid::messaging::Sender> Senders; - - mutable qpid::sys::Mutex lock; - boost::intrusive_ptr<ConnectionImpl> connection; - qpid::client::Session session; - AddressResolution resolver; - IncomingMessages incoming; - Receivers receivers; - Senders senders; - const bool transactional; - - bool accept(ReceiverImpl*, qpid::messaging::Message*, IncomingMessages::MessageTransfer&); - bool getIncoming(IncomingMessages::Handler& handler, qpid::messaging::Duration timeout); - bool getNextReceiver(qpid::messaging::Receiver* receiver, IncomingMessages::MessageTransfer& transfer); - void reconnect(); - bool backoff(); - - void commitImpl(); - void rollbackImpl(); - void acknowledgeImpl(); - void acknowledgeImpl(qpid::messaging::Message&); - void rejectImpl(qpid::messaging::Message&); - void releaseImpl(qpid::messaging::Message&); - void closeImpl(); - void syncImpl(bool block); - qpid::messaging::Sender createSenderImpl(const qpid::messaging::Address& address); - qpid::messaging::Receiver createReceiverImpl(const qpid::messaging::Address& address); - uint32_t getReceivableImpl(const std::string* destination); - uint32_t getUnsettledAcksImpl(const std::string* destination); - - //functors for public facing methods (allows locking and retry - //logic to be centralised) - struct Command - { - SessionImpl& impl; - - Command(SessionImpl& i) : impl(i) {} - }; - - struct Commit : Command - { - Commit(SessionImpl& i) : Command(i) {} - void operator()() { impl.commitImpl(); } - }; - - struct Rollback : Command - { - Rollback(SessionImpl& i) : Command(i) {} - void operator()() { impl.rollbackImpl(); } - }; - - struct Acknowledge : Command - { - Acknowledge(SessionImpl& i) : Command(i) {} - void operator()() { impl.acknowledgeImpl(); } - }; - - struct Sync : Command - { - Sync(SessionImpl& i) : Command(i) {} - void operator()() { impl.syncImpl(true); } - }; - - struct NonBlockingSync : Command - { - NonBlockingSync(SessionImpl& i) : Command(i) {} - void operator()() { impl.syncImpl(false); } - }; - - struct Reject : Command - { - qpid::messaging::Message& message; - - Reject(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {} - void operator()() { impl.rejectImpl(message); } - }; - - struct Release : Command - { - qpid::messaging::Message& message; - - Release(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {} - void operator()() { impl.releaseImpl(message); } - }; - - struct Acknowledge1 : Command - { - qpid::messaging::Message& message; - - Acknowledge1(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {} - void operator()() { impl.acknowledgeImpl(message); } - }; - - struct CreateSender; - struct CreateReceiver; - struct UnsettledAcks; - struct Receivable; - - //helper templates for some common patterns - template <class F> bool execute() - { - F f(*this); - return execute(f); - } - - template <class F> void retry() - { - while (!execute<F>()) {} - } - - template <class F, class P> bool execute1(P p) - { - F f(*this, p); - return execute(f); - } - - template <class F, class R, class P> R get1(P p) - { - F f(*this, p); - while (!execute(f)) {} - return f.result; - } -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_SESSIONIMPL_H*/ diff --git a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp deleted file mode 100644 index 327c2274a6..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "SimpleUrlParser.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/Exception.h" -#include <boost/lexical_cast.hpp> - -namespace qpid { -namespace client { -namespace amqp0_10 { - -bool split(const std::string& in, char delim, std::pair<std::string, std::string>& result) -{ - std::string::size_type i = in.find(delim); - if (i != std::string::npos) { - result.first = in.substr(0, i); - if (i+1 < in.size()) { - result.second = in.substr(i+1); - } - return true; - } else { - return false; - } -} - -void parseUsernameAndPassword(const std::string& in, qpid::client::ConnectionSettings& result) -{ - std::pair<std::string, std::string> parts; - if (!split(in, '/', parts)) { - result.username = in; - } else { - result.username = parts.first; - result.password = parts.second; - } -} - -void parseHostAndPort(const std::string& in, qpid::client::ConnectionSettings& result) -{ - std::pair<std::string, std::string> parts; - if (!split(in, ':', parts)) { - result.host = in; - } else { - result.host = parts.first; - if (parts.second.size()) { - result.port = boost::lexical_cast<uint16_t>(parts.second); - } - } -} - -void SimpleUrlParser::parse(const std::string& url, qpid::client::ConnectionSettings& result) -{ - std::pair<std::string, std::string> parts; - if (!split(url, '@', parts)) { - parseHostAndPort(url, result); - } else { - parseUsernameAndPassword(parts.first, result); - parseHostAndPort(parts.second, result); - } -} - -}}} // namespace qpid::client::amqp0_10 diff --git a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h deleted file mode 100644 index 24f90ca9d6..0000000000 --- a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H -#define QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> - -namespace qpid { -namespace client { - -struct ConnectionSettings; - -namespace amqp0_10 { - -/** - * Parses a simple url of the form user/password@hostname:port - */ -struct SimpleUrlParser -{ - static void parse(const std::string& url, qpid::client::ConnectionSettings& result); -}; -}}} // namespace qpid::client::amqp0_10 - -#endif /*!QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H*/ diff --git a/cpp/src/qpid/client/windows/SaslFactory.cpp b/cpp/src/qpid/client/windows/SaslFactory.cpp deleted file mode 100644 index d1ae762f1b..0000000000 --- a/cpp/src/qpid/client/windows/SaslFactory.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/SaslFactory.h" - -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/log/Statement.h" - -#include "boost/tokenizer.hpp" - -namespace qpid { - -using qpid::sys::SecurityLayer; -using qpid::sys::SecuritySettings; -using qpid::framing::InternalErrorException; - -struct WindowsSaslSettings -{ - WindowsSaslSettings ( ) : - username ( std::string(0) ), - password ( std::string(0) ), - service ( std::string(0) ), - host ( std::string(0) ), - minSsf ( 0 ), - maxSsf ( 0 ) - { - } - - WindowsSaslSettings ( const std::string & user, const std::string & password, const std::string & service, const std::string & host, int minSsf, int maxSsf ) : - username(user), - password(password), - service(service), - host(host), - minSsf(minSsf), - maxSsf(maxSsf) - { - } - - std::string username, - password, - service, - host; - - int minSsf, - maxSsf; -}; - -class WindowsSasl : public Sasl -{ - public: - WindowsSasl( const std::string &, const std::string &, const std::string &, const std::string &, int, int ); - ~WindowsSasl(); - std::string start(const std::string& mechanisms, const SecuritySettings* externalSettings); - std::string step(const std::string& challenge); - std::string getMechanism(); - std::string getUserId(); - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); - private: - WindowsSaslSettings settings; - std::string mechanism; -}; - -qpid::sys::Mutex SaslFactory::lock; -std::auto_ptr<SaslFactory> SaslFactory::instance; - -SaslFactory::SaslFactory() -{ -} - -SaslFactory::~SaslFactory() -{ -} - -SaslFactory& SaslFactory::getInstance() -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (!instance.get()) { - instance = std::auto_ptr<SaslFactory>(new SaslFactory()); - } - return *instance; -} - -std::auto_ptr<Sasl> SaslFactory::create( const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool ) -{ - std::auto_ptr<Sasl> sasl(new WindowsSasl( username, password, serviceName, hostName, minSsf, maxSsf )); - return sasl; -} - -namespace { - const std::string ANONYMOUS = "ANONYMOUS"; - const std::string PLAIN = "PLAIN"; -} - -WindowsSasl::WindowsSasl( const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf ) - : settings(username, password, serviceName, hostName, minSsf, maxSsf) -{ -} - -WindowsSasl::~WindowsSasl() -{ -} - -std::string WindowsSasl::start(const std::string& mechanisms, - const SecuritySettings* /*externalSettings*/) -{ - QPID_LOG(debug, "WindowsSasl::start(" << mechanisms << ")"); - - typedef boost::tokenizer<boost::char_separator<char> > tokenizer; - boost::char_separator<char> sep(" "); - bool havePlain = false; - bool haveAnon = false; - tokenizer mechs(mechanisms, sep); - for (tokenizer::iterator mech = mechs.begin(); - mech != mechs.end(); - ++mech) { - if (*mech == ANONYMOUS) - haveAnon = true; - else if (*mech == PLAIN) - havePlain = true; - } - if (!haveAnon && !havePlain) - throw InternalErrorException(QPID_MSG("Sasl error: no common mechanism")); - - std::string resp = ""; - if (havePlain) { - mechanism = PLAIN; - resp = ((char)0) + settings.username + ((char)0) + settings.password; - } - else { - mechanism = ANONYMOUS; - } - return resp; -} - -std::string WindowsSasl::step(const std::string& /*challenge*/) -{ - // Shouldn't get this for PLAIN... - throw InternalErrorException(QPID_MSG("Sasl step error")); -} - -std::string WindowsSasl::getMechanism() -{ - return mechanism; -} - -std::string WindowsSasl::getUserId() -{ - return std::string(); // TODO - when GSSAPI is supported, return userId for connection. -} - -std::auto_ptr<SecurityLayer> WindowsSasl::getSecurityLayer(uint16_t /*maxFrameSize*/) -{ - return std::auto_ptr<SecurityLayer>(0); -} - -} // namespace qpid diff --git a/cpp/src/qpid/client/windows/SslConnector.cpp b/cpp/src/qpid/client/windows/SslConnector.cpp deleted file mode 100644 index a33713e1a8..0000000000 --- a/cpp/src/qpid/client/windows/SslConnector.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/TCPConnector.h" - -#include "config.h" -#include "qpid/Msg.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/windows/check.h" -#include "qpid/sys/windows/SslAsynchIO.h" - -#include <iostream> -#include <boost/bind.hpp> -#include <boost/format.hpp> - -#include <memory.h> -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include <security.h> -#include <Schnlsp.h> -#undef SECURITY_WIN32 -#include <winsock2.h> - -namespace qpid { -namespace client { -namespace windows { - -using namespace qpid::sys; -using boost::format; -using boost::str; - - -class SslConnector : public qpid::client::TCPConnector -{ - qpid::sys::windows::ClientSslAsynchIO *shim; - boost::shared_ptr<qpid::sys::Poller> poller; - std::string brokerHost; - SCHANNEL_CRED cred; - CredHandle credHandle; - TimeStamp credExpiry; - - virtual ~SslConnector(); - void negotiationDone(SECURITY_STATUS status); - - // A number of AsynchIO callbacks go right through to TCPConnector, but - // we can't boost::bind to a protected ancestor, so these methods redirect - // to those TCPConnector methods. - bool redirectReadbuff(qpid::sys::AsynchIO&, qpid::sys::AsynchIOBufferBase*); - void redirectWritebuff(qpid::sys::AsynchIO&); - void redirectEof(qpid::sys::AsynchIO&); - -public: - SslConnector(boost::shared_ptr<qpid::sys::Poller>, - framing::ProtocolVersion pVersion, - const ConnectionSettings&, - ConnectionImpl*); - virtual void connect(const std::string& host, int port); - virtual void connected(const Socket&); - unsigned int getSSF(); -}; - -// Static constructor which registers connector here -namespace { - Connector* create(boost::shared_ptr<qpid::sys::Poller> p, - framing::ProtocolVersion v, - const ConnectionSettings& s, - ConnectionImpl* c) { - return new SslConnector(p, v, s, c); - } - - struct StaticInit { - StaticInit() { - try { - Connector::registerFactory("ssl", &create); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL connector: " << e.what()); - } - }; - ~StaticInit() { } - } init; -} - -void SslConnector::negotiationDone(SECURITY_STATUS status) -{ - if (status == SEC_E_OK) - initAmqp(); - else - connectFailed(QPID_MSG(qpid::sys::strError(status))); -} - -bool SslConnector::redirectReadbuff(qpid::sys::AsynchIO& a, - qpid::sys::AsynchIOBufferBase* b) { - return readbuff(a, b); -} - -void SslConnector::redirectWritebuff(qpid::sys::AsynchIO& a) { - writebuff(a); -} - -void SslConnector::redirectEof(qpid::sys::AsynchIO& a) { - eof(a); -} - -SslConnector::SslConnector(boost::shared_ptr<qpid::sys::Poller> p, - framing::ProtocolVersion ver, - const ConnectionSettings& settings, - ConnectionImpl* cimpl) - : TCPConnector(p, ver, settings, cimpl), shim(0), poller(p) -{ - memset(&cred, 0, sizeof(cred)); - cred.dwVersion = SCHANNEL_CRED_VERSION; - SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL, - UNISP_NAME, - SECPKG_CRED_OUTBOUND, - NULL, - &cred, - NULL, - NULL, - &credHandle, - &credExpiry); - if (status != SEC_E_OK) - throw QPID_WINDOWS_ERROR(status); - QPID_LOG(debug, "SslConnector created for " << ver.toString()); -} - -SslConnector::~SslConnector() -{ - ::FreeCredentialsHandle(&credHandle); -} - - // Will this get reach via virtual method via boost::bind???? - -void SslConnector::connect(const std::string& host, int port) { - brokerHost = host; - TCPConnector::connect(host, port); -} - -void SslConnector::connected(const Socket& s) { - shim = new qpid::sys::windows::ClientSslAsynchIO(brokerHost, - s, - credHandle, - boost::bind(&SslConnector::redirectReadbuff, this, _1, _2), - boost::bind(&SslConnector::redirectEof, this, _1), - boost::bind(&SslConnector::redirectEof, this, _1), - 0, // closed - 0, // nobuffs - boost::bind(&SslConnector::redirectWritebuff, this, _1), - boost::bind(&SslConnector::negotiationDone, this, _1)); - start(shim); - shim->start(poller); -} - -unsigned int SslConnector::getSSF() -{ - return shim->getSslKeySize(); -} - -}}} // namespace qpid::client::windows diff --git a/cpp/src/qpid/cluster/Cluster.cpp b/cpp/src/qpid/cluster/Cluster.cpp deleted file mode 100644 index 0daf0c7f5a..0000000000 --- a/cpp/src/qpid/cluster/Cluster.cpp +++ /dev/null @@ -1,1176 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * <h1>CLUSTER IMPLEMENTATION OVERVIEW</h1> - * - * The cluster works on the principle that if all members of the - * cluster receive identical input, they will all produce identical - * results. cluster::Connections intercept data received from clients - * and multicast it via CPG. The data is processed (passed to the - * broker::Connection) only when it is received from CPG in cluster - * order. Each cluster member has Connection objects for directly - * connected clients and "shadow" Connection objects for connections - * to other members. - * - * This assumes that all broker actions occur deterministically in - * response to data arriving on client connections. There are two - * situations where this assumption fails: - * - sending data in response to polling local connections for writabiliy. - * - taking actions based on a timer or timestamp comparison. - * - * IMPORTANT NOTE: any time code is added to the broker that uses timers, - * the cluster may need to be updated to take account of this. - * - * - * USE OF TIMESTAMPS IN THE BROKER - * - * The following are the current areas where broker uses timers or timestamps: - * - * - Producer flow control: broker::SemanticState uses - * connection::getClusterOrderOutput. a FrameHandler that sends - * frames to the client via the cluster. Used by broker::SessionState - * - * - QueueCleaner, Message TTL: uses ExpiryPolicy, which is - * implemented by cluster::ExpiryPolicy. - * - * - Connection heartbeat: sends connection controls, not part of - * session command counting so OK to ignore. - * - * - LinkRegistry: only cluster elder is ever active for links. - * - * - management::ManagementBroker: uses MessageHandler supplied by cluster - * to send messages to the broker via the cluster. - * - * - Dtx: not yet supported with cluster. - * - * cluster::ExpiryPolicy implements the strategy for message expiry. - * - * ClusterTimer implements periodic timed events in the cluster context. - * Used for periodic management events. - * - * <h1>CLUSTER PROTOCOL OVERVIEW</h1> - * - * Messages sent to/from CPG are called Events. - * - * An Event carries a ConnectionId, which includes a MemberId and a - * connection number. - * - * Events are either - * - Connection events: non-0 connection number and are associated with a connection. - * - Cluster Events: 0 connection number, are not associated with a connection. - * - * Events are further categorized as: - * - Control: carries method frame(s) that affect cluster behavior. - * - Data: carries raw data received from a client connection. - * - * The cluster defines extensions to the AMQP command set in ../../../xml/cluster.xml - * which defines two classes: - * - cluster: cluster control information. - * - cluster.connection: control information for a specific connection. - * - * The following combinations are legal: - * - Data frames carrying connection data. - * - Cluster control events carrying cluster commands. - * - Connection control events carrying cluster.connection commands. - * - Connection control events carrying non-cluster frames: frames sent to the client. - * e.g. flow-control frames generated on a timer. - * - * <h1>CLUSTER INITIALIZATION OVERVIEW</h1> - * - * @see InitialStatusMap - * - * When a new member joins the CPG group, all members (including the - * new one) multicast their "initial status." The new member is in - * PRE_INIT mode until it gets a complete set of initial status - * messages from all cluster members. In a newly-forming cluster is - * then in INIT mode until the configured cluster-size members have - * joined. - * - * The newcomer uses initial status to determine - * - The cluster UUID - * - Am I speaking the correct version of the cluster protocol? - * - Do I need to get an update from an existing active member? - * - Can I recover from my own store? - * - * Pre-initialization happens in the Cluster constructor (plugin - * early-init phase) because it needs to set the recovery flag before - * the store initializes. This phase lasts until inital-status is - * received for all active members. The PollableQueues and Multicaster - * are in "bypass" mode during this phase since the poller has not - * started so there are no threads to serve pollable queues. - * - * The remaining initialization happens in Cluster::initialize() or, - * if cluster-size=N is specified, in the deliver thread when an - * initial-status control is delivered that brings the total to N. - */ -#include "qpid/Exception.h" -#include "qpid/cluster/Cluster.h" -#include "qpid/sys/ClusterSafe.h" -#include "qpid/cluster/ClusterSettings.h" -#include "qpid/cluster/Connection.h" -#include "qpid/cluster/UpdateClient.h" -#include "qpid/cluster/RetractClient.h" -#include "qpid/cluster/FailoverExchange.h" -#include "qpid/cluster/UpdateDataExchange.h" -#include "qpid/cluster/UpdateExchange.h" -#include "qpid/cluster/ClusterTimer.h" - -#include "qpid/assert.h" -#include "qmf/org/apache/qpid/cluster/ArgsClusterStopClusterNode.h" -#include "qmf/org/apache/qpid/cluster/Package.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/SessionState.h" -#include "qpid/broker/SignalHandler.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQP_AllOperations.h" -#include "qpid/framing/AllInvoker.h" -#include "qpid/framing/ClusterConfigChangeBody.h" -#include "qpid/framing/ClusterConnectionDeliverCloseBody.h" -#include "qpid/framing/ClusterConnectionAbortBody.h" -#include "qpid/framing/ClusterRetractOfferBody.h" -#include "qpid/framing/ClusterConnectionDeliverDoOutputBody.h" -#include "qpid/framing/ClusterReadyBody.h" -#include "qpid/framing/ClusterShutdownBody.h" -#include "qpid/framing/ClusterUpdateOfferBody.h" -#include "qpid/framing/ClusterUpdateRequestBody.h" -#include "qpid/framing/ClusterConnectionAnnounceBody.h" -#include "qpid/framing/ClusterErrorCheckBody.h" -#include "qpid/framing/ClusterTimerWakeupBody.h" -#include "qpid/framing/ClusterDeliverToQueueBody.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Helpers.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/memory.h" -#include "qpid/sys/Thread.h" - -#include <boost/shared_ptr.hpp> -#include <boost/bind.hpp> -#include <boost/cast.hpp> -#include <boost/current_function.hpp> -#include <algorithm> -#include <iterator> -#include <map> -#include <ostream> - - -namespace qpid { -namespace cluster { -using namespace qpid; -using namespace qpid::framing; -using namespace qpid::sys; -using namespace qpid::cluster; -using namespace framing::cluster; -using namespace std; -using management::ManagementAgent; -using management::ManagementObject; -using management::Manageable; -using management::Args; -namespace _qmf = ::qmf::org::apache::qpid::cluster; - -/** - * NOTE: must increment this number whenever any incompatible changes in - * cluster protocol/behavior are made. It allows early detection and - * sensible reporting of an attempt to mix different versions in a - * cluster. - * - * Currently use SVN revision to avoid clashes with versions from - * different branches. - */ -const uint32_t Cluster::CLUSTER_VERSION = 1097431; - -struct ClusterDispatcher : public framing::AMQP_AllOperations::ClusterHandler { - qpid::cluster::Cluster& cluster; - MemberId member; - Cluster::Lock& l; - ClusterDispatcher(Cluster& c, const MemberId& id, Cluster::Lock& l_) : cluster(c), member(id), l(l_) {} - - void updateRequest(const std::string& url) { cluster.updateRequest(member, url, l); } - - void initialStatus(uint32_t version, bool active, const Uuid& clusterId, - uint8_t storeState, const Uuid& shutdownId, - const std::string& firstConfig) - { - cluster.initialStatus( - member, version, active, clusterId, - framing::cluster::StoreState(storeState), shutdownId, - firstConfig, l); - } - void ready(const std::string& url) { - cluster.ready(member, url, l); - } - void configChange(const std::string& members, - const std::string& left, - const std::string& joined) - { - cluster.configChange(member, members, left, joined, l); - } - void updateOffer(uint64_t updatee) { - cluster.updateOffer(member, updatee, l); - } - void retractOffer(uint64_t updatee) { cluster.retractOffer(member, updatee, l); } - void messageExpired(uint64_t id) { cluster.messageExpired(member, id, l); } - void errorCheck(uint8_t type, const framing::SequenceNumber& frameSeq) { - cluster.errorCheck(member, type, frameSeq, l); - } - void timerWakeup(const std::string& name) { cluster.timerWakeup(member, name, l); } - void timerDrop(const std::string& name) { cluster.timerDrop(member, name, l); } - void shutdown(const Uuid& id) { cluster.shutdown(member, id, l); } - void deliverToQueue(const std::string& queue, const std::string& message) { - cluster.deliverToQueue(queue, message, l); - } - bool invoke(AMQBody& body) { return framing::invoke(*this, body).wasHandled(); } -}; - -Cluster::Cluster(const ClusterSettings& set, broker::Broker& b) : - settings(set), - broker(b), - mgmtObject(0), - poller(b.getPoller()), - cpg(*this), - name(settings.name), - self(cpg.self()), - clusterId(true), - mAgent(0), - expiryPolicy(new ExpiryPolicy(mcast, self, broker.getTimer())), - mcast(cpg, poller, boost::bind(&Cluster::leave, this)), - dispatcher(cpg, poller, boost::bind(&Cluster::leave, this)), - deliverEventQueue(boost::bind(&Cluster::deliveredEvent, this, _1), - boost::bind(&Cluster::leave, this), - "Error decoding events, may indicate a broker version mismatch", - poller), - deliverFrameQueue(boost::bind(&Cluster::deliveredFrame, this, _1), - boost::bind(&Cluster::leave, this), - "Error delivering frames", - poller), - failoverExchange(new FailoverExchange(broker.GetVhostObject(), &broker)), - updateDataExchange(new UpdateDataExchange(*this)), - quorum(boost::bind(&Cluster::leave, this)), - decoder(boost::bind(&Cluster::deliverFrame, this, _1)), - discarding(true), - state(PRE_INIT), - initMap(self, settings.size), - store(broker.getDataDir().getPath()), - elder(false), - lastAliveCount(0), - lastBroker(false), - updateRetracted(false), - updateClosed(false), - error(*this) -{ - broker.setInCluster(true); - - // We give ownership of the timer to the broker and keep a plain pointer. - // This is OK as it means the timer has the same lifetime as the broker. - timer = new ClusterTimer(*this); - broker.setClusterTimer(std::auto_ptr<sys::Timer>(timer)); - - // Failover exchange provides membership updates to clients. - broker.getExchanges().registerExchange(failoverExchange); - - // Update exchange is used during updates to replicate messages - // without modifying delivery-properties.exchange. - broker.getExchanges().registerExchange( - boost::shared_ptr<broker::Exchange>(new UpdateExchange(this))); - - // Update-data exchange is used for passing data that may be too large - // for single control frame. - broker.getExchanges().registerExchange(updateDataExchange); - - // Load my store status before we go into initialization - if (! broker::NullMessageStore::isNullStore(&broker.getStore())) { - store.load(); - clusterId = store.getClusterId(); - QPID_LOG(notice, "Cluster store state: " << store) - } - cpg.join(name); - // pump the CPG dispatch manually till we get past PRE_INIT. - while (state == PRE_INIT) - cpg.dispatchOne(); -} - -Cluster::~Cluster() { - broker.setClusterTimer(std::auto_ptr<sys::Timer>(0)); // Delete cluster timer - if (updateThread) updateThread.join(); // Join the previous updatethread. -} - -void Cluster::initialize() { - if (settings.quorum) quorum.start(poller); - if (settings.url.empty()) - myUrl = Url::getIpAddressesUrl(broker.getPort(broker::Broker::TCP_TRANSPORT)); - else - myUrl = settings.url; - broker.getKnownBrokers = boost::bind(&Cluster::getUrls, this); - broker.deferDelivery = boost::bind(&Cluster::deferDeliveryImpl, this, _1, _2); - broker.setExpiryPolicy(expiryPolicy); - deliverEventQueue.bypassOff(); - deliverEventQueue.start(); - deliverFrameQueue.bypassOff(); - deliverFrameQueue.start(); - mcast.start(); - - /// Create management object - mAgent = broker.getManagementAgent(); - if (mAgent != 0){ - _qmf::Package packageInit(mAgent); - mgmtObject = new _qmf::Cluster (mAgent, this, &broker,name,myUrl.str()); - mAgent->addObject (mgmtObject); - } - - // Run initMapCompleted immediately to process the initial configuration - // that allowed us to transition out of PRE_INIT - assert(state == INIT); - initMapCompleted(*(Mutex::ScopedLock*)0); // Fake lock, single-threaded context. - - // Add finalizer last for exception safety. - broker.addFinalizer(boost::bind(&Cluster::brokerShutdown, this)); - - // Start dispatching CPG events. - dispatcher.start(); -} - -// Called in connection thread to insert a client connection. -void Cluster::addLocalConnection(const boost::intrusive_ptr<Connection>& c) { - assert(c->getId().getMember() == self); - localConnections.insert(c); -} - -// Called in connection thread to insert an updated shadow connection. -void Cluster::addShadowConnection(const boost::intrusive_ptr<Connection>& c) { - QPID_LOG(debug, *this << " new shadow connection " << c->getId()); - // Safe to use connections here because we're pre-catchup, stalled - // and discarding, so deliveredFrame is not processing any - // connection events. - assert(discarding); - pair<ConnectionMap::iterator, bool> ib - = connections.insert(ConnectionMap::value_type(c->getId(), c)); - assert(ib.second); -} - -void Cluster::erase(const ConnectionId& id) { - Lock l(lock); - erase(id,l); -} - -// Called by Connection::deliverClose() in deliverFrameQueue thread. -void Cluster::erase(const ConnectionId& id, Lock&) { - connections.erase(id); - decoder.erase(id); -} - -std::vector<string> Cluster::getIds() const { - Lock l(lock); - return getIds(l); -} - -std::vector<string> Cluster::getIds(Lock&) const { - return map.memberIds(); -} - -std::vector<Url> Cluster::getUrls() const { - Lock l(lock); - return getUrls(l); -} - -std::vector<Url> Cluster::getUrls(Lock&) const { - return map.memberUrls(); -} - -void Cluster::leave() { - Lock l(lock); - leave(l); -} - -#define LEAVE_TRY(STMT) try { STMT; } \ - catch (const std::exception& e) { \ - QPID_LOG(warning, *this << " error leaving cluster: " << e.what()); \ - } do {} while(0) - -void Cluster::leave(Lock&) { - if (state != LEFT) { - state = LEFT; - QPID_LOG(notice, *this << " leaving cluster " << name); - // Finalize connections now now to avoid problems later in destructor. - ClusterSafeScope css; // Don't trigger cluster-safe assertions. - LEAVE_TRY(localConnections.clear()); - LEAVE_TRY(connections.clear()); - LEAVE_TRY(broker::SignalHandler::shutdown()); - } -} - -// Deliver CPG message. -void Cluster::deliver( - cpg_handle_t /*handle*/, - const cpg_name* /*group*/, - uint32_t nodeid, - uint32_t pid, - void* msg, - int msg_len) -{ - MemberId from(nodeid, pid); - framing::Buffer buf(static_cast<char*>(msg), msg_len); - Event e(Event::decodeCopy(from, buf)); - deliverEvent(e); -} - -void Cluster::deliverEvent(const Event& e) { deliverEventQueue.push(e); } - -void Cluster::deliverFrame(const EventFrame& e) { deliverFrameQueue.push(e); } - -const ClusterUpdateOfferBody* castUpdateOffer(const framing::AMQBody* body) { - return (body && body->getMethod() && - body->getMethod()->isA<ClusterUpdateOfferBody>()) ? - static_cast<const ClusterUpdateOfferBody*>(body) : 0; -} - -const ClusterConnectionAnnounceBody* castAnnounce( const framing::AMQBody *body) { - return (body && body->getMethod() && - body->getMethod()->isA<ClusterConnectionAnnounceBody>()) ? - static_cast<const ClusterConnectionAnnounceBody*>(body) : 0; -} - -// Handler for deliverEventQueue. -// This thread decodes frames from events. -void Cluster::deliveredEvent(const Event& e) { - if (e.isCluster()) { - EventFrame ef(e, e.getFrame()); - // Stop the deliverEventQueue on update offers. - // This preserves the connection decoder fragments for an update. - // Only do this for the two brokers that are directly involved in this - // offer: the one making the offer, or the one receiving it. - const ClusterUpdateOfferBody* offer = castUpdateOffer(ef.frame.getBody()); - if (offer && ( e.getMemberId() == self || MemberId(offer->getUpdatee()) == self) ) { - QPID_LOG(info, *this << " stall for update offer from " << e.getMemberId() - << " to " << MemberId(offer->getUpdatee())); - deliverEventQueue.stop(); - } - deliverFrame(ef); - } - else if(!discarding) { - if (e.isControl()) - deliverFrame(EventFrame(e, e.getFrame())); - else { - try { decoder.decode(e, e.getData()); } - catch (const Exception& ex) { - // Close a connection that is sending us invalid data. - QPID_LOG(error, *this << " aborting connection " - << e.getConnectionId() << ": " << ex.what()); - framing::AMQFrame abort((ClusterConnectionAbortBody())); - deliverFrame(EventFrame(EventHeader(CONTROL, e.getConnectionId()), abort)); - } - } - } -} - -void Cluster::flagError( - Connection& connection, ErrorCheck::ErrorType type, const std::string& msg) -{ - Mutex::ScopedLock l(lock); - if (connection.isCatchUp()) { - QPID_LOG(critical, *this << " error on update connection " << connection - << ": " << msg); - leave(l); - } - error.error(connection, type, map.getFrameSeq(), map.getMembers(), msg); -} - -// Handler for deliverFrameQueue. -// This thread executes the main logic. -void Cluster::deliveredFrame(const EventFrame& efConst) { - Mutex::ScopedLock l(lock); - sys::ClusterSafeScope css; // Don't trigger cluster-safe asserts. - if (state == LEFT) return; - EventFrame e(efConst); - const ClusterUpdateOfferBody* offer = castUpdateOffer(e.frame.getBody()); - if (offer && error.isUnresolved()) { - // We can't honour an update offer that is delivered while an - // error is in progress so replace it with a retractOffer and re-start - // the event queue. - e.frame = AMQFrame( - ClusterRetractOfferBody(ProtocolVersion(), offer->getUpdatee())); - deliverEventQueue.start(); - } - // Process each frame through the error checker. - if (error.isUnresolved()) { - error.delivered(e); - while (error.canProcess()) // There is a frame ready to process. - processFrame(error.getNext(), l); - } - else - processFrame(e, l); -} - - -void Cluster::processFrame(const EventFrame& e, Lock& l) { - if (e.isCluster()) { - QPID_LOG(trace, *this << " DLVR: " << e); - ClusterDispatcher dispatch(*this, e.connectionId.getMember(), l); - if (!framing::invoke(dispatch, *e.frame.getBody()).wasHandled()) - throw Exception(QPID_MSG("Invalid cluster control")); - } - else if (state >= CATCHUP) { - map.incrementFrameSeq(); - ConnectionPtr connection = getConnection(e, l); - if (connection) { - QPID_LOG(trace, *this << " DLVR " << map.getFrameSeq() << ": " << e); - connection->deliveredFrame(e); - } - else - throw Exception(QPID_MSG("Unknown connection: " << e)); - } - else // Drop connection frames while state < CATCHUP - QPID_LOG(trace, *this << " DROP (joining): " << e); -} - -// Called in deliverFrameQueue thread -ConnectionPtr Cluster::getConnection(const EventFrame& e, Lock&) { - ConnectionId id = e.connectionId; - ConnectionMap::iterator i = connections.find(id); - if (i != connections.end()) return i->second; - ConnectionPtr cp; - // If the frame is an announcement for a new connection, add it. - const ClusterConnectionAnnounceBody *announce = castAnnounce(e.frame.getBody()); - if (e.frame.getBody() && e.frame.getMethod() && announce) - { - if (id.getMember() == self) { // Announces one of my own - cp = localConnections.getErase(id); - assert(cp); - } - else { // New remote connection, create a shadow. - qpid::sys::SecuritySettings secSettings; - if (announce) { - secSettings.ssf = announce->getSsf(); - secSettings.authid = announce->getAuthid(); - secSettings.nodict = announce->getNodict(); - } - cp = new Connection(*this, shadowOut, announce->getManagementId(), id, secSettings); - } - connections.insert(ConnectionMap::value_type(id, cp)); - } - return cp; -} - -Cluster::ConnectionVector Cluster::getConnections(Lock&) { - ConnectionVector result(connections.size()); - std::transform(connections.begin(), connections.end(), result.begin(), - boost::bind(&ConnectionMap::value_type::second, _1)); - return result; -} - -// CPG config-change callback. -void Cluster::configChange ( - cpg_handle_t /*handle*/, - const cpg_name */*group*/, - const cpg_address *members, int nMembers, - const cpg_address *left, int nLeft, - const cpg_address *joined, int nJoined) -{ - Mutex::ScopedLock l(lock); - string membersStr, leftStr, joinedStr; - // Encode members and enqueue as an event so the config change can - // be executed in the correct thread. - for (const cpg_address* p = members; p < members+nMembers; ++p) - membersStr.append(MemberId(*p).str()); - for (const cpg_address* p = left; p < left+nLeft; ++p) - leftStr.append(MemberId(*p).str()); - for (const cpg_address* p = joined; p < joined+nJoined; ++p) - joinedStr.append(MemberId(*p).str()); - deliverEvent(Event::control(ClusterConfigChangeBody( - ProtocolVersion(), membersStr, leftStr, joinedStr), - self)); -} - -void Cluster::setReady(Lock&) { - state = READY; - mcast.setReady(); - broker.getQueueEvents().enable(); - enableClusterSafe(); // Enable cluster-safe assertions. -} - -// Set the management status from the Cluster::state. -// -// NOTE: Management updates are sent based on property changes. In -// order to keep consistency across the cluster, we touch the local -// management status property even if it is locally unchanged for any -// event that could have cause a cluster property change on any cluster member. -void Cluster::setMgmtStatus(Lock&) { - if (mgmtObject) - mgmtObject->set_status(state >= CATCHUP ? "ACTIVE" : "JOINING"); -} - -void Cluster::initMapCompleted(Lock& l) { - // Called on completion of the initial status map. - QPID_LOG(debug, *this << " initial status map complete. "); - setMgmtStatus(l); - if (state == PRE_INIT) { - // PRE_INIT means we're still in the earlyInitialize phase, in the constructor. - // We decide here whether we want to recover from our store. - // We won't recover if we are joining an active cluster or our store is dirty. - if (store.hasStore() && - store.getState() != STORE_STATE_EMPTY_STORE && - (initMap.isActive() || store.getState() == STORE_STATE_DIRTY_STORE)) - broker.setRecovery(false); // Ditch my current store. - state = INIT; - } - else if (state == INIT) { - // INIT means we are past Cluster::initialize(). - - // If we're forming an initial cluster (no active members) - // then we wait to reach the configured cluster-size - if (!initMap.isActive() && initMap.getActualSize() < initMap.getRequiredSize()) { - QPID_LOG(info, *this << initMap.getActualSize() - << " members, waiting for at least " << initMap.getRequiredSize()); - return; - } - - initMap.checkConsistent(); - elders = initMap.getElders(); - QPID_LOG(debug, *this << " elders: " << elders); - if (elders.empty()) - becomeElder(l); - else { - broker.getLinks().setPassive(true); - broker.getQueueEvents().disable(); - QPID_LOG(info, *this << " not active for links."); - } - setClusterId(initMap.getClusterId(), l); - - if (initMap.isUpdateNeeded()) { // Joining established cluster. - broker.setRecovery(false); // Ditch my current store. - broker.setClusterUpdatee(true); - if (mAgent) mAgent->suppress(true); // Suppress mgmt output during update. - state = JOINER; - mcast.mcastControl(ClusterUpdateRequestBody(ProtocolVersion(), myUrl.str()), self); - QPID_LOG(notice, *this << " joining cluster " << name); - } - else { // I can go ready. - discarding = false; - setReady(l); - memberUpdate(l); - updateMgmtMembership(l); - mcast.mcastControl(ClusterReadyBody(ProtocolVersion(), myUrl.str()), self); - QPID_LOG(notice, *this << " joined cluster " << name); - } - } -} - -void Cluster::configChange(const MemberId&, - const std::string& membersStr, - const std::string& leftStr, - const std::string& joinedStr, - Lock& l) -{ - if (state == LEFT) return; - MemberSet members = decodeMemberSet(membersStr); - MemberSet left = decodeMemberSet(leftStr); - MemberSet joined = decodeMemberSet(joinedStr); - QPID_LOG(notice, *this << " configuration change: " << members); - QPID_LOG_IF(notice, !left.empty(), *this << " Members left: " << left); - QPID_LOG_IF(notice, !joined.empty(), *this << " Members joined: " << joined); - - // If we are still joining, make sure there is someone to give us an update. - elders = intersection(elders, members); - if (elders.empty() && INIT < state && state < CATCHUP) { - QPID_LOG(critical, "Cannot update, all potential updaters left the cluster."); - leave(l); - return; - } - bool memberChange = map.configChange(members); - - // Update initital status for members joining or leaving. - initMap.configChange(members); - if (initMap.isResendNeeded()) { - mcast.mcastControl( - ClusterInitialStatusBody( - ProtocolVersion(), CLUSTER_VERSION, state > INIT, clusterId, - store.getState(), store.getShutdownId(), - initMap.getFirstConfigStr() - ), - self); - } - if (initMap.transitionToComplete()) initMapCompleted(l); - - if (state >= CATCHUP && memberChange) { - memberUpdate(l); - if (elders.empty()) becomeElder(l); - } - - updateMgmtMembership(l); // Update on every config change for consistency -} - -void Cluster::becomeElder(Lock&) { - if (elder) return; // We were already the elder. - // We are the oldest, reactive links if necessary - QPID_LOG(info, *this << " became the elder, active for links."); - elder = true; - broker.getLinks().setPassive(false); - timer->becomeElder(); -} - -void Cluster::makeOffer(const MemberId& id, Lock& ) { - if (state == READY && map.isJoiner(id)) { - state = OFFER; - QPID_LOG(info, *this << " send update-offer to " << id); - mcast.mcastControl(ClusterUpdateOfferBody(ProtocolVersion(), id), self); - } -} - -namespace { -struct AppendQueue { - ostream* os; - AppendQueue(ostream& o) : os(&o) {} - void operator()(const boost::shared_ptr<broker::Queue>& q) { - (*os) << " " << q->getName() << "=" << q->getMessageCount(); - } -}; -} // namespace - -// Log a snapshot of broker state, used for debugging inconsistency problems. -// May only be called in deliver thread. -std::string Cluster::debugSnapshot() { - assertClusterSafe(); - std::ostringstream msg; - msg << "Member joined, frameSeq=" << map.getFrameSeq() << ", queue snapshot:"; - AppendQueue append(msg); - broker.getQueues().eachQueue(append); - return msg.str(); -} - -// Called from Broker::~Broker when broker is shut down. At this -// point we know the poller has stopped so no poller callbacks will be -// invoked. We must ensure that CPG has also shut down so no CPG -// callbacks will be invoked. -// -void Cluster::brokerShutdown() { - sys::ClusterSafeScope css; // Don't trigger cluster-safe asserts. - try { cpg.shutdown(); } - catch (const std::exception& e) { - QPID_LOG(error, *this << " shutting down CPG: " << e.what()); - } - delete this; -} - -void Cluster::updateRequest(const MemberId& id, const std::string& url, Lock& l) { - map.updateRequest(id, url); - makeOffer(id, l); -} - -void Cluster::initialStatus(const MemberId& member, uint32_t version, bool active, - const framing::Uuid& id, - framing::cluster::StoreState store, - const framing::Uuid& shutdownId, - const std::string& firstConfig, - Lock& l) -{ - if (version != CLUSTER_VERSION) { - QPID_LOG(critical, *this << " incompatible cluster versions " << - version << " != " << CLUSTER_VERSION); - leave(l); - return; - } - QPID_LOG_IF(debug, state == PRE_INIT, *this - << " received initial status from " << member); - initMap.received( - member, - ClusterInitialStatusBody(ProtocolVersion(), version, active, id, - store, shutdownId, firstConfig) - ); - if (initMap.transitionToComplete()) initMapCompleted(l); -} - -void Cluster::ready(const MemberId& id, const std::string& url, Lock& l) { - try { - if (map.ready(id, Url(url))) - memberUpdate(l); - if (state == CATCHUP && id == self) { - setReady(l); - QPID_LOG(notice, *this << " caught up."); - } - } catch (const Url::Invalid& e) { - QPID_LOG(error, "Invalid URL in cluster ready command: " << url); - } - // Update management on every ready event to be consistent across cluster. - setMgmtStatus(l); - updateMgmtMembership(l); -} - -void Cluster::updateOffer(const MemberId& updater, uint64_t updateeInt, Lock& l) { - // NOTE: deliverEventQueue has been stopped at the update offer by - // deliveredEvent in case an update is required. - if (state == LEFT) return; - MemberId updatee(updateeInt); - boost::optional<Url> url = map.updateOffer(updater, updatee); - if (updater == self) { - assert(state == OFFER); - if (url) // My offer was first. - updateStart(updatee, *url, l); - else { // Another offer was first. - QPID_LOG(info, *this << " cancelled offer to " << updatee << " unstall"); - setReady(l); - makeOffer(map.firstJoiner(), l); // Maybe make another offer. - deliverEventQueue.start(); // Go back to normal processing - } - } - else if (updatee == self && url) { - assert(state == JOINER); - state = UPDATEE; - QPID_LOG(notice, *this << " receiving update from " << updater); - checkUpdateIn(l); - } - else { - QPID_LOG(info, *this << " unstall, ignore update " << updater - << " to " << updatee); - deliverEventQueue.start(); // Not involved in update. - } - if (updatee != self && url) { - QPID_LOG(debug, debugSnapshot()); - if (mAgent) mAgent->clusterUpdate(); - // Updatee will call clusterUpdate when update completes - } -} - -static client::ConnectionSettings connectionSettings(const ClusterSettings& settings) { - client::ConnectionSettings cs; - cs.username = settings.username; - cs.password = settings.password; - cs.mechanism = settings.mechanism; - return cs; -} - -void Cluster::retractOffer(const MemberId& updater, uint64_t updateeInt, Lock& l) { - // An offer was received while handling an error, and converted to a retract. - // Behavior is very similar to updateOffer. - if (state == LEFT) return; - MemberId updatee(updateeInt); - boost::optional<Url> url = map.updateOffer(updater, updatee); - if (updater == self) { - assert(state == OFFER); - if (url) { // My offer was first. - if (updateThread) - updateThread.join(); // Join the previous updateThread to avoid leaks. - updateThread = Thread(new RetractClient(*url, connectionSettings(settings))); - } - setReady(l); - makeOffer(map.firstJoiner(), l); // Maybe make another offer. - // Don't unstall the event queue, that was already done in deliveredFrame - } - QPID_LOG(debug,*this << " retracted offer " << updater << " to " << updatee); -} - -void Cluster::updateStart(const MemberId& updatee, const Url& url, Lock& l) { - // NOTE: deliverEventQueue is already stopped at the stall point by deliveredEvent. - if (state == LEFT) return; - assert(state == OFFER); - state = UPDATER; - QPID_LOG(notice, *this << " sending update to " << updatee << " at " << url); - if (updateThread) - updateThread.join(); // Join the previous updateThread to avoid leaks. - updateThread = Thread( - new UpdateClient(self, updatee, url, broker, map, *expiryPolicy, - getConnections(l), decoder, - boost::bind(&Cluster::updateOutDone, this), - boost::bind(&Cluster::updateOutError, this, _1), - connectionSettings(settings))); -} - -// Called in network thread -void Cluster::updateInClosed() { - Lock l(lock); - assert(!updateClosed); - updateClosed = true; - checkUpdateIn(l); -} - -// Called in update thread. -void Cluster::updateInDone(const ClusterMap& m) { - Lock l(lock); - updatedMap = m; - checkUpdateIn(l); -} - -void Cluster::updateInRetracted() { - Lock l(lock); - updateRetracted = true; - map.clearStatus(); - checkUpdateIn(l); -} - -bool Cluster::isExpectingUpdate() { - Lock l(lock); - return state <= UPDATEE; -} - -// Called in update thread or deliver thread. -void Cluster::checkUpdateIn(Lock& l) { - if (state != UPDATEE) return; // Wait till we reach the stall point. - if (!updateClosed) return; // Wait till update connection closes. - if (updatedMap) { // We're up to date - map = *updatedMap; - failoverExchange->setUrls(getUrls(l)); - mcast.mcastControl(ClusterReadyBody(ProtocolVersion(), myUrl.str()), self); - state = CATCHUP; - memberUpdate(l); - // NB: don't updateMgmtMembership() here as we are not in the deliver - // thread. It will be updated on delivery of the "ready" we just mcast. - broker.setClusterUpdatee(false); - discarding = false; // OK to set, we're stalled for update. - QPID_LOG(notice, *this << " update complete, starting catch-up."); - QPID_LOG(debug, debugSnapshot()); // OK to call because we're stalled. - if (mAgent) { - // Update management agent now, after all update activity is complete. - updateDataExchange->updateManagementAgent(mAgent); - mAgent->suppress(false); // Enable management output. - mAgent->clusterUpdate(); - } - // Restore alternate exchange settings on exchanges. - broker.getExchanges().eachExchange( - boost::bind(&broker::Exchange::recoveryComplete, _1, - boost::ref(broker.getExchanges()))); - enableClusterSafe(); // Enable cluster-safe assertions - deliverEventQueue.start(); - } - else if (updateRetracted) { // Update was retracted, request another update - updateRetracted = false; - updateClosed = false; - state = JOINER; - QPID_LOG(notice, *this << " update retracted, sending new update request."); - mcast.mcastControl(ClusterUpdateRequestBody(ProtocolVersion(), myUrl.str()), self); - deliverEventQueue.start(); - } -} - -void Cluster::updateOutDone() { - Monitor::ScopedLock l(lock); - updateOutDone(l); -} - -void Cluster::updateOutDone(Lock& l) { - QPID_LOG(notice, *this << " update sent"); - assert(state == UPDATER); - state = READY; - deliverEventQueue.start(); // Start processing events again. - makeOffer(map.firstJoiner(), l); // Try another offer -} - -void Cluster::updateOutError(const std::exception& e) { - Monitor::ScopedLock l(lock); - QPID_LOG(error, *this << " error sending update: " << e.what()); - updateOutDone(l); -} - -void Cluster ::shutdown(const MemberId& , const Uuid& id, Lock& l) { - QPID_LOG(notice, *this << " cluster shut down by administrator."); - if (store.hasStore()) store.clean(id); - leave(l); -} - -ManagementObject* Cluster::GetManagementObject() const { return mgmtObject; } - -Manageable::status_t Cluster::ManagementMethod (uint32_t methodId, Args& args, string&) { - Lock l(lock); - QPID_LOG(debug, *this << " managementMethod [id=" << methodId << "]"); - switch (methodId) { - case _qmf::Cluster::METHOD_STOPCLUSTERNODE : - { - _qmf::ArgsClusterStopClusterNode& iargs = (_qmf::ArgsClusterStopClusterNode&) args; - stringstream stream; - stream << self; - if (iargs.i_brokerId == stream.str()) - stopClusterNode(l); - } - break; - case _qmf::Cluster::METHOD_STOPFULLCLUSTER : - stopFullCluster(l); - break; - default: - return Manageable::STATUS_UNKNOWN_METHOD; - } - return Manageable::STATUS_OK; -} - -void Cluster::stopClusterNode(Lock& l) { - QPID_LOG(notice, *this << " cluster member stopped by administrator."); - leave(l); -} - -void Cluster::stopFullCluster(Lock& ) { - QPID_LOG(notice, *this << " shutting down cluster " << name); - mcast.mcastControl(ClusterShutdownBody(ProtocolVersion(), Uuid(true)), self); -} - -void Cluster::memberUpdate(Lock& l) { - // Ignore config changes while we are joining. - if (state < CATCHUP) return; - QPID_LOG(info, *this << " member update: " << map); - size_t aliveCount = map.aliveCount(); - assert(map.isAlive(self)); - failoverExchange->updateUrls(getUrls(l)); - - // Mark store clean if I am the only broker, dirty otherwise. - if (store.hasStore()) { - if (aliveCount == 1) { - if (store.getState() != STORE_STATE_CLEAN_STORE) { - QPID_LOG(notice, *this << "Sole member of cluster, marking store clean."); - store.clean(Uuid(true)); - } - } - else { - if (store.getState() != STORE_STATE_DIRTY_STORE) { - QPID_LOG(notice, "Running in a cluster, marking store dirty."); - store.dirty(); - } - } - } - - // If I am the last member standing, set queue policies. - if (aliveCount == 1 && lastAliveCount > 1 && state >= CATCHUP) { - QPID_LOG(notice, *this << " last broker standing, update queue policies"); - lastBroker = true; - broker.getQueues().updateQueueClusterState(true); - } - else if (aliveCount > 1 && lastBroker) { - QPID_LOG(notice, *this << " last broker standing joined by " << aliveCount-1 - << " replicas, updating queue policies."); - lastBroker = false; - broker.getQueues().updateQueueClusterState(false); - } - lastAliveCount = aliveCount; - - // Close connections belonging to members that have left the cluster. - ConnectionMap::iterator i = connections.begin(); - while (i != connections.end()) { - ConnectionMap::iterator j = i++; - MemberId m = j->second->getId().getMember(); - if (m != self && !map.isMember(m)) { - j->second->close(); - erase(j->second->getId(), l); - } - } -} - -// See comment on Cluster::setMgmtStatus -void Cluster::updateMgmtMembership(Lock& l) { - if (!mgmtObject) return; - std::vector<Url> urls = getUrls(l); - mgmtObject->set_clusterSize(urls.size()); - string urlstr; - for(std::vector<Url>::iterator i = urls.begin(); i != urls.end(); i++ ) { - if (i != urls.begin()) urlstr += ";"; - urlstr += i->str(); - } - std::vector<string> ids = getIds(l); - string idstr; - for(std::vector<string>::iterator i = ids.begin(); i != ids.end(); i++ ) { - if (i != ids.begin()) idstr += ";"; - idstr += *i; - } - mgmtObject->set_members(urlstr); - mgmtObject->set_memberIDs(idstr); -} - -std::ostream& operator<<(std::ostream& o, const Cluster& cluster) { - static const char* STATE[] = { - "PRE_INIT", "INIT", "JOINER", "UPDATEE", "CATCHUP", - "READY", "OFFER", "UPDATER", "LEFT" - }; - assert(sizeof(STATE)/sizeof(*STATE) == Cluster::LEFT+1); - o << "cluster(" << cluster.self << " " << STATE[cluster.state]; - if (cluster.error.isUnresolved()) o << "/error"; - return o << ")"; -} - -MemberId Cluster::getId() const { - return self; // Immutable, no need to lock. -} - -broker::Broker& Cluster::getBroker() const { - return broker; // Immutable, no need to lock. -} - -void Cluster::setClusterId(const Uuid& uuid, Lock&) { - clusterId = uuid; - if (store.hasStore()) store.setClusterId(uuid); - if (mgmtObject) { - stringstream stream; - stream << self; - mgmtObject->set_clusterID(clusterId.str()); - mgmtObject->set_memberID(stream.str()); - } - QPID_LOG(notice, *this << " cluster-uuid = " << clusterId); -} - -void Cluster::messageExpired(const MemberId&, uint64_t id, Lock&) { - expiryPolicy->deliverExpire(id); -} - -void Cluster::errorCheck(const MemberId& from, uint8_t type, framing::SequenceNumber frameSeq, Lock&) { - // If we see an errorCheck here (rather than in the ErrorCheck - // class) then we have processed succesfully past the point of the - // error. - if (state >= CATCHUP) // Don't respond pre catchup, we don't know what happened - error.respondNone(from, type, frameSeq); -} - -void Cluster::timerWakeup(const MemberId& , const std::string& name, Lock&) { - if (state >= CATCHUP) // Pre catchup our timer isn't set up. - timer->deliverWakeup(name); -} - -void Cluster::timerDrop(const MemberId& , const std::string& name, Lock&) { - QPID_LOG(debug, "Cluster timer drop " << map.getFrameSeq() << ": " << name) - if (state >= CATCHUP) // Pre catchup our timer isn't set up. - timer->deliverDrop(name); -} - -bool Cluster::isElder() const { - return elder; -} - -void Cluster::deliverToQueue(const std::string& queue, const std::string& message, Lock& l) -{ - broker::Queue::shared_ptr q = broker.getQueues().find(queue); - if (!q) { - QPID_LOG(critical, *this << " cluster delivery to non-existent queue: " << queue); - leave(l); - } - framing::Buffer buf(const_cast<char*>(message.data()), message.size()); - boost::intrusive_ptr<broker::Message> msg(new broker::Message); - msg->decodeHeader(buf); - msg->decodeContent(buf); - q->deliver(msg); -} - -bool Cluster::deferDeliveryImpl(const std::string& queue, - const boost::intrusive_ptr<broker::Message>& msg) -{ - if (isClusterSafe()) return false; - std::string message; - message.resize(msg->encodedSize()); - framing::Buffer buf(const_cast<char*>(message.data()), message.size()); - msg->encode(buf); - mcast.mcastControl(ClusterDeliverToQueueBody(ProtocolVersion(), queue, message), self); - return true; -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/Cluster.h b/cpp/src/qpid/cluster/Cluster.h deleted file mode 100644 index 78d325cdf9..0000000000 --- a/cpp/src/qpid/cluster/Cluster.h +++ /dev/null @@ -1,308 +0,0 @@ -#ifndef QPID_CLUSTER_CLUSTER_H -#define QPID_CLUSTER_CLUSTER_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "ClusterMap.h" -#include "ClusterSettings.h" -#include "Cpg.h" -#include "Decoder.h" -#include "ErrorCheck.h" -#include "Event.h" -#include "EventFrame.h" -#include "ExpiryPolicy.h" -#include "FailoverExchange.h" -#include "InitialStatusMap.h" -#include "LockedConnectionMap.h" -#include "Multicaster.h" -#include "NoOpConnectionOutputHandler.h" -#include "PollableQueue.h" -#include "PollerDispatch.h" -#include "Quorum.h" -#include "StoreStatus.h" -#include "UpdateReceiver.h" - -#include "qmf/org/apache/qpid/cluster/Cluster.h" -#include "qpid/Url.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/Manageable.h" -#include "qpid/sys/Monitor.h" - -#include <boost/bind.hpp> -#include <boost/intrusive_ptr.hpp> -#include <boost/optional.hpp> - -#include <algorithm> -#include <map> -#include <vector> - -namespace qpid { - -namespace broker { -class Message; -} - -namespace framing { -class AMQBody; -struct Uuid; -} - -namespace cluster { - -class Connection; -struct EventFrame; -class ClusterTimer; -class UpdateDataExchange; - -/** - * Connection to the cluster - */ -class Cluster : private Cpg::Handler, public management::Manageable { - public: - typedef boost::intrusive_ptr<Connection> ConnectionPtr; - typedef std::vector<ConnectionPtr> ConnectionVector; - - // Public functions are thread safe unless otherwise mentioned in a comment. - - // Construct the cluster in plugin earlyInitialize. - Cluster(const ClusterSettings&, broker::Broker&); - virtual ~Cluster(); - - // Called by plugin initialize: cluster start-up requires transport plugins . - // Thread safety: only called by plugin initialize. - void initialize(); - - // Connection map. - void addLocalConnection(const ConnectionPtr&); - void addShadowConnection(const ConnectionPtr&); - void erase(const ConnectionId&); - - // URLs of current cluster members. - std::vector<std::string> getIds() const; - std::vector<Url> getUrls() const; - boost::shared_ptr<FailoverExchange> getFailoverExchange() const { return failoverExchange; } - - // Leave the cluster - called when fatal errors occur. - void leave(); - - // Update completed - called in update thread - void updateInClosed(); - void updateInDone(const ClusterMap&); - void updateInRetracted(); - // True if we are expecting to receive catch-up connections. - bool isExpectingUpdate(); - - MemberId getId() const; - broker::Broker& getBroker() const; - Multicaster& getMulticast() { return mcast; } - - const ClusterSettings& getSettings() const { return settings; } - - void deliverFrame(const EventFrame&); - - // Called in deliverFrame thread to indicate an error from the broker. - void flagError(Connection&, ErrorCheck::ErrorType, const std::string& msg); - - // Called only during update by Connection::shadowReady - Decoder& getDecoder() { return decoder; } - - ExpiryPolicy& getExpiryPolicy() { return *expiryPolicy; } - - UpdateReceiver& getUpdateReceiver() { return updateReceiver; } - - bool isElder() const; - - // Generates a log message for debugging purposes. - std::string debugSnapshot(); - - // Defer messages delivered in an unsafe context by multicasting. - bool deferDeliveryImpl(const std::string& queue, - const boost::intrusive_ptr<broker::Message>& msg); - - private: - typedef sys::Monitor::ScopedLock Lock; - - typedef PollableQueue<Event> PollableEventQueue; - typedef PollableQueue<EventFrame> PollableFrameQueue; - typedef std::map<ConnectionId, ConnectionPtr> ConnectionMap; - - /** Version number of the cluster protocol, to avoid mixed versions. */ - static const uint32_t CLUSTER_VERSION; - - // NB: A dummy Lock& parameter marks functions that must only be - // called with Cluster::lock locked. - - void leave(Lock&); - std::vector<std::string> getIds(Lock&) const; - std::vector<Url> getUrls(Lock&) const; - - // == Called in main thread from Broker destructor. - void brokerShutdown(); - - // == Called in deliverEventQueue thread - void deliveredEvent(const Event&); - - // == Called in deliverFrameQueue thread - void deliveredFrame(const EventFrame&); - void processFrame(const EventFrame&, Lock&); - - // Cluster controls implement XML methods from cluster.xml. - void updateRequest(const MemberId&, const std::string&, Lock&); - void updateOffer(const MemberId& updater, uint64_t updatee, Lock&); - void retractOffer(const MemberId& updater, uint64_t updatee, Lock&); - void initialStatus(const MemberId&, - uint32_t version, - bool active, - const framing::Uuid& clusterId, - framing::cluster::StoreState, - const framing::Uuid& shutdownId, - const std::string& firstConfig, - Lock&); - void ready(const MemberId&, const std::string&, Lock&); - void configChange(const MemberId&, - const std::string& members, - const std::string& left, - const std::string& joined, - Lock& l); - void messageExpired(const MemberId&, uint64_t, Lock& l); - void errorCheck(const MemberId&, uint8_t type, SequenceNumber frameSeq, Lock&); - void timerWakeup(const MemberId&, const std::string& name, Lock&); - void timerDrop(const MemberId&, const std::string& name, Lock&); - void shutdown(const MemberId&, const framing::Uuid& shutdownId, Lock&); - void deliverToQueue(const std::string& queue, const std::string& message, Lock&); - - // Helper functions - ConnectionPtr getConnection(const EventFrame&, Lock&); - ConnectionVector getConnections(Lock&); - void updateStart(const MemberId& updatee, const Url& url, Lock&); - void makeOffer(const MemberId&, Lock&); - void setReady(Lock&); - void memberUpdate(Lock&); - void setClusterId(const framing::Uuid&, Lock&); - void erase(const ConnectionId&, Lock&); - void requestUpdate(Lock& ); - void initMapCompleted(Lock&); - void becomeElder(Lock&); - void setMgmtStatus(Lock&); - void updateMgmtMembership(Lock&); - - // == Called in CPG dispatch thread - void deliver( // CPG deliver callback. - cpg_handle_t /*handle*/, - const struct cpg_name *group, - uint32_t /*nodeid*/, - uint32_t /*pid*/, - void* /*msg*/, - int /*msg_len*/); - - void deliverEvent(const Event&); - - void configChange( // CPG config change callback. - cpg_handle_t /*handle*/, - const struct cpg_name */*group*/, - const struct cpg_address */*members*/, int /*nMembers*/, - const struct cpg_address */*left*/, int /*nLeft*/, - const struct cpg_address */*joined*/, int /*nJoined*/ - ); - - // == Called in management threads. - virtual qpid::management::ManagementObject* GetManagementObject() const; - virtual management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args, std::string& text); - - void stopClusterNode(Lock&); - void stopFullCluster(Lock&); - - // == Called in connection IO threads . - void checkUpdateIn(Lock&); - - // == Called in UpdateClient thread. - void updateOutDone(); - void updateOutError(const std::exception&); - void updateOutDone(Lock&); - - // Immutable members set on construction, never changed. - const ClusterSettings settings; - broker::Broker& broker; - qmf::org::apache::qpid::cluster::Cluster* mgmtObject; // mgnt owns lifecycle - boost::shared_ptr<sys::Poller> poller; - Cpg cpg; - const std::string name; - Url myUrl; - const MemberId self; - framing::Uuid clusterId; - NoOpConnectionOutputHandler shadowOut; - qpid::management::ManagementAgent* mAgent; - boost::intrusive_ptr<ExpiryPolicy> expiryPolicy; - - // Thread safe members - Multicaster mcast; - PollerDispatch dispatcher; - PollableEventQueue deliverEventQueue; - PollableFrameQueue deliverFrameQueue; - boost::shared_ptr<FailoverExchange> failoverExchange; - boost::shared_ptr<UpdateDataExchange> updateDataExchange; - Quorum quorum; - LockedConnectionMap localConnections; - - // Used only in deliverEventQueue thread or when stalled for update. - Decoder decoder; - bool discarding; - - - // Remaining members are protected by lock. - mutable sys::Monitor lock; - - - // Local cluster state, cluster map - enum { - PRE_INIT,///< Have not yet received complete initial status map. - INIT, ///< Waiting to reach cluster-size. - JOINER, ///< Sent update request, waiting for update offer. - UPDATEE, ///< Stalled receive queue at update offer, waiting for update to complete. - CATCHUP, ///< Update complete, unstalled but has not yet seen own "ready" event. - READY, ///< Fully operational - OFFER, ///< Sent an offer, waiting for accept/reject. - UPDATER, ///< Offer accepted, sending a state update. - LEFT ///< Final state, left the cluster. - } state; - - ConnectionMap connections; - InitialStatusMap initMap; - StoreStatus store; - ClusterMap map; - MemberSet elders; - bool elder; - size_t lastAliveCount; - bool lastBroker; - sys::Thread updateThread; - boost::optional<ClusterMap> updatedMap; - bool updateRetracted, updateClosed; - ErrorCheck error; - UpdateReceiver updateReceiver; - ClusterTimer* timer; - - friend std::ostream& operator<<(std::ostream&, const Cluster&); - friend struct ClusterDispatcher; -}; - -}} // namespace qpid::cluster - - - -#endif /*!QPID_CLUSTER_CLUSTER_H*/ diff --git a/cpp/src/qpid/cluster/ClusterMap.cpp b/cpp/src/qpid/cluster/ClusterMap.cpp deleted file mode 100644 index a8389095c9..0000000000 --- a/cpp/src/qpid/cluster/ClusterMap.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/ClusterMap.h" -#include "qpid/Url.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/log/Statement.h" -#include <boost/bind.hpp> -#include <algorithm> -#include <functional> -#include <iterator> -#include <ostream> - -using namespace std; -using namespace boost; - -namespace qpid { -using namespace framing; - -namespace cluster { - -namespace { - -void addFieldTableValue(FieldTable::ValueMap::value_type vt, ClusterMap::Map& map, ClusterMap::Set& set) { - MemberId id(vt.first); - set.insert(id); - string url = vt.second->get<string>(); - if (!url.empty()) - map.insert(ClusterMap::Map::value_type(id, Url(url))); -} - -void insertFieldTableFromMapValue(FieldTable& ft, const ClusterMap::Map::value_type& vt) { - ft.setString(vt.first.str(), vt.second.str()); -} - -} - -ClusterMap::ClusterMap() : frameSeq(0) {} - -ClusterMap::ClusterMap(const Map& map) : frameSeq(0) { - transform(map.begin(), map.end(), inserter(alive, alive.begin()), bind(&Map::value_type::first, _1)); - members = map; -} - -ClusterMap::ClusterMap(const FieldTable& joinersFt, const FieldTable& membersFt, - framing::SequenceNumber frameSeq_) - : frameSeq(frameSeq_) -{ - for_each(joinersFt.begin(), joinersFt.end(), bind(&addFieldTableValue, _1, ref(joiners), ref(alive))); - for_each(membersFt.begin(), membersFt.end(), bind(&addFieldTableValue, _1, ref(members), ref(alive))); -} - -void ClusterMap::toMethodBody(framing::ClusterConnectionMembershipBody& b) const { - b.getJoiners().clear(); - for_each(joiners.begin(), joiners.end(), bind(&insertFieldTableFromMapValue, ref(b.getJoiners()), _1)); - for(Set::const_iterator i = alive.begin(); i != alive.end(); ++i) { - if (!isMember(*i) && !isJoiner(*i)) - b.getJoiners().setString(i->str(), string()); - } - b.getMembers().clear(); - for_each(members.begin(), members.end(), bind(&insertFieldTableFromMapValue, ref(b.getMembers()), _1)); - b.setFrameSeq(frameSeq); -} - -Url ClusterMap::getUrl(const Map& map, const MemberId& id) { - Map::const_iterator i = map.find(id); - return i == map.end() ? Url() : i->second; -} - -MemberId ClusterMap::firstJoiner() const { - return joiners.empty() ? MemberId() : joiners.begin()->first; -} - -vector<string> ClusterMap::memberIds() const { - vector<string> ids; - for (Map::const_iterator iter = members.begin(); - iter != members.end(); iter++) { - stringstream stream; - stream << iter->first; - ids.push_back(stream.str()); - } - return ids; -} - -vector<Url> ClusterMap::memberUrls() const { - vector<Url> urls(members.size()); - transform(members.begin(), members.end(), urls.begin(), - bind(&Map::value_type::second, _1)); - return urls; -} - -ClusterMap::Set ClusterMap::getAlive() const { return alive; } - -ClusterMap::Set ClusterMap::getMembers() const { - Set s; - transform(members.begin(), members.end(), inserter(s, s.begin()), - bind(&Map::value_type::first, _1)); - return s; -} - -ostream& operator<<(ostream& o, const ClusterMap::Map& m) { - ostream_iterator<MemberId> oi(o); - transform(m.begin(), m.end(), oi, bind(&ClusterMap::Map::value_type::first, _1)); - return o; -} - -ostream& operator<<(ostream& o, const ClusterMap& m) { - for (ClusterMap::Set::const_iterator i = m.alive.begin(); i != m.alive.end(); ++i) { - o << *i; - if (m.isMember(*i)) o << "(member)"; - else if (m.isJoiner(*i)) o << "(joiner)"; - else o << "(unknown)"; - o << " "; - } - o << "frameSeq=" << m.getFrameSeq(); - return o; -} - -bool ClusterMap::updateRequest(const MemberId& id, const string& url) { - try { - if (isAlive(id)) { - joiners[id] = Url(url); - return true; - } - } catch (const Url::Invalid&) { - QPID_LOG(error, "Invalid URL in cluster update request: " << url); - } - return false; -} - -bool ClusterMap::ready(const MemberId& id, const Url& url) { - return isAlive(id) && members.insert(Map::value_type(id,url)).second; -} - -bool ClusterMap::configChange(const Set& update) { - bool memberChange = false; - Set removed; - set_difference(alive.begin(), alive.end(), - update.begin(), update.end(), - inserter(removed, removed.begin())); - alive = update; - for (Set::const_iterator i = removed.begin(); i != removed.end(); ++i) { - memberChange = memberChange || members.erase(*i); - joiners.erase(*i); - } - return memberChange; -} - -optional<Url> ClusterMap::updateOffer(const MemberId& from, const MemberId& to) { - Map::iterator i = joiners.find(to); - if (isAlive(from) && i != joiners.end()) { - Url url= i->second; - joiners.erase(i); // No longer a potential updatee. - return url; - } - return optional<Url>(); -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/ClusterMap.h b/cpp/src/qpid/cluster/ClusterMap.h deleted file mode 100644 index cfa4ad924a..0000000000 --- a/cpp/src/qpid/cluster/ClusterMap.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef QPID_CLUSTER_CLUSTERMAP_H -#define QPID_CLUSTER_CLUSTERMAP_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "MemberSet.h" -#include "qpid/Url.h" -#include "qpid/framing/ClusterConnectionMembershipBody.h" -#include "qpid/framing/SequenceNumber.h" - -#include <boost/function.hpp> -#include <boost/optional.hpp> - -#include <vector> -#include <deque> -#include <map> -#include <iosfwd> - -namespace qpid { -namespace cluster { - -/** - * Map of established cluster members and joiners waiting for an update, - * along with other cluster state that must be updated. - */ -class ClusterMap { - public: - typedef std::map<MemberId, Url> Map; - typedef std::set<MemberId> Set; - - ClusterMap(); - ClusterMap(const Map& map); - ClusterMap(const framing::FieldTable& joiners, const framing::FieldTable& members, - framing::SequenceNumber frameSeq); - - /** Update from config change. - *@return true if member set changed. - */ - bool configChange(const Set& members); - - bool isJoiner(const MemberId& id) const { return joiners.find(id) != joiners.end(); } - bool isMember(const MemberId& id) const { return members.find(id) != members.end(); } - bool isAlive(const MemberId& id) const { return alive.find(id) != alive.end(); } - - Url getJoinerUrl(const MemberId& id) { return getUrl(joiners, id); } - Url getMemberUrl(const MemberId& id) { return getUrl(members, id); } - - /** First joiner in the cluster in ID order, target for offers */ - MemberId firstJoiner() const; - - /** Convert map contents to a cluster control body. */ - void toMethodBody(framing::ClusterConnectionMembershipBody&) const; - - size_t aliveCount() const { return alive.size(); } - size_t memberCount() const { return members.size(); } - std::vector<std::string> memberIds() const; - std::vector<Url> memberUrls() const; - Set getAlive() const; - Set getMembers() const; - - bool updateRequest(const MemberId& id, const std::string& url); - /** Return non-empty Url if accepted */ - boost::optional<Url> updateOffer(const MemberId& from, const MemberId& to); - - /**@return true If this is a new member */ - bool ready(const MemberId& id, const Url&); - - framing::SequenceNumber getFrameSeq() const { return frameSeq; } - framing::SequenceNumber incrementFrameSeq() { return ++frameSeq; } - - /** Clear out all knowledge of joiners & members, just keep alive set */ - void clearStatus() { joiners.clear(); members.clear(); } - - private: - Url getUrl(const Map& map, const MemberId& id); - - Map joiners, members; - Set alive; - framing::SequenceNumber frameSeq; - - friend std::ostream& operator<<(std::ostream&, const Map&); - friend std::ostream& operator<<(std::ostream&, const ClusterMap&); -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_CLUSTERMAP_H*/ diff --git a/cpp/src/qpid/cluster/ClusterPlugin.cpp b/cpp/src/qpid/cluster/ClusterPlugin.cpp deleted file mode 100644 index 2962daaa07..0000000000 --- a/cpp/src/qpid/cluster/ClusterPlugin.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "config.h" -#include "qpid/cluster/Connection.h" -#include "qpid/cluster/ConnectionCodec.h" -#include "qpid/cluster/ClusterSettings.h" - -#include "qpid/cluster/SecureConnectionFactory.h" - -#include "qpid/cluster/Cluster.h" -#include "qpid/cluster/ConnectionCodec.h" -#include "qpid/cluster/UpdateClient.h" - -#include "qpid/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/log/Statement.h" - -#include "qpid/management/ManagementAgent.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/SessionState.h" -#include "qpid/client/ConnectionSettings.h" - -#include <boost/shared_ptr.hpp> -#include <boost/utility/in_place_factory.hpp> -#include <boost/scoped_ptr.hpp> - -namespace qpid { -namespace cluster { - -using namespace std; -using broker::Broker; -using management::ManagementAgent; - - -/** Note separating options from settings to work around boost version differences. - * Old boost takes a reference to options objects, but new boost makes a copy. - * New boost allows a shared_ptr but that's not compatible with old boost. - */ -struct ClusterOptions : public Options { - ClusterSettings& settings; - - ClusterOptions(ClusterSettings& v) : Options("Cluster Options"), settings(v) { - addOptions() - ("cluster-name", optValue(settings.name, "NAME"), "Name of cluster to join") - ("cluster-url", optValue(settings.url,"URL"), - "Set URL of this individual broker, to be advertized to clients.\n" - "Defaults to a URL listing all the local IP addresses\n") - ("cluster-username", optValue(settings.username, ""), "Username for connections between brokers") - ("cluster-password", optValue(settings.password, ""), "Password for connections between brokers") - ("cluster-mechanism", optValue(settings.mechanism, ""), "Authentication mechanism for connections between brokers") -#if HAVE_LIBCMAN_H - ("cluster-cman", optValue(settings.quorum), "Integrate with Cluster Manager (CMAN) cluster.") -#endif - ("cluster-size", optValue(settings.size, "N"), "Wait for N cluster members before allowing clients to connect.") - ("cluster-read-max", optValue(settings.readMax,"N"), "Experimental: flow-control limit reads per connection. 0=no limit.") - ; - } -}; - -typedef boost::shared_ptr<sys::ConnectionCodec::Factory> CodecFactoryPtr; - -struct ClusterPlugin : public Plugin { - - ClusterSettings settings; - ClusterOptions options; - Cluster* cluster; - boost::scoped_ptr<ConnectionCodec::Factory> factory; - - ClusterPlugin() : options(settings), cluster(0) {} - - // Cluster needs to be initialized after the store - int initOrder() const { return Plugin::DEFAULT_INIT_ORDER+500; } - - Options* getOptions() { return &options; } - - void earlyInitialize(Plugin::Target& target) { - if (settings.name.empty()) return; // Only if --cluster-name option was specified. - Broker* broker = dynamic_cast<Broker*>(&target); - if (!broker) return; - cluster = new Cluster(settings, *broker); - CodecFactoryPtr simpleFactory(new broker::ConnectionFactory(*broker)); - CodecFactoryPtr clusterFactory(new ConnectionCodec::Factory(simpleFactory, *cluster)); - CodecFactoryPtr secureFactory(new SecureConnectionFactory(clusterFactory)); - broker->setConnectionFactory(secureFactory); - } - - void disallowManagementMethods(ManagementAgent* agent) { - if (!agent) return; - agent->disallowV1Methods(); - } - - void initialize(Plugin::Target& target) { - Broker* broker = dynamic_cast<Broker*>(&target); - if (broker && cluster) { - disallowManagementMethods(broker->getManagementAgent()); - cluster->initialize(); - } - } -}; - -static ClusterPlugin instance; // Static initialization. - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/ClusterSettings.h b/cpp/src/qpid/cluster/ClusterSettings.h deleted file mode 100644 index 8e708aa139..0000000000 --- a/cpp/src/qpid/cluster/ClusterSettings.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_CLUSTER_CLUSTERSETTINGS_H -#define QPID_CLUSTER_CLUSTERSETTINGS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/Url.h> -#include <string> - -namespace qpid { -namespace cluster { - -struct ClusterSettings { - std::string name; - std::string url; - bool quorum; - size_t readMax; - std::string username, password, mechanism; - size_t size; - - ClusterSettings() : quorum(false), readMax(10), size(1) - {} - - Url getUrl(uint16_t port) const { - if (url.empty()) return Url::getIpAddressesUrl(port); - return Url(url); - } -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_CLUSTERSETTINGS_H*/ diff --git a/cpp/src/qpid/cluster/ClusterTimer.cpp b/cpp/src/qpid/cluster/ClusterTimer.cpp deleted file mode 100644 index f6e1c7a849..0000000000 --- a/cpp/src/qpid/cluster/ClusterTimer.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License "); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "Cluster.h" -#include "ClusterTimer.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/ClusterTimerWakeupBody.h" -#include "qpid/framing/ClusterTimerDropBody.h" - -namespace qpid { -namespace cluster { - -using boost::intrusive_ptr; -using std::max; -using sys::Timer; -using sys::TimerTask; - -// -// Note on use of Broker::getTimer() rather than getClusterTime in broker code. -// The following uses of getTimer() are cluster safe: -// -// LinkRegistry: maintenance visits in timer can call Bridge::create/cancel -// but these don't modify any management state. -// -// broker::Connection: -// - Heartbeats use ClusterOrderOutput to ensure consistency -// - timeout: aborts connection in timer, cluster does an orderly connection close. -// -// SessionState: scheduledCredit - uses ClusterOrderProxy -// Broker::queueCleaner: cluster implements ExpiryPolicy for consistent expiry. -// -// Broker::dtxManager: dtx disabled with cluster. -// -// requestIOProcessing: called in doOutput. -// - - -ClusterTimer::ClusterTimer(Cluster& c) : cluster(c) { - // Allow more generous overrun threshold with cluster as we - // have to do a CPG round trip before executing the task. - overran = 10*sys::TIME_MSEC; - late = 100*sys::TIME_MSEC; -} - -ClusterTimer::~ClusterTimer() {} - -// Initialization or deliver thread. -void ClusterTimer::add(intrusive_ptr<TimerTask> task) -{ - QPID_LOG(trace, "Adding cluster timer task " << task->getName()); - Map::iterator i = map.find(task->getName()); - if (i != map.end()) - throw Exception(QPID_MSG("Task already exists with name " << task->getName())); - map[task->getName()] = task; - // Only the elder actually activates the task with the Timer base class. - if (cluster.isElder()) { - QPID_LOG(trace, "Elder activating cluster timer task " << task->getName()); - Timer::add(task); - } -} - -// Timer thread -void ClusterTimer::fire(intrusive_ptr<TimerTask> t) { - // Elder mcasts wakeup on fire, task is not fired until deliverWakeup - if (cluster.isElder()) { - QPID_LOG(trace, "Sending cluster timer wakeup " << t->getName()); - cluster.getMulticast().mcastControl( - framing::ClusterTimerWakeupBody(framing::ProtocolVersion(), t->getName()), - cluster.getId()); - } - else - QPID_LOG(trace, "Cluster timer task fired, but not elder " << t->getName()); -} - -// Timer thread -void ClusterTimer::drop(intrusive_ptr<TimerTask> t) { - // Elder mcasts drop, task is droped in deliverDrop - if (cluster.isElder()) { - QPID_LOG(trace, "Sending cluster timer drop " << t->getName()); - cluster.getMulticast().mcastControl( - framing::ClusterTimerDropBody(framing::ProtocolVersion(), t->getName()), - cluster.getId()); - } - else - QPID_LOG(trace, "Cluster timer task dropped, but not on elder " << t->getName()); -} - -// Deliver thread -void ClusterTimer::deliverWakeup(const std::string& name) { - QPID_LOG(trace, "Cluster timer wakeup delivered for " << name); - Map::iterator i = map.find(name); - if (i == map.end()) - throw Exception(QPID_MSG("Cluster timer wakeup non-existent task " << name)); - else { - intrusive_ptr<TimerTask> t = i->second; - map.erase(i); - Timer::fire(t); - } -} - -// Deliver thread -void ClusterTimer::deliverDrop(const std::string& name) { - QPID_LOG(trace, "Cluster timer drop delivered for " << name); - Map::iterator i = map.find(name); - if (i == map.end()) - throw Exception(QPID_MSG("Cluster timer drop non-existent task " << name)); - else { - intrusive_ptr<TimerTask> t = i->second; - map.erase(i); - } -} - -// Deliver thread -void ClusterTimer::becomeElder() { - for (Map::iterator i = map.begin(); i != map.end(); ++i) { - Timer::add(i->second); - } -} - -}} diff --git a/cpp/src/qpid/cluster/ClusterTimer.h b/cpp/src/qpid/cluster/ClusterTimer.h deleted file mode 100644 index 69f6c622e4..0000000000 --- a/cpp/src/qpid/cluster/ClusterTimer.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_CLUSTER_CLUSTERTIMER_H -#define QPID_CLUSTER_CLUSTERTIMER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Timer.h" -#include <map> - -namespace qpid { -namespace cluster { - -class Cluster; - -/** - * Timer implementation that executes tasks consistently in the - * deliver thread across a cluster. Task is not executed when timer - * fires, instead the elder multicasts a wakeup. The task is executed - * when the wakeup is delivered. - */ -class ClusterTimer : public sys::Timer { - public: - ClusterTimer(Cluster&); - ~ClusterTimer(); - - void add(boost::intrusive_ptr<sys::TimerTask> task); - - void deliverWakeup(const std::string& name); - void deliverDrop(const std::string& name); - void becomeElder(); - - protected: - void fire(boost::intrusive_ptr<sys::TimerTask> task); - void drop(boost::intrusive_ptr<sys::TimerTask> task); - - private: - typedef std::map<std::string, boost::intrusive_ptr<sys::TimerTask> > Map; - Cluster& cluster; - Map map; -}; - - -}} - - -#endif /*!QPID_CLUSTER_CLUSTERTIMER_H*/ diff --git a/cpp/src/qpid/cluster/Connection.cpp b/cpp/src/qpid/cluster/Connection.cpp deleted file mode 100644 index b9895290e9..0000000000 --- a/cpp/src/qpid/cluster/Connection.cpp +++ /dev/null @@ -1,728 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/Codecs.h" -#include "Connection.h" -#include "UpdateClient.h" -#include "Cluster.h" -#include "UpdateReceiver.h" -#include "qpid/assert.h" -#include "qpid/broker/SessionState.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/broker/TxBuffer.h" -#include "qpid/broker/TxPublish.h" -#include "qpid/broker/TxAccept.h" -#include "qpid/broker/RecoveredEnqueue.h" -#include "qpid/broker/RecoveredDequeue.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Fairshare.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/StatefulQueueObserver.h" -#include "qpid/broker/Queue.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AllInvoker.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/ClusterConnectionDeliverCloseBody.h" -#include "qpid/framing/ClusterConnectionAnnounceBody.h" -#include "qpid/framing/ConnectionCloseBody.h" -#include "qpid/framing/ConnectionCloseOkBody.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/ClusterSafe.h" -#include "qpid/types/Variant.h" -#include "qpid/management/ManagementAgent.h" -#include <boost/current_function.hpp> - - -namespace qpid { -namespace cluster { - -using namespace framing; -using namespace framing::cluster; -using amqp_0_10::ListCodec; -using types::Variant; - -qpid::sys::AtomicValue<uint64_t> Connection::catchUpId(0x5000000000000000LL); - -Connection::NullFrameHandler Connection::nullFrameHandler; - -struct NullFrameHandler : public framing::FrameHandler { - void handle(framing::AMQFrame&) {} -}; - - -namespace { -sys::AtomicValue<uint64_t> idCounter; -const std::string shadowPrefix("[shadow]"); -} - - -// Shadow connection -Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out, - const std::string& mgmtId, - const ConnectionId& id, const qpid::sys::SecuritySettings& external) - : cluster(c), self(id), catchUp(false), announced(false), output(*this, out), - connectionCtor(&output, cluster.getBroker(), mgmtId, external, false, 0, true), - expectProtocolHeader(false), - mcastFrameHandler(cluster.getMulticast(), self), - updateIn(c.getUpdateReceiver()), - secureConnection(0) -{} - -// Local connection -Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out, - const std::string& mgmtId, MemberId member, - bool isCatchUp, bool isLink, const qpid::sys::SecuritySettings& external -) : cluster(c), self(member, ++idCounter), catchUp(isCatchUp), announced(false), output(*this, out), - connectionCtor(&output, cluster.getBroker(), - mgmtId, - external, - isLink, - isCatchUp ? ++catchUpId : 0, - isCatchUp), // isCatchUp => shadow - expectProtocolHeader(isLink), - mcastFrameHandler(cluster.getMulticast(), self), - updateIn(c.getUpdateReceiver()), - secureConnection(0) -{ - if (isLocalClient()) { - giveReadCredit(cluster.getSettings().readMax); // Flow control - // Delay adding the connection to the management map until announce() - connectionCtor.delayManagement = true; - } - else { - // Catch-up shadow connections initialized using nextShadow id. - assert(catchUp); - if (!updateIn.nextShadowMgmtId.empty()) - connectionCtor.mgmtId = updateIn.nextShadowMgmtId; - updateIn.nextShadowMgmtId.clear(); - } - init(); - QPID_LOG(debug, cluster << " local connection " << *this); -} - -void Connection::setSecureConnection(broker::SecureConnection* sc) { - secureConnection = sc; - if (connection.get()) connection->setSecureConnection(sc); -} - -void Connection::init() { - connection = connectionCtor.construct(); - if (isLocalClient()) { - if (secureConnection) connection->setSecureConnection(secureConnection); - // Actively send cluster-order frames from local node - connection->setClusterOrderOutput(mcastFrameHandler); - } - else { // Shadow or catch-up connection - // Passive, discard cluster-order frames - connection->setClusterOrderOutput(nullFrameHandler); - // Disable client throttling, done by active node. - connection->setClientThrottling(false); - } - if (!isCatchUp()) - connection->setErrorListener(this); -} - -// Called when we have consumed a read buffer to give credit to the -// connection layer to continue reading. -void Connection::giveReadCredit(int credit) { - if (cluster.getSettings().readMax && credit) - output.giveReadCredit(credit); -} - -void Connection::announce( - const std::string& mgmtId, uint32_t ssf, const std::string& authid, bool nodict, - const std::string& username, const std::string& initialFrames) -{ - QPID_ASSERT(mgmtId == connectionCtor.mgmtId); - QPID_ASSERT(ssf == connectionCtor.external.ssf); - QPID_ASSERT(authid == connectionCtor.external.authid); - QPID_ASSERT(nodict == connectionCtor.external.nodict); - // Local connections are already initialized but with management delayed. - if (isLocalClient()) { - connection->addManagementObject(); - } - else if (isShadow()) { - init(); - // Play initial frames into the connection. - Buffer buf(const_cast<char*>(initialFrames.data()), initialFrames.size()); - AMQFrame frame; - while (frame.decode(buf)) - connection->received(frame); - connection->setUserId(username); - } - // Do managment actions now that the connection is replicated. - connection->raiseConnectEvent(); - QPID_LOG(debug, cluster << " replicated connection " << *this); -} - -Connection::~Connection() { - if (connection.get()) connection->setErrorListener(0); - // Don't trigger cluster-safe asserts in broker:: ~Connection as - // it may be called in an IO thread context during broker - // shutdown. - sys::ClusterSafeScope css; - connection.reset(); -} - -bool Connection::doOutput() { - return output.doOutput(); -} - -// Received from a directly connected client. -void Connection::received(framing::AMQFrame& f) { - if (!connection.get()) { - QPID_LOG(warning, cluster << " ignoring frame on closed connection " - << *this << ": " << f); - return; - } - QPID_LOG(trace, cluster << " RECV " << *this << ": " << f); - if (isLocal()) { // Local catch-up connection. - currentChannel = f.getChannel(); - if (!framing::invoke(*this, *f.getBody()).wasHandled()) - connection->received(f); - } - else { // Shadow or updated catch-up connection. - if (f.getMethod() && f.getMethod()->isA<ConnectionCloseBody>()) { - if (isShadow()) - cluster.addShadowConnection(this); - AMQFrame ok((ConnectionCloseOkBody())); - connection->getOutput().send(ok); - output.closeOutput(); - catchUp = false; - } - else - QPID_LOG(warning, cluster << " ignoring unexpected frame " << *this << ": " << f); - } -} - -bool Connection::checkUnsupported(const AMQBody& body) { - std::string message; - if (body.getMethod()) { - switch (body.getMethod()->amqpClassId()) { - case DTX_CLASS_ID: message = "DTX transactions are not currently supported by cluster."; break; - } - } - if (!message.empty()) - connection->close(connection::CLOSE_CODE_FRAMING_ERROR, message); - return !message.empty(); -} - -struct GiveReadCreditOnExit { - Connection& connection; - int credit; - GiveReadCreditOnExit(Connection& connection_, int credit_) : - connection(connection_), credit(credit_) {} - ~GiveReadCreditOnExit() { if (credit) connection.giveReadCredit(credit); } -}; - -void Connection::deliverDoOutput(uint32_t limit) { - output.deliverDoOutput(limit); -} - -// Called in delivery thread, in cluster order. -void Connection::deliveredFrame(const EventFrame& f) { - GiveReadCreditOnExit gc(*this, f.readCredit); - assert(!catchUp); - currentChannel = f.frame.getChannel(); - if (f.frame.getBody() // frame can be emtpy with just readCredit - && !framing::invoke(*this, *f.frame.getBody()).wasHandled() // Connection contol. - && !checkUnsupported(*f.frame.getBody())) // Unsupported operation. - { - if (f.type == DATA) // incoming data frames to broker::Connection - connection->received(const_cast<AMQFrame&>(f.frame)); - else { // frame control, send frame via SessionState - broker::SessionState* ss = connection->getChannel(currentChannel).getSession(); - if (ss) ss->out(const_cast<AMQFrame&>(f.frame)); - } - } -} - -// A local connection is closed by the network layer. Called in the connection thread. -void Connection::closed() { - try { - if (isUpdated()) { - QPID_LOG(debug, cluster << " update connection closed " << *this); - close(); - cluster.updateInClosed(); - } - else if (catchUp && cluster.isExpectingUpdate()) { - QPID_LOG(critical, cluster << " catch-up connection closed prematurely " << *this); - cluster.leave(); - } - else if (isLocal()) { - // This was a local replicated connection. Multicast a deliver - // closed and process any outstanding frames from the cluster - // until self-delivery of deliver-close. - output.closeOutput(); - if (announced) - cluster.getMulticast().mcastControl( - ClusterConnectionDeliverCloseBody(), self); - } - } - catch (const std::exception& e) { - QPID_LOG(error, cluster << " error closing connection " << *this << ": " << e.what()); - } -} - -// Self-delivery of close message, close the connection. -void Connection::deliverClose () { - close(); - cluster.erase(self); -} - -// Close the connection -void Connection::close() { - if (connection.get()) { - QPID_LOG(debug, cluster << " closed connection " << *this); - connection->closed(); - connection.reset(); - } -} - -// The connection has sent invalid data and should be aborted. -// All members will get the same abort since they all process the same data. -void Connection::abort() { - connection->abort(); - // Aborting the connection will result in a call to ::closed() - // and allow the connection to close in an orderly manner. -} - -// ConnectionCodec::decode receives read buffers from directly-connected clients. -size_t Connection::decode(const char* data, size_t size) { - GiveReadCreditOnExit grc(*this, 1); // Give a read credit by default. - const char* ptr = data; - const char* end = data + size; - if (catchUp) { // Handle catch-up locally. - if (!cluster.isExpectingUpdate()) { - QPID_LOG(error, "Rejecting unexpected catch-up connection."); - abort(); // Cluster is not expecting catch-up connections. - } - bool wasOpen = connection->isOpen(); - Buffer buf(const_cast<char*>(ptr), size); - ptr += size; - while (localDecoder.decode(buf)) - received(localDecoder.getFrame()); - if (!wasOpen && connection->isOpen()) { - // Connections marked as federation links are allowed to proxy - // messages with user-ID that doesn't match the connection's - // authenticated ID. This is important for updates. - connection->setFederationLink(isCatchUp()); - } - } - else { // Multicast local connections. - assert(isLocalClient()); - assert(connection.get()); - if (!checkProtocolHeader(ptr, size)) // Updates ptr - return 0; // Incomplete header - - if (!connection->isOpen()) - processInitialFrames(ptr, end-ptr); // Updates ptr - - if (connection->isOpen() && end - ptr > 0) { - // We're multi-casting, we will give read credit on delivery. - grc.credit = 0; - cluster.getMulticast().mcastBuffer(ptr, end - ptr, self); - ptr = end; - } - } - return ptr - data; -} - -// Decode the protocol header if needed. Updates data and size -// returns true if the header is complete or already read. -bool Connection::checkProtocolHeader(const char*& data, size_t size) { - if (expectProtocolHeader) { - // This is an outgoing link connection, we will receive a protocol - // header which needs to be decoded first - framing::ProtocolInitiation pi; - Buffer buf(const_cast<char*&>(data), size); - if (pi.decode(buf)) { - //TODO: check the version is correct - expectProtocolHeader = false; - data += pi.encodedSize(); - } else { - return false; - } - } - return true; -} - -void Connection::processInitialFrames(const char*& ptr, size_t size) { - // Process the initial negotiation locally and store it so - // it can be replayed on other brokers in announce() - Buffer buf(const_cast<char*>(ptr), size); - framing::AMQFrame frame; - while (!connection->isOpen() && frame.decode(buf)) - received(frame); - initialFrames.append(ptr, buf.getPosition()); - ptr += buf.getPosition(); - if (connection->isOpen()) { // initial negotiation complete - cluster.getMulticast().mcastControl( - ClusterConnectionAnnounceBody( - ProtocolVersion(), - connectionCtor.mgmtId, - connectionCtor.external.ssf, - connectionCtor.external.authid, - connectionCtor.external.nodict, - connection->getUserId(), - initialFrames), - getId()); - announced = true; - initialFrames.clear(); - } -} - -broker::SessionState& Connection::sessionState() { - return *connection->getChannel(currentChannel).getSession(); -} - -broker::SemanticState& Connection::semanticState() { - return sessionState().getSemanticState(); -} - -void Connection::shadowPrepare(const std::string& mgmtId) { - updateIn.nextShadowMgmtId = mgmtId; -} - -void Connection::shadowSetUser(const std::string& userId) { - connection->setUserId(userId); -} - -void Connection::consumerState(const string& name, bool blocked, bool notifyEnabled, const SequenceNumber& position) -{ - broker::SemanticState::ConsumerImpl& c = semanticState().find(name); - c.position = position; - c.setBlocked(blocked); - if (notifyEnabled) c.enableNotify(); else c.disableNotify(); - updateIn.consumerNumbering.add(c.shared_from_this()); -} - - -void Connection::sessionState( - const SequenceNumber& replayStart, - const SequenceNumber& sendCommandPoint, - const SequenceSet& sentIncomplete, - const SequenceNumber& expected, - const SequenceNumber& received, - const SequenceSet& unknownCompleted, - const SequenceSet& receivedIncomplete) -{ - sessionState().setState( - replayStart, - sendCommandPoint, - sentIncomplete, - expected, - received, - unknownCompleted, - receivedIncomplete); - QPID_LOG(debug, cluster << " received session state update for " << sessionState().getId()); - // The output tasks will be added later in the update process. - connection->getOutputTasks().removeAll(); -} - -void Connection::outputTask(uint16_t channel, const std::string& name) { - broker::SessionState* session = connection->getChannel(channel).getSession(); - if (!session) - throw Exception(QPID_MSG(cluster << " channel not attached " << *this - << "[" << channel << "] ")); - OutputTask* task = &session->getSemanticState().find(name); - connection->getOutputTasks().addOutputTask(task); -} - -void Connection::shadowReady( - uint64_t memberId, uint64_t connectionId, const string& mgmtId, - const string& username, const string& fragment, uint32_t sendMax) -{ - QPID_ASSERT(mgmtId == getBrokerConnection()->getMgmtId()); - ConnectionId shadowId = ConnectionId(memberId, connectionId); - QPID_LOG(debug, cluster << " catch-up connection " << *this - << " becomes shadow " << shadowId); - self = shadowId; - connection->setUserId(username); - // OK to use decoder here because cluster is stalled for update. - cluster.getDecoder().get(self).setFragment(fragment.data(), fragment.size()); - connection->setErrorListener(this); - output.setSendMax(sendMax); -} - -void Connection::membership(const FieldTable& joiners, const FieldTable& members, - const framing::SequenceNumber& frameSeq) -{ - QPID_LOG(debug, cluster << " incoming update complete on connection " << *this); - updateIn.consumerNumbering.clear(); - closeUpdated(); - cluster.updateInDone(ClusterMap(joiners, members, frameSeq)); -} - -void Connection::retractOffer() { - QPID_LOG(info, cluster << " incoming update retracted on connection " << *this); - closeUpdated(); - cluster.updateInRetracted(); -} - -void Connection::closeUpdated() { - self.second = 0; // Mark this as completed update connection. - if (connection.get()) - connection->close(connection::CLOSE_CODE_NORMAL, "OK"); -} - -bool Connection::isLocal() const { - return self.first == cluster.getId() && self.second; -} - -bool Connection::isShadow() const { - return self.first != cluster.getId(); -} - -bool Connection::isUpdated() const { - return self.first == cluster.getId() && self.second == 0; -} - - -boost::shared_ptr<broker::Queue> Connection::findQueue(const std::string& qname) { - boost::shared_ptr<broker::Queue> queue = cluster.getBroker().getQueues().find(qname); - if (!queue) throw Exception(QPID_MSG(cluster << " can't find queue " << qname)); - return queue; -} - -broker::QueuedMessage Connection::getUpdateMessage() { - boost::shared_ptr<broker::Queue> updateq = findQueue(UpdateClient::UPDATE); - assert(!updateq->isDurable()); - broker::QueuedMessage m = updateq->get(); - if (!m.payload) throw Exception(QPID_MSG(cluster << " empty update queue")); - return m; -} - -void Connection::deliveryRecord(const string& qname, - const SequenceNumber& position, - const string& tag, - const SequenceNumber& id, - bool acquired, - bool accepted, - bool cancelled, - bool completed, - bool ended, - bool windowing, - bool enqueued, - uint32_t credit) -{ - broker::QueuedMessage m; - broker::Queue::shared_ptr queue = findQueue(qname); - if (!ended) { // Has a message - if (acquired) { // Message is on the update queue - m = getUpdateMessage(); - m.queue = queue.get(); - m.position = position; - if (enqueued) queue->updateEnqueued(m); //inform queue of the message - } else { // Message at original position in original queue - m = queue->find(position); - } - if (!m.payload) - throw Exception(QPID_MSG("deliveryRecord no update message")); - } - - broker::DeliveryRecord dr(m, queue, tag, acquired, accepted, windowing, credit); - dr.setId(id); - if (cancelled) dr.cancel(dr.getTag()); - if (completed) dr.complete(); - if (ended) dr.setEnded(); // Exsitance of message - semanticState().record(dr); // Part of the session's unacked list. -} - -void Connection::queuePosition(const string& qname, const SequenceNumber& position) { - findQueue(qname)->setPosition(position); -} - -void Connection::queueFairshareState(const std::string& qname, const uint8_t priority, const uint8_t count) -{ - if (!qpid::broker::Fairshare::setState(findQueue(qname)->getMessages(), priority, count)) { - QPID_LOG(error, "Failed to set fair share state on queue " << qname << "; this will result in inconsistencies."); - } -} - - -namespace { - // find a StatefulQueueObserver that matches a given identifier - class ObserverFinder { - const std::string id; - boost::shared_ptr<broker::QueueObserver> target; - ObserverFinder(const ObserverFinder&) {} - public: - ObserverFinder(const std::string& _id) : id(_id) {} - broker::StatefulQueueObserver *getObserver() - { - if (target) - return dynamic_cast<broker::StatefulQueueObserver *>(target.get()); - return 0; - } - void operator() (boost::shared_ptr<broker::QueueObserver> o) - { - if (!target) { - broker::StatefulQueueObserver *p = dynamic_cast<broker::StatefulQueueObserver *>(o.get()); - if (p && p->getId() == id) { - target = o; - } - } - } - }; -} - - -void Connection::queueObserverState(const std::string& qname, const std::string& observerId, const FieldTable& state) -{ - boost::shared_ptr<broker::Queue> queue(findQueue(qname)); - ObserverFinder finder(observerId); // find this observer - queue->eachObserver<ObserverFinder &>(finder); - broker::StatefulQueueObserver *so = finder.getObserver(); - if (so) { - so->setState( state ); - QPID_LOG(debug, "updated queue observer " << observerId << "'s state on queue " << qname << "; ..."); - return; - } - QPID_LOG(error, "Failed to find observer " << observerId << " state on queue " << qname << "; this will result in inconsistencies."); -} - -void Connection::expiryId(uint64_t id) { - cluster.getExpiryPolicy().setId(id); -} - -std::ostream& operator<<(std::ostream& o, const Connection& c) { - const char* type="unknown"; - if (c.isLocal()) type = "local"; - else if (c.isShadow()) type = "shadow"; - else if (c.isUpdated()) type = "updated"; - const broker::Connection* bc = c.getBrokerConnection(); - if (bc) o << bc->getMgmtId(); - else o << "<disconnected>"; - return o << "(" << c.getId() << " " << type << (c.isCatchUp() ? ",catchup":"") << ")"; -} - -void Connection::txStart() { - txBuffer.reset(new broker::TxBuffer()); -} -void Connection::txAccept(const framing::SequenceSet& acked) { - txBuffer->enlist(boost::shared_ptr<broker::TxAccept>( - new broker::TxAccept(acked, semanticState().getUnacked()))); -} - -void Connection::txDequeue(const std::string& queue) { - txBuffer->enlist(boost::shared_ptr<broker::RecoveredDequeue>( - new broker::RecoveredDequeue(findQueue(queue), getUpdateMessage().payload))); -} - -void Connection::txEnqueue(const std::string& queue) { - txBuffer->enlist(boost::shared_ptr<broker::RecoveredEnqueue>( - new broker::RecoveredEnqueue(findQueue(queue), getUpdateMessage().payload))); -} - -void Connection::txPublish(const framing::Array& queues, bool delivered) { - boost::shared_ptr<broker::TxPublish> txPub(new broker::TxPublish(getUpdateMessage().payload)); - for (framing::Array::const_iterator i = queues.begin(); i != queues.end(); ++i) - txPub->deliverTo(findQueue((*i)->get<std::string>())); - txPub->delivered = delivered; - txBuffer->enlist(txPub); -} - -void Connection::txEnd() { - semanticState().setTxBuffer(txBuffer); -} - -void Connection::accumulatedAck(const qpid::framing::SequenceSet& s) { - semanticState().setAccumulatedAck(s); -} - -void Connection::exchange(const std::string& encoded) { - Buffer buf(const_cast<char*>(encoded.data()), encoded.size()); - broker::Exchange::shared_ptr ex = broker::Exchange::decode(cluster.getBroker().getExchanges(), buf); - if(ex.get() && ex->isDurable() && !ex->getName().find("amq.") == 0 && !ex->getName().find("qpid.") == 0) { - cluster.getBroker().getStore().create(*(ex.get()), ex->getArgs()); - } - QPID_LOG(debug, cluster << " updated exchange " << ex->getName()); -} - -void Connection::sessionError(uint16_t , const std::string& msg) { - // Ignore errors before isOpen(), we're not multicasting yet. - if (connection->isOpen()) - cluster.flagError(*this, ERROR_TYPE_SESSION, msg); -} - -void Connection::connectionError(const std::string& msg) { - // Ignore errors before isOpen(), we're not multicasting yet. - if (connection->isOpen()) - cluster.flagError(*this, ERROR_TYPE_CONNECTION, msg); -} - -void Connection::addQueueListener(const std::string& q, uint32_t listener) { - if (listener >= updateIn.consumerNumbering.size()) - throw Exception(QPID_MSG("Invalid listener ID: " << listener)); - findQueue(q)->getListeners().addListener(updateIn.consumerNumbering[listener]); -} - -// -// This is the handler for incoming managementsetup messages. -// -void Connection::managementSetupState( - uint64_t objectNum, uint16_t bootSequence, const framing::Uuid& id, - const std::string& vendor, const std::string& product, const std::string& instance) -{ - QPID_LOG(debug, cluster << " updated management: object number=" - << objectNum << " boot sequence=" << bootSequence - << " broker-id=" << id - << " vendor=" << vendor - << " product=" << product - << " instance=" << instance); - management::ManagementAgent* agent = cluster.getBroker().getManagementAgent(); - if (!agent) - throw Exception(QPID_MSG("Management schema update but management not enabled.")); - agent->setNextObjectId(objectNum); - agent->setBootSequence(bootSequence); - agent->setUuid(id); - agent->setName(vendor, product, instance); -} - -void Connection::config(const std::string& encoded) { - Buffer buf(const_cast<char*>(encoded.data()), encoded.size()); - string kind; - buf.getShortString (kind); - if (kind == "link") { - broker::Link::shared_ptr link = - broker::Link::decode(cluster.getBroker().getLinks(), buf); - QPID_LOG(debug, cluster << " updated link " - << link->getHost() << ":" << link->getPort()); - } - else if (kind == "bridge") { - broker::Bridge::shared_ptr bridge = - broker::Bridge::decode(cluster.getBroker().getLinks(), buf); - QPID_LOG(debug, cluster << " updated bridge " << bridge->getName()); - } - else throw Exception(QPID_MSG("Update failed, invalid kind of config: " << kind)); -} - -void Connection::doCatchupIoCallbacks() { - // We need to process IO callbacks during the catch-up phase in - // order to service asynchronous completions for messages - // transferred during catch-up. - - if (catchUp) getBrokerConnection()->doIoCallbacks(); -} -}} // Namespace qpid::cluster - diff --git a/cpp/src/qpid/cluster/Connection.h b/cpp/src/qpid/cluster/Connection.h deleted file mode 100644 index a0da9efbb8..0000000000 --- a/cpp/src/qpid/cluster/Connection.h +++ /dev/null @@ -1,276 +0,0 @@ -#ifndef QPID_CLUSTER_CONNECTION_H -#define QPID_CLUSTER_CONNECTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "types.h" -#include "OutputInterceptor.h" -#include "McastFrameHandler.h" -#include "UpdateReceiver.h" - -#include "qpid/RefCounted.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/SecureConnection.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/amqp_0_10/Connection.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/ConnectionInputHandler.h" -#include "qpid/sys/ConnectionOutputHandler.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/FrameDecoder.h" - -#include <iosfwd> - -namespace qpid { - -namespace framing { class AMQFrame; } - -namespace broker { -class SemanticState; -struct QueuedMessage; -class TxBuffer; -class TxAccept; -} - -namespace cluster { -class Cluster; -class Event; -struct EventFrame; - -/** Intercept broker::Connection calls for shadow and local cluster connections. */ -class Connection : - public RefCounted, - public sys::ConnectionInputHandler, - public framing::AMQP_AllOperations::ClusterConnectionHandler, - private broker::Connection::ErrorListener - -{ - public: - - /** Local connection. */ - Connection(Cluster&, sys::ConnectionOutputHandler& out, const std::string& mgmtId, MemberId, bool catchUp, bool isLink, - const qpid::sys::SecuritySettings& external); - /** Shadow connection. */ - Connection(Cluster&, sys::ConnectionOutputHandler& out, const std::string& mgmtId, const ConnectionId& id, - const qpid::sys::SecuritySettings& external); - ~Connection(); - - ConnectionId getId() const { return self; } - broker::Connection* getBrokerConnection() { return connection.get(); } - const broker::Connection* getBrokerConnection() const { return connection.get(); } - - /** Local connections may be clients or catch-up connections */ - bool isLocal() const; - - bool isLocalClient() const { return isLocal() && !isCatchUp(); } - - /** True for connections that are shadowing remote broker connections */ - bool isShadow() const; - - /** True if the connection is in "catch-up" mode: building initial broker state. */ - bool isCatchUp() const { return catchUp; } - - /** True if the connection is a completed shared update connection */ - bool isUpdated() const; - - Cluster& getCluster() { return cluster; } - - // ConnectionInputHandler methods - void received(framing::AMQFrame&); - void closed(); - bool doOutput(); - void idleOut() { if (connection.get()) connection->idleOut(); } - void idleIn() { if (connection.get()) connection->idleIn(); } - - // ConnectionCodec methods - called by IO layer with a read buffer. - size_t decode(const char* buffer, size_t size); - - // Called for data delivered from the cluster. - void deliveredFrame(const EventFrame&); - - void consumerState(const std::string& name, bool blocked, bool notifyEnabled, const qpid::framing::SequenceNumber& position); - - // ==== Used in catch-up mode to build initial state. - // - // State update methods. - void shadowPrepare(const std::string&); - - void shadowSetUser(const std::string&); - - void sessionState(const framing::SequenceNumber& replayStart, - const framing::SequenceNumber& sendCommandPoint, - const framing::SequenceSet& sentIncomplete, - const framing::SequenceNumber& expected, - const framing::SequenceNumber& received, - const framing::SequenceSet& unknownCompleted, - const SequenceSet& receivedIncomplete); - - void outputTask(uint16_t channel, const std::string& name); - - void shadowReady(uint64_t memberId, - uint64_t connectionId, - const std::string& managementId, - const std::string& username, - const std::string& fragment, - uint32_t sendMax); - - void membership(const framing::FieldTable&, const framing::FieldTable&, - const framing::SequenceNumber& frameSeq); - - void retractOffer(); - - void deliveryRecord(const std::string& queue, - const framing::SequenceNumber& position, - const std::string& tag, - const framing::SequenceNumber& id, - bool acquired, - bool accepted, - bool cancelled, - bool completed, - bool ended, - bool windowing, - bool enqueued, - uint32_t credit); - - void queuePosition(const std::string&, const framing::SequenceNumber&); - void queueFairshareState(const std::string&, const uint8_t priority, const uint8_t count); - void queueObserverState(const std::string&, const std::string&, const framing::FieldTable&); - void expiryId(uint64_t); - - void txStart(); - void txAccept(const framing::SequenceSet&); - void txDequeue(const std::string&); - void txEnqueue(const std::string&); - void txPublish(const framing::Array&, bool); - void txEnd(); - void accumulatedAck(const framing::SequenceSet&); - - // Encoded exchange replication. - void exchange(const std::string& encoded); - - void giveReadCredit(int credit); - void announce(const std::string& mgmtId, uint32_t ssf, const std::string& authid, - bool nodict, const std::string& username, - const std::string& initFrames); - void close(); - void abort(); - void deliverClose(); - - OutputInterceptor& getOutput() { return output; } - - void addQueueListener(const std::string& queue, uint32_t listener); - void managementSetupState(uint64_t objectNum, - uint16_t bootSequence, - const framing::Uuid&, - const std::string& vendor, - const std::string& product, - const std::string& instance); - - void config(const std::string& encoded); - - void setSecureConnection ( broker::SecureConnection * sc ); - - void doCatchupIoCallbacks(); - - private: - struct NullFrameHandler : public framing::FrameHandler { - void handle(framing::AMQFrame&) {} - }; - - // Arguments to construct a broker::Connection - struct ConnectionCtor { - sys::ConnectionOutputHandler* out; - broker::Broker& broker; - std::string mgmtId; - qpid::sys::SecuritySettings external; - bool isLink; - uint64_t objectId; - bool shadow; - bool delayManagement; - - ConnectionCtor( - sys::ConnectionOutputHandler* out_, - broker::Broker& broker_, - const std::string& mgmtId_, - const qpid::sys::SecuritySettings& external_, - bool isLink_=false, - uint64_t objectId_=0, - bool shadow_=false, - bool delayManagement_=false - ) : out(out_), broker(broker_), mgmtId(mgmtId_), external(external_), - isLink(isLink_), objectId(objectId_), shadow(shadow_), - delayManagement(delayManagement_) - {} - - std::auto_ptr<broker::Connection> construct() { - return std::auto_ptr<broker::Connection>( - new broker::Connection( - out, broker, mgmtId, external, isLink, objectId, - shadow, delayManagement) - ); - } - }; - - static NullFrameHandler nullFrameHandler; - - // Error listener functions - void connectionError(const std::string&); - void sessionError(uint16_t channel, const std::string&); - - void init(); - bool checkUnsupported(const framing::AMQBody& body); - void deliverDoOutput(uint32_t limit); - - bool checkProtocolHeader(const char*& data, size_t size); - void processInitialFrames(const char*& data, size_t size); - boost::shared_ptr<broker::Queue> findQueue(const std::string& qname); - broker::SessionState& sessionState(); - broker::SemanticState& semanticState(); - broker::QueuedMessage getUpdateMessage(); - void closeUpdated(); - - Cluster& cluster; - ConnectionId self; - bool catchUp; - bool announced; - OutputInterceptor output; - framing::FrameDecoder localDecoder; - ConnectionCtor connectionCtor; - std::auto_ptr<broker::Connection> connection; - framing::SequenceNumber deliverSeq; - framing::ChannelId currentChannel; - boost::shared_ptr<broker::TxBuffer> txBuffer; - bool expectProtocolHeader; - McastFrameHandler mcastFrameHandler; - UpdateReceiver& updateIn; - qpid::broker::SecureConnection* secureConnection; - std::string initialFrames; - - static qpid::sys::AtomicValue<uint64_t> catchUpId; - - friend std::ostream& operator<<(std::ostream&, const Connection&); -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_CONNECTION_H*/ diff --git a/cpp/src/qpid/cluster/ConnectionCodec.cpp b/cpp/src/qpid/cluster/ConnectionCodec.cpp deleted file mode 100644 index d0ba8abfb3..0000000000 --- a/cpp/src/qpid/cluster/ConnectionCodec.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/ConnectionCodec.h" -#include "qpid/cluster/Connection.h" -#include "qpid/cluster/Cluster.h" -#include "qpid/cluster/ProxyInputHandler.h" -#include "qpid/broker/Connection.h" -#include "qpid/framing/ConnectionCloseBody.h" -#include "qpid/framing/ConnectionCloseOkBody.h" -#include "qpid/log/Statement.h" -#include "qpid/memory.h" -#include <stdexcept> -#include <boost/utility/in_place_factory.hpp> - -namespace qpid { -namespace cluster { - -using namespace framing; - -sys::ConnectionCodec* -ConnectionCodec::Factory::create(ProtocolVersion v, sys::OutputControl& out, - const std::string& id, - const qpid::sys::SecuritySettings& external) -{ - broker::Broker& broker = cluster.getBroker(); - if (broker.getConnectionCounter().allowConnection()) - { - QPID_LOG(error, "Client max connection count limit exceeded: " - << broker.getOptions().maxConnections << " connection refused"); - return 0; - } - if (v == ProtocolVersion(0, 10)) - return new ConnectionCodec(v, out, id, cluster, false, false, external); - else if (v == ProtocolVersion(0x80 + 0, 0x80 + 10)) // Catch-up connection - return new ConnectionCodec(v, out, id, cluster, true, false, external); - return 0; -} - -// Used for outgoing Link connections -sys::ConnectionCodec* -ConnectionCodec::Factory::create(sys::OutputControl& out, const std::string& logId, - const qpid::sys::SecuritySettings& external) { - return new ConnectionCodec(ProtocolVersion(0,10), out, logId, cluster, false, true, external); -} - -ConnectionCodec::ConnectionCodec( - const ProtocolVersion& v, sys::OutputControl& out, - const std::string& logId, Cluster& cluster, bool catchUp, bool isLink, const qpid::sys::SecuritySettings& external -) : codec(out, logId, isLink), - interceptor(new Connection(cluster, codec, logId, cluster.getId(), catchUp, isLink, external)) -{ - cluster.addLocalConnection(interceptor); - std::auto_ptr<sys::ConnectionInputHandler> ih(new ProxyInputHandler(interceptor)); - codec.setInputHandler(ih); - codec.setVersion(v); -} - -ConnectionCodec::~ConnectionCodec() {} - -size_t ConnectionCodec::decode(const char* buffer, size_t size) { - return interceptor->decode(buffer, size); -} - -bool ConnectionCodec::isClosed() const { return codec.isClosed(); } - -size_t ConnectionCodec::encode(const char* buffer, size_t size) { return codec.encode(buffer, size); } - -bool ConnectionCodec::canEncode() { return codec.canEncode(); } - -void ConnectionCodec::closed() { codec.closed(); } - -ProtocolVersion ConnectionCodec::getVersion() const { return codec.getVersion(); } - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/ConnectionCodec.h b/cpp/src/qpid/cluster/ConnectionCodec.h deleted file mode 100644 index 17a08904d9..0000000000 --- a/cpp/src/qpid/cluster/ConnectionCodec.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef QPID_CLUSTER_CONNCTIONCODEC_H -#define QPID_CLUSTER_CONNCTIONCODEC_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/Connection.h" -#include "qpid/cluster/Connection.h" -#include <boost/shared_ptr.hpp> -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - -namespace broker { -class Connection; -} - -namespace cluster { -class Cluster; - -/** - * Encapsulates the standard amqp_0_10::ConnectionCodec and sets up - * a cluster::Connection for the connection. - * - * The ConnectionCodec is deleted by the network layer when the - * connection closes. The cluster::Connection needs to be kept - * around until all cluster business on the connection is complete. - * - */ -class ConnectionCodec : public sys::ConnectionCodec { - public: - struct Factory : public sys::ConnectionCodec::Factory { - boost::shared_ptr<sys::ConnectionCodec::Factory> next; - Cluster& cluster; - Factory(boost::shared_ptr<sys::ConnectionCodec::Factory> f, Cluster& c) - : next(f), cluster(c) {} - sys::ConnectionCodec* create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id, - const qpid::sys::SecuritySettings& external); - sys::ConnectionCodec* create(sys::OutputControl&, const std::string& id, - const qpid::sys::SecuritySettings& external); - }; - - ConnectionCodec(const framing::ProtocolVersion&, sys::OutputControl& out, - const std::string& logId, Cluster& c, bool catchUp, bool isLink, - const qpid::sys::SecuritySettings& external); - ~ConnectionCodec(); - - // ConnectionCodec functions. - size_t decode(const char* buffer, size_t size); - size_t encode(const char* buffer, size_t size); - bool canEncode(); - void closed(); - bool isClosed() const; - framing::ProtocolVersion getVersion() const; - void setSecureConnection(broker::SecureConnection* sc) { interceptor->setSecureConnection(sc); } - - private: - amqp_0_10::Connection codec; - boost::intrusive_ptr<cluster::Connection> interceptor; -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_CONNCTIONCODEC_H*/ diff --git a/cpp/src/qpid/cluster/Cpg.cpp b/cpp/src/qpid/cluster/Cpg.cpp deleted file mode 100644 index 0856bcd824..0000000000 --- a/cpp/src/qpid/cluster/Cpg.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/cluster/Cpg.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include "qpid/log/Statement.h" - -#include <vector> -#include <limits> -#include <iterator> -#include <sstream> - -#include <unistd.h> - -// This is a macro instead of a function because we don't want to -// evaluate the MSG argument unless there is an error. -#define CPG_CHECK(RESULT, MSG) \ - if ((RESULT) != CPG_OK) throw Exception(errorStr((RESULT), (MSG))) - -namespace qpid { -namespace cluster { - -using namespace std; - - - -Cpg* Cpg::cpgFromHandle(cpg_handle_t handle) { - void* cpg=0; - CPG_CHECK(cpg_context_get(handle, &cpg), "Cannot get CPG instance."); - if (!cpg) throw Exception("Cannot get CPG instance."); - return reinterpret_cast<Cpg*>(cpg); -} - -// Applies the same retry-logic to all cpg calls that need it. -void Cpg::callCpg ( CpgOp & c ) { - cpg_error_t result; - unsigned int snooze = 10; - for ( unsigned int nth_try = 0; nth_try < cpgRetries; ++ nth_try ) { - if ( CPG_OK == (result = c.op(handle, & group))) { - break; - } - else if ( result == CPG_ERR_TRY_AGAIN ) { - QPID_LOG(info, "Retrying " << c.opName ); - sys::usleep ( snooze ); - snooze *= 10; - snooze = (snooze <= maxCpgRetrySleep) ? snooze : maxCpgRetrySleep; - } - else break; // Don't retry unless CPG tells us to. - } - - if ( result != CPG_OK ) - CPG_CHECK(result, c.msg(group)); -} - -// Global callback functions. -void Cpg::globalDeliver ( - cpg_handle_t handle, - const struct cpg_name *group, - uint32_t nodeid, - uint32_t pid, - void* msg, - size_t msg_len) -{ - cpgFromHandle(handle)->handler.deliver(handle, group, nodeid, pid, msg, msg_len); -} - -void Cpg::globalConfigChange( - cpg_handle_t handle, - const struct cpg_name *group, - const struct cpg_address *members, size_t nMembers, - const struct cpg_address *left, size_t nLeft, - const struct cpg_address *joined, size_t nJoined -) -{ - cpgFromHandle(handle)->handler.configChange(handle, group, members, nMembers, left, nLeft, joined, nJoined); -} - -void Cpg::globalDeliver ( - cpg_handle_t handle, - struct cpg_name *group, - uint32_t nodeid, - uint32_t pid, - void* msg, - int msg_len) -{ - cpgFromHandle(handle)->handler.deliver(handle, group, nodeid, pid, msg, msg_len); -} - -void Cpg::globalConfigChange( - cpg_handle_t handle, - struct cpg_name *group, - struct cpg_address *members, int nMembers, - struct cpg_address *left, int nLeft, - struct cpg_address *joined, int nJoined -) -{ - cpgFromHandle(handle)->handler.configChange(handle, group, members, nMembers, left, nLeft, joined, nJoined); -} - -int Cpg::getFd() { - int fd; - CPG_CHECK(cpg_fd_get(handle, &fd), "Cannot get CPG file descriptor"); - return fd; -} - -Cpg::Cpg(Handler& h) : IOHandle(new sys::IOHandlePrivate), handler(h), isShutdown(false) { - cpg_callbacks_t callbacks; - ::memset(&callbacks, 0, sizeof(callbacks)); - callbacks.cpg_deliver_fn = &globalDeliver; - callbacks.cpg_confchg_fn = &globalConfigChange; - - QPID_LOG(notice, "Initializing CPG"); - cpg_error_t err = cpg_initialize(&handle, &callbacks); - int retries = 6; // FIXME aconway 2009-08-06: make this configurable. - while (err == CPG_ERR_TRY_AGAIN && --retries) { - QPID_LOG(notice, "Re-trying CPG initialization."); - sys::sleep(5); - err = cpg_initialize(&handle, &callbacks); - } - CPG_CHECK(err, "Failed to initialize CPG."); - CPG_CHECK(cpg_context_set(handle, this), "Cannot set CPG context"); - // Note: CPG is currently unix-specific. If CPG is ported to - // windows then this needs to be refactored into - // qpid::sys::<platform> - IOHandle::impl->fd = getFd(); -} - -Cpg::~Cpg() { - try { - shutdown(); - } catch (const std::exception& e) { - QPID_LOG(error, "Error during CPG shutdown: " << e.what()); - } -} - -void Cpg::join(const std::string& name) { - group = name; - callCpg ( cpgJoinOp ); -} - -void Cpg::leave() { - callCpg ( cpgLeaveOp ); -} - - - - -bool Cpg::mcast(const iovec* iov, int iovLen) { - // Check for flow control - cpg_flow_control_state_t flowState; - CPG_CHECK(cpg_flow_control_state_get(handle, &flowState), "Cannot get CPG flow control status."); - if (flowState == CPG_FLOW_CONTROL_ENABLED) - return false; - - cpg_error_t result; - do { - result = cpg_mcast_joined(handle, CPG_TYPE_AGREED, const_cast<iovec*>(iov), iovLen); - if (result != CPG_ERR_TRY_AGAIN) CPG_CHECK(result, cantMcastMsg(group)); - } while(result == CPG_ERR_TRY_AGAIN); - return true; -} - -void Cpg::shutdown() { - if (!isShutdown) { - QPID_LOG(debug,"Shutting down CPG"); - isShutdown=true; - - callCpg ( cpgFinalizeOp ); - } -} - -void Cpg::dispatchOne() { - CPG_CHECK(cpg_dispatch(handle,CPG_DISPATCH_ONE), "Error in CPG dispatch"); -} - -void Cpg::dispatchAll() { - CPG_CHECK(cpg_dispatch(handle,CPG_DISPATCH_ALL), "Error in CPG dispatch"); -} - -void Cpg::dispatchBlocking() { - CPG_CHECK(cpg_dispatch(handle,CPG_DISPATCH_BLOCKING), "Error in CPG dispatch"); -} - -string Cpg::errorStr(cpg_error_t err, const std::string& msg) { - std::ostringstream os; - os << msg << ": "; - switch (err) { - case CPG_OK: os << "ok"; break; - case CPG_ERR_LIBRARY: os << "library"; break; - case CPG_ERR_TIMEOUT: os << "timeout"; break; - case CPG_ERR_TRY_AGAIN: os << "try again"; break; - case CPG_ERR_INVALID_PARAM: os << "invalid param"; break; - case CPG_ERR_NO_MEMORY: os << "no memory"; break; - case CPG_ERR_BAD_HANDLE: os << "bad handle"; break; - case CPG_ERR_ACCESS: os << "access denied. You may need to set your group ID to 'ais'"; break; - case CPG_ERR_NOT_EXIST: os << "not exist"; break; - case CPG_ERR_EXIST: os << "exist"; break; - case CPG_ERR_NOT_SUPPORTED: os << "not supported"; break; - case CPG_ERR_SECURITY: os << "security"; break; - case CPG_ERR_TOO_MANY_GROUPS: os << "too many groups"; break; - default: os << ": unknown cpg error " << err; - }; - os << " (" << err << ")"; - return os.str(); -} - -std::string Cpg::cantJoinMsg(const Name& group) { - return "Cannot join CPG group "+group.str(); -} - -std::string Cpg::cantFinalizeMsg(const Name& group) { - return "Cannot finalize CPG group "+group.str(); -} - -std::string Cpg::cantLeaveMsg(const Name& group) { - return "Cannot leave CPG group "+group.str(); -} - -std::string Cpg::cantMcastMsg(const Name& group) { - return "Cannot mcast to CPG group "+group.str(); -} - -MemberId Cpg::self() const { - unsigned int nodeid; - CPG_CHECK(cpg_local_get(handle, &nodeid), "Cannot get local CPG identity"); - return MemberId(nodeid, getpid()); -} - -namespace { int byte(uint32_t value, int i) { return (value >> (i*8)) & 0xff; } } - -ostream& operator<<(ostream& out, const MemberId& id) { - if (id.first) { - out << byte(id.first, 0) << "." - << byte(id.first, 1) << "." - << byte(id.first, 2) << "." - << byte(id.first, 3) - << ":"; - } - return out << id.second; -} - -ostream& operator<<(ostream& o, const ConnectionId& c) { - return o << c.first << "-" << c.second; -} - -std::string MemberId::str() const { - char s[8]; - uint32_t x; - x = htonl(first); - ::memcpy(s, &x, 4); - x = htonl(second); - ::memcpy(s+4, &x, 4); - return std::string(s,8); -} - -MemberId::MemberId(const std::string& s) { - uint32_t x; - memcpy(&x, &s[0], 4); - first = ntohl(x); - memcpy(&x, &s[4], 4); - second = ntohl(x); -} -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/Cpg.h b/cpp/src/qpid/cluster/Cpg.h deleted file mode 100644 index 6b81c602bd..0000000000 --- a/cpp/src/qpid/cluster/Cpg.h +++ /dev/null @@ -1,236 +0,0 @@ -#ifndef CPG_H -#define CPG_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/Exception.h" -#include "qpid/cluster/types.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/Mutex.h" - -#include <boost/scoped_ptr.hpp> - -#include <cassert> -#include <string.h> - -namespace qpid { -namespace cluster { - -/** - * Lightweight C++ interface to cpg.h operations. - * - * Manages a single CPG handle, initialized in ctor, finialzed in destructor. - * On error all functions throw Cpg::Exception. - * - */ - -class Cpg : public sys::IOHandle { - public: - struct Exception : public ::qpid::Exception { - Exception(const std::string& msg) : ::qpid::Exception(msg) {} - }; - - struct Name : public cpg_name { - Name() { length = 0; } - Name(const char* s) { copy(s, strlen(s)); } - Name(const char* s, size_t n) { copy(s,n); } - Name(const std::string& s) { copy(s.data(), s.size()); } - void copy(const char* s, size_t n) { - assert(n < CPG_MAX_NAME_LENGTH); - memcpy(value, s, n); - length=n; - } - - std::string str() const { return std::string(value, length); } - }; - - static std::string str(const cpg_name& n) { - return std::string(n.value, n.length); - } - - struct Handler { - virtual ~Handler() {}; - virtual void deliver( - cpg_handle_t /*handle*/, - const struct cpg_name *group, - uint32_t /*nodeid*/, - uint32_t /*pid*/, - void* /*msg*/, - int /*msg_len*/) = 0; - - virtual void configChange( - cpg_handle_t /*handle*/, - const struct cpg_name */*group*/, - const struct cpg_address */*members*/, int /*nMembers*/, - const struct cpg_address */*left*/, int /*nLeft*/, - const struct cpg_address */*joined*/, int /*nJoined*/ - ) = 0; - }; - - /** Open a CPG handle. - *@param handler for CPG events. - */ - Cpg(Handler&); - - /** Destructor calls shutdown if not already calledx. */ - ~Cpg(); - - /** Disconnect from CPG */ - void shutdown(); - - void dispatchOne(); - void dispatchAll(); - void dispatchBlocking(); - - void join(const std::string& group); - void leave(); - - /** Multicast to the group. NB: must not be called concurrently. - * - *@return true if the message was multi-cast, false if - * it was not sent due to flow control. - */ - bool mcast(const iovec* iov, int iovLen); - - cpg_handle_t getHandle() const { return handle; } - - MemberId self() const; - - int getFd(); - - private: - - // Maximum number of retries for cog functions that can tell - // us to "try again later". - static const unsigned int cpgRetries = 5; - - // Don't let sleep-time between cpg retries to go above 0.1 second. - static const unsigned int maxCpgRetrySleep = 100000; - - - // Base class for the Cpg operations that need retry capability. - struct CpgOp { - std::string opName; - - CpgOp ( std::string opName ) - : opName(opName) { } - - virtual cpg_error_t op ( cpg_handle_t handle, struct cpg_name * ) = 0; - virtual std::string msg(const Name&) = 0; - virtual ~CpgOp ( ) { } - }; - - - struct CpgJoinOp : public CpgOp { - CpgJoinOp ( ) - : CpgOp ( std::string("cpg_join") ) { } - - cpg_error_t op(cpg_handle_t handle, struct cpg_name * group) { - return cpg_join ( handle, group ); - } - - std::string msg(const Name& name) { return cantJoinMsg(name); } - }; - - struct CpgLeaveOp : public CpgOp { - CpgLeaveOp ( ) - : CpgOp ( std::string("cpg_leave") ) { } - - cpg_error_t op(cpg_handle_t handle, struct cpg_name * group) { - return cpg_leave ( handle, group ); - } - - std::string msg(const Name& name) { return cantLeaveMsg(name); } - }; - - struct CpgFinalizeOp : public CpgOp { - CpgFinalizeOp ( ) - : CpgOp ( std::string("cpg_finalize") ) { } - - cpg_error_t op(cpg_handle_t handle, struct cpg_name *) { - return cpg_finalize ( handle ); - } - - std::string msg(const Name& name) { return cantFinalizeMsg(name); } - }; - - // This fn standardizes retry policy across all Cpg ops that need it. - void callCpg ( CpgOp & ); - - CpgJoinOp cpgJoinOp; - CpgLeaveOp cpgLeaveOp; - CpgFinalizeOp cpgFinalizeOp; - - static std::string errorStr(cpg_error_t err, const std::string& msg); - static std::string cantJoinMsg(const Name&); - static std::string cantLeaveMsg(const Name&); - static std::string cantMcastMsg(const Name&); - static std::string cantFinalizeMsg(const Name&); - - static Cpg* cpgFromHandle(cpg_handle_t); - - // New versions for corosync 1.0 and higher - static void globalDeliver( - cpg_handle_t handle, - const struct cpg_name *group, - uint32_t nodeid, - uint32_t pid, - void* msg, - size_t msg_len); - - static void globalConfigChange( - cpg_handle_t handle, - const struct cpg_name *group, - const struct cpg_address *members, size_t nMembers, - const struct cpg_address *left, size_t nLeft, - const struct cpg_address *joined, size_t nJoined - ); - - // Old versions for openais - static void globalDeliver( - cpg_handle_t handle, - struct cpg_name *group, - uint32_t nodeid, - uint32_t pid, - void* msg, - int msg_len); - - static void globalConfigChange( - cpg_handle_t handle, - struct cpg_name *group, - struct cpg_address *members, int nMembers, - struct cpg_address *left, int nLeft, - struct cpg_address *joined, int nJoined - ); - - cpg_handle_t handle; - Handler& handler; - bool isShutdown; - Name group; - sys::Mutex dispatchLock; -}; - -inline bool operator==(const cpg_name& a, const cpg_name& b) { - return a.length==b.length && strncmp(a.value, b.value, a.length) == 0; -} -inline bool operator!=(const cpg_name& a, const cpg_name& b) { return !(a == b); } - -}} // namespace qpid::cluster - -#endif /*!CPG_H*/ diff --git a/cpp/src/qpid/cluster/Decoder.cpp b/cpp/src/qpid/cluster/Decoder.cpp deleted file mode 100644 index 23ba372d78..0000000000 --- a/cpp/src/qpid/cluster/Decoder.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/Decoder.h" -#include "qpid/cluster/EventFrame.h" -#include "qpid/framing/ClusterConnectionDeliverCloseBody.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/AMQFrame.h" - - -namespace qpid { -namespace cluster { - -void Decoder::decode(const EventHeader& eh, const char* data) { - sys::Mutex::ScopedLock l(lock); - assert(eh.getType() == DATA); // Only handle connection data events. - const char* cp = static_cast<const char*>(data); - framing::Buffer buf(const_cast<char*>(cp), eh.getSize()); - framing::FrameDecoder& decoder = map[eh.getConnectionId()]; - if (decoder.decode(buf)) { // Decoded a frame - framing::AMQFrame frame(decoder.getFrame()); - while (decoder.decode(buf)) { - callback(EventFrame(eh, frame)); - frame = decoder.getFrame(); - } - // Set read-credit on the last frame ending in this event. - // Credit will be given when this frame is processed. - callback(EventFrame(eh, frame, 1)); - } - else { - // We must give 1 unit read credit per event. - // This event does not complete any frames so - // send an empty frame with the read credit. - callback(EventFrame(eh, framing::AMQFrame(), 1)); - } -} - -void Decoder::erase(const ConnectionId& c) { - sys::Mutex::ScopedLock l(lock); - map.erase(c); -} - -framing::FrameDecoder& Decoder::get(const ConnectionId& c) { - sys::Mutex::ScopedLock l(lock); - return map[c]; -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/Decoder.h b/cpp/src/qpid/cluster/Decoder.h deleted file mode 100644 index 3b5ada4a81..0000000000 --- a/cpp/src/qpid/cluster/Decoder.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef QPID_CLUSTER_DECODER_H -#define QPID_CLUSTER_DECODER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/types.h" -#include "qpid/framing/FrameDecoder.h" -#include "qpid/sys/Mutex.h" -#include <boost/function.hpp> -#include <map> - -namespace qpid { -namespace cluster { - -struct EventFrame; -class EventHeader; - -/** - * A map of decoders for connections. - */ -class Decoder -{ - public: - typedef boost::function<void(const EventFrame&)> FrameHandler; - - Decoder(FrameHandler fh) : callback(fh) {} - void decode(const EventHeader& eh, const char* data); - void erase(const ConnectionId&); - framing::FrameDecoder& get(const ConnectionId& c); - - private: - typedef std::map<ConnectionId, framing::FrameDecoder> Map; - sys::Mutex lock; - Map map; - void process(const EventFrame&); - FrameHandler callback; -}; -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_DECODER_H*/ diff --git a/cpp/src/qpid/cluster/Dispatchable.h b/cpp/src/qpid/cluster/Dispatchable.h deleted file mode 100644 index e7f0df4218..0000000000 --- a/cpp/src/qpid/cluster/Dispatchable.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_CLUSTER_DISPATCHABLE_H -#define QPID_CLUSTER_DISPATCHABLE_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -namespace qpid { -namespace cluster { - -/** - * Interface for classes that have some "events" that need dispatching - * in a thread. - */ -class Dispatchable -{ - public: - virtual ~Dispatchable() {} - - /** Dispatch one event in current thread. */ - virtual void dispatchOne() = 0; - /** Dispatch all available events, don't block. */ - virtual void dispatchAll() = 0; - /** Blocking loop to dispatch cluster events */ - virtual void dispatchBlocking() = 0; - - /** Wait for at least one event, then dispatch all available events. - * Don't block. Useful for tests. - */ - virtual void dispatchSome() { dispatchOne(); dispatchAll(); } - -}; - -}} // namespace qpid::cluster - - - -#endif /*!QPID_CLUSTER_DISPATCHABLE_H*/ diff --git a/cpp/src/qpid/cluster/ErrorCheck.cpp b/cpp/src/qpid/cluster/ErrorCheck.cpp deleted file mode 100644 index be671c0f48..0000000000 --- a/cpp/src/qpid/cluster/ErrorCheck.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/ErrorCheck.h" -#include "qpid/cluster/EventFrame.h" -#include "qpid/cluster/ClusterMap.h" -#include "qpid/cluster/Cluster.h" -#include "qpid/framing/ClusterErrorCheckBody.h" -#include "qpid/framing/ClusterConfigChangeBody.h" -#include "qpid/log/Statement.h" - -#include <algorithm> - -namespace qpid { -namespace cluster { - -using namespace std; -using namespace framing; -using namespace framing::cluster; - -ErrorCheck::ErrorCheck(Cluster& c) - : cluster(c), mcast(c.getMulticast()), frameSeq(0), type(ERROR_TYPE_NONE), connection(0) -{} - -void ErrorCheck::error( - Connection& c, ErrorType t, framing::SequenceNumber seq, const MemberSet& ms, - const std::string& msg) -{ - // Detected a local error, inform cluster and set error state. - assert(t != ERROR_TYPE_NONE); // Must be an error. - assert(type == ERROR_TYPE_NONE); // Can't be called when already in an error state. - type = t; - unresolved = ms; - frameSeq = seq; - connection = &c; - message = msg; - QPID_LOG(debug, cluster<< (type == ERROR_TYPE_SESSION ? " channel" : " connection") - << " error " << frameSeq << " on " << c - << " must be resolved with: " << unresolved - << ": " << message); - mcast.mcastControl( - ClusterErrorCheckBody(ProtocolVersion(), type, frameSeq), cluster.getId()); - // If there are already frames queued up by a previous error, review - // them with respect to this new error. - for (FrameQueue::iterator i = frames.begin(); i != frames.end(); i = review(i)) - ; -} - -void ErrorCheck::delivered(const EventFrame& e) { - frames.push_back(e); - review(frames.end()-1); -} - -// Review a frame in the queue with respect to the current error. -ErrorCheck::FrameQueue::iterator ErrorCheck::review(const FrameQueue::iterator& i) { - FrameQueue::iterator next = i+1; - if(!isUnresolved() || !i->frame.getBody() || !i->frame.getMethod()) - return next; // Only interested in control frames while unresolved. - const AMQMethodBody* method = i->frame.getMethod(); - if (method->isA<const ClusterErrorCheckBody>()) { - const ClusterErrorCheckBody* errorCheck = - static_cast<const ClusterErrorCheckBody*>(method); - - if (errorCheck->getFrameSeq() == frameSeq) { // Addresses current error - next = frames.erase(i); // Drop matching error check controls - if (errorCheck->getType() < type) { // my error is worse than his - QPID_LOG(critical, cluster - << " local error " << frameSeq << " did not occur on member " - << i->getMemberId() - << ": " << message); - throw Exception( - QPID_MSG("local error did not occur on all cluster members " << ": " << message)); - } - else { // his error is worse/same as mine. - QPID_LOG(debug, cluster << " error " << frameSeq - << " resolved with " << i->getMemberId()); - unresolved.erase(i->getMemberId()); - checkResolved(); - } - } - else if (errorCheck->getFrameSeq() < frameSeq && errorCheck->getType() != NONE - && i->connectionId.getMember() != cluster.getId()) - { - // This error occured before the current error so we - // have processed past it. - next = frames.erase(i); // Drop the error check control - respondNone(i->connectionId.getMember(), errorCheck->getType(), - errorCheck->getFrameSeq()); - } - // if errorCheck->getFrameSeq() > frameSeq then leave it in the queue. - } - else if (method->isA<const ClusterConfigChangeBody>()) { - const ClusterConfigChangeBody* configChange = - static_cast<const ClusterConfigChangeBody*>(method); - if (configChange) { - MemberSet members(decodeMemberSet(configChange->getMembers())); - QPID_LOG(debug, cluster << " apply config change to error " - << frameSeq << ": " << members); - MemberSet intersect; - set_intersection(members.begin(), members.end(), - unresolved.begin(), unresolved.end(), - inserter(intersect, intersect.begin())); - unresolved.swap(intersect); - checkResolved(); - } - } - return next; -} - -void ErrorCheck::checkResolved() { - if (unresolved.empty()) { // No more potentially conflicted members, we're clear. - type = ERROR_TYPE_NONE; - QPID_LOG(debug, cluster << " error " << frameSeq << " resolved."); - } - else - QPID_LOG(debug, cluster << " error " << frameSeq - << " must be resolved with " << unresolved); -} - -EventFrame ErrorCheck::getNext() { - assert(canProcess()); - EventFrame e(frames.front()); - frames.pop_front(); - return e; -} - -void ErrorCheck::respondNone(const MemberId& from, uint8_t type, framing::SequenceNumber frameSeq) { - // Don't respond to non-errors or to my own errors. - if (type == ERROR_TYPE_NONE || from == cluster.getId()) - return; - QPID_LOG(debug, cluster << " error " << frameSeq << " did not occur locally."); - mcast.mcastControl( - ClusterErrorCheckBody(ProtocolVersion(), ERROR_TYPE_NONE, frameSeq), - cluster.getId() - ); -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/ErrorCheck.h b/cpp/src/qpid/cluster/ErrorCheck.h deleted file mode 100644 index a417b2ec25..0000000000 --- a/cpp/src/qpid/cluster/ErrorCheck.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef QPID_CLUSTER_ERRORCHECK_H -#define QPID_CLUSTER_ERRORCHECK_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/MemberSet.h" -#include "qpid/cluster/Multicaster.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/SequenceNumber.h" -#include <boost/function.hpp> -#include <deque> -#include <set> - -namespace qpid { -namespace cluster { - -struct EventFrame; -class Cluster; -class Multicaster; -class Connection; - -/** - * Error checking logic. - * - * When an error occurs queue up frames until we can determine if all - * nodes experienced the error. If not, we shut down. - */ -class ErrorCheck -{ - public: - typedef framing::cluster::ErrorType ErrorType; - typedef framing::SequenceNumber SequenceNumber; - - ErrorCheck(Cluster&); - - /** A local error has occured */ - void error(Connection&, ErrorType, SequenceNumber frameSeq, const MemberSet&, - const std::string& msg); - - /** Called when a frame is delivered */ - void delivered(const EventFrame&); - - /**@pre canProcess **/ - EventFrame getNext(); - - bool canProcess() const { return type == NONE && !frames.empty(); } - - bool isUnresolved() const { return type != NONE; } - - /** Respond to an error check saying we had no error. */ - void respondNone(const MemberId&, uint8_t type, SequenceNumber frameSeq); - - private: - static const ErrorType NONE = framing::cluster::ERROR_TYPE_NONE; - typedef std::deque<EventFrame> FrameQueue; - FrameQueue::iterator review(const FrameQueue::iterator&); - void checkResolved(); - - Cluster& cluster; - Multicaster& mcast; - FrameQueue frames; - MemberSet unresolved; - SequenceNumber frameSeq; - ErrorType type; - Connection* connection; - std::string message; -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_ERRORCHECK_H*/ diff --git a/cpp/src/qpid/cluster/Event.cpp b/cpp/src/qpid/cluster/Event.cpp deleted file mode 100644 index da2bc89d8c..0000000000 --- a/cpp/src/qpid/cluster/Event.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/types.h" -#include "qpid/cluster/Event.h" -#include "qpid/cluster/Cpg.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/RefCountedBuffer.h" -#include "qpid/assert.h" -#include <ostream> -#include <iterator> -#include <algorithm> - -namespace qpid { -namespace cluster { - -using framing::Buffer; -using framing::AMQFrame; - -const size_t EventHeader::HEADER_SIZE = - sizeof(uint8_t) + // type - sizeof(uint64_t) + // connection pointer only, CPG provides member ID. - sizeof(uint32_t) // payload size - ; - -EventHeader::EventHeader(EventType t, const ConnectionId& c, size_t s) - : type(t), connectionId(c), size(s) {} - - -Event::Event() {} - -Event::Event(EventType t, const ConnectionId& c, size_t s) - : EventHeader(t,c,s), store(RefCountedBuffer::create(s+HEADER_SIZE)) -{} - -void EventHeader::decode(const MemberId& m, framing::Buffer& buf) { - QPID_ASSERT(buf.available() >= HEADER_SIZE); - type = (EventType)buf.getOctet(); - QPID_ASSERT(type == DATA || type == CONTROL); - connectionId = ConnectionId(m, buf.getLongLong()); - size = buf.getLong(); -} - -Event Event::decodeCopy(const MemberId& m, framing::Buffer& buf) { - Event e; - e.decode(m, buf); // Header - QPID_ASSERT(buf.available() >= e.size); - e.store = RefCountedBuffer::create(e.size + HEADER_SIZE); - memcpy(e.getData(), buf.getPointer() + buf.getPosition(), e.size); - return e; -} - -Event Event::control(const framing::AMQFrame& f, const ConnectionId& cid) { - Event e(CONTROL, cid, f.encodedSize()); - Buffer buf(e); - f.encode(buf); - return e; -} - -Event Event::control(const framing::AMQBody& body, const ConnectionId& cid) { - return control(framing::AMQFrame(body), cid); -} - -iovec Event::toIovec() const { - encodeHeader(); - iovec iov = { const_cast<char*>(getStore()), getStoreSize() }; - return iov; -} - -void EventHeader::encode(Buffer& b) const { - b.putOctet(type); - b.putLongLong(connectionId.getNumber()); - b.putLong(size); -} - -// Encode my header in my buffer. -void Event::encodeHeader () const { - Buffer b(const_cast<char*>(getStore()), HEADER_SIZE); - encode(b); - assert(b.getPosition() == HEADER_SIZE); -} - -Event::operator Buffer() const { - return Buffer(const_cast<char*>(getData()), getSize()); -} - -const AMQFrame& Event::getFrame() const { - assert(type == CONTROL); - if (!frame.getBody()) { - Buffer buf(*this); - QPID_ASSERT(frame.decode(buf)); - } - return frame; -} - -static const char* EVENT_TYPE_NAMES[] = { "data", "control" }; - -std::ostream& operator<< (std::ostream& o, EventType t) { - return o << EVENT_TYPE_NAMES[t]; -} - -std::ostream& operator<< (std::ostream& o, const EventHeader& e) { - return o << "Event[" << e.getConnectionId() << " " << e.getType() - << " " << e.getSize() << " bytes]"; -} - -std::ostream& operator<< (std::ostream& o, const Event& e) { - o << "Event[" << e.getConnectionId() << " "; - if (e.getType() == CONTROL) - o << e.getFrame(); - else - o << " data " << e.getSize() << " bytes"; - return o << "]"; -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/Event.h b/cpp/src/qpid/cluster/Event.h deleted file mode 100644 index 13283edff7..0000000000 --- a/cpp/src/qpid/cluster/Event.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef QPID_CLUSTER_EVENT_H -#define QPID_CLUSTER_EVENT_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/types.h" -#include "qpid/BufferRef.h" -#include "qpid/framing/AMQFrame.h" -#include <sys/uio.h> // For iovec -#include <iosfwd> - -#include "qpid/cluster/types.h" - -namespace qpid { - -namespace framing { -class AMQBody; -class AMQFrame; -class Buffer; -} - -namespace cluster { - -/** Header data for a multicast event */ -class EventHeader { - public: - EventHeader(EventType t=DATA, const ConnectionId& c=ConnectionId(), size_t size=0); - void decode(const MemberId& m, framing::Buffer&); - void encode(framing::Buffer&) const; - - EventType getType() const { return type; } - ConnectionId getConnectionId() const { return connectionId; } - MemberId getMemberId() const { return connectionId.getMember(); } - - /** Size of payload data, excluding header. */ - size_t getSize() const { return size; } - /** Size of header + payload. */ - size_t getStoreSize() const { return size + HEADER_SIZE; } - - bool isCluster() const { return connectionId.getNumber() == 0; } - bool isConnection() const { return connectionId.getNumber() != 0; } - bool isControl() const { return type == CONTROL; } - - protected: - static const size_t HEADER_SIZE; - - EventType type; - ConnectionId connectionId; - size_t size; -}; - -/** - * Events are sent to/received from the cluster. - * Refcounted so they can be stored on queues. - */ -class Event : public EventHeader { - public: - Event(); - /** Create an event with a buffer that can hold size bytes plus an event header. */ - Event(EventType t, const ConnectionId& c, size_t); - - /** Create an event copied from delivered data. */ - static Event decodeCopy(const MemberId& m, framing::Buffer&); - - /** Create a control event. */ - static Event control(const framing::AMQBody&, const ConnectionId&); - - /** Create a control event. */ - static Event control(const framing::AMQFrame&, const ConnectionId&); - - // Data excluding header. - char* getData() { return store.begin() + HEADER_SIZE; } - const char* getData() const { return store.begin() + HEADER_SIZE; } - - // Store including header - char* getStore() { return store.begin(); } - const char* getStore() const { return store.begin(); } - - const framing::AMQFrame& getFrame() const; - - operator framing::Buffer() const; - - iovec toIovec() const; - - private: - void encodeHeader() const; - - BufferRef store; - mutable framing::AMQFrame frame; -}; - -std::ostream& operator << (std::ostream&, const Event&); -std::ostream& operator << (std::ostream&, const EventHeader&); - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_EVENT_H*/ diff --git a/cpp/src/qpid/cluster/EventFrame.cpp b/cpp/src/qpid/cluster/EventFrame.cpp deleted file mode 100644 index 5fbe1fe57c..0000000000 --- a/cpp/src/qpid/cluster/EventFrame.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/EventFrame.h" -#include "qpid/cluster/Connection.h" - -namespace qpid { -namespace cluster { - -EventFrame::EventFrame() {} - -EventFrame::EventFrame(const EventHeader& e, const framing::AMQFrame& f, int rc) - : connectionId(e.getConnectionId()), frame(f), readCredit(rc), type(e.getType()) -{} - -std::ostream& operator<<(std::ostream& o, const EventFrame& e) { - if (e.frame.getBody()) o << e.frame; - else o << "null-frame"; - o << " " << e.type << " " << e.connectionId; - if (e.readCredit) o << " read-credit=" << e.readCredit; - return o; -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/EventFrame.h b/cpp/src/qpid/cluster/EventFrame.h deleted file mode 100644 index 6b702a9bf8..0000000000 --- a/cpp/src/qpid/cluster/EventFrame.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_CLUSTER_EVENTFRAME_H -#define QPID_CLUSTER_EVENTFRAME_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/types.h" -#include "qpid/cluster/Event.h" -#include "qpid/framing/AMQFrame.h" -#include <boost/intrusive_ptr.hpp> -#include <iosfwd> - -namespace qpid { -namespace cluster { - -/** - * A frame decoded from an Event. - */ -struct EventFrame -{ - public: - EventFrame(); - - EventFrame(const EventHeader& e, const framing::AMQFrame& f, int rc=0); - - bool isCluster() const { return connectionId.getNumber() == 0; } - bool isConnection() const { return connectionId.getNumber() != 0; } - bool isLastInEvent() const { return readCredit; } - MemberId getMemberId() const { return connectionId.getMember(); } - - - ConnectionId connectionId; - framing::AMQFrame frame; - int readCredit; ///< last frame in an event, give credit when processed. - EventType type; -}; - -std::ostream& operator<<(std::ostream& o, const EventFrame& e); - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_EVENTFRAME_H*/ diff --git a/cpp/src/qpid/cluster/ExpiryPolicy.cpp b/cpp/src/qpid/cluster/ExpiryPolicy.cpp deleted file mode 100644 index d9a7b0122a..0000000000 --- a/cpp/src/qpid/cluster/ExpiryPolicy.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Message.h" -#include "qpid/cluster/ExpiryPolicy.h" -#include "qpid/cluster/Multicaster.h" -#include "qpid/framing/ClusterMessageExpiredBody.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Timer.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace cluster { - -ExpiryPolicy::ExpiryPolicy(Multicaster& m, const MemberId& id, sys::Timer& t) - : expiryId(1), expiredPolicy(new Expired), mcast(m), memberId(id), timer(t) {} - -struct ExpiryTask : public sys::TimerTask { - ExpiryTask(const boost::intrusive_ptr<ExpiryPolicy>& policy, uint64_t id, sys::AbsTime when) - : TimerTask(when,"ExpiryPolicy"), expiryPolicy(policy), expiryId(id) {} - void fire() { expiryPolicy->sendExpire(expiryId); } - boost::intrusive_ptr<ExpiryPolicy> expiryPolicy; - const uint64_t expiryId; -}; - -// Called while receiving an update -void ExpiryPolicy::setId(uint64_t id) { - sys::Mutex::ScopedLock l(lock); - expiryId = id; -} - -// Called while giving an update -uint64_t ExpiryPolicy::getId() const { - sys::Mutex::ScopedLock l(lock); - return expiryId; -} - -// Called in enqueuing connection thread -void ExpiryPolicy::willExpire(broker::Message& m) { - uint64_t id; - { - // When messages are fanned out to multiple queues, update sends - // them as independenty messages so we can have multiple messages - // with the same expiry ID. - // - sys::Mutex::ScopedLock l(lock); - id = expiryId++; - if (!id) { // This is an update of an already-expired message. - m.setExpiryPolicy(expiredPolicy); - } - else { - assert(unexpiredByMessage.find(&m) == unexpiredByMessage.end()); - // If this is an update, the id may already exist - unexpiredById.insert(IdMessageMap::value_type(id, &m)); - unexpiredByMessage[&m] = id; - } - } - timer.add(new ExpiryTask(this, id, m.getExpiration())); -} - -// Called in dequeueing connection thread -void ExpiryPolicy::forget(broker::Message& m) { - sys::Mutex::ScopedLock l(lock); - MessageIdMap::iterator i = unexpiredByMessage.find(&m); - assert(i != unexpiredByMessage.end()); - unexpiredById.erase(i->second); - unexpiredByMessage.erase(i); -} - -// Called in dequeueing connection or cleanup thread. -bool ExpiryPolicy::hasExpired(broker::Message& m) { - sys::Mutex::ScopedLock l(lock); - return unexpiredByMessage.find(&m) == unexpiredByMessage.end(); -} - -// Called in timer thread -void ExpiryPolicy::sendExpire(uint64_t id) { - { - sys::Mutex::ScopedLock l(lock); - // Don't multicast an expiry notice if message is already forgotten. - if (unexpiredById.find(id) == unexpiredById.end()) return; - } - mcast.mcastControl(framing::ClusterMessageExpiredBody(framing::ProtocolVersion(), id), memberId); -} - -// Called in CPG deliver thread. -void ExpiryPolicy::deliverExpire(uint64_t id) { - sys::Mutex::ScopedLock l(lock); - std::pair<IdMessageMap::iterator, IdMessageMap::iterator> expired = unexpiredById.equal_range(id); - IdMessageMap::iterator i = expired.first; - while (i != expired.second) { - i->second->setExpiryPolicy(expiredPolicy); // hasExpired() == true; - unexpiredByMessage.erase(i->second); - unexpiredById.erase(i++); - } -} - -// Called in update thread on the updater. -boost::optional<uint64_t> ExpiryPolicy::getId(broker::Message& m) { - sys::Mutex::ScopedLock l(lock); - MessageIdMap::iterator i = unexpiredByMessage.find(&m); - return i == unexpiredByMessage.end() ? boost::optional<uint64_t>() : i->second; -} - -bool ExpiryPolicy::Expired::hasExpired(broker::Message&) { return true; } -void ExpiryPolicy::Expired::willExpire(broker::Message&) { } - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/ExpiryPolicy.h b/cpp/src/qpid/cluster/ExpiryPolicy.h deleted file mode 100644 index 77a656aa68..0000000000 --- a/cpp/src/qpid/cluster/ExpiryPolicy.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef QPID_CLUSTER_EXPIRYPOLICY_H -#define QPID_CLUSTER_EXPIRYPOLICY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/types.h" -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/sys/Mutex.h" -#include <boost/function.hpp> -#include <boost/intrusive_ptr.hpp> -#include <boost/optional.hpp> -#include <map> - -namespace qpid { - -namespace broker { -class Message; -} - -namespace sys { -class Timer; -} - -namespace cluster { -class Multicaster; - -/** - * Cluster expiry policy - */ -class ExpiryPolicy : public broker::ExpiryPolicy -{ - public: - ExpiryPolicy(Multicaster&, const MemberId&, sys::Timer&); - - void willExpire(broker::Message&); - bool hasExpired(broker::Message&); - void forget(broker::Message&); - - // Send expiration notice to cluster. - void sendExpire(uint64_t); - - // Cluster delivers expiry notice. - void deliverExpire(uint64_t); - - void setId(uint64_t id); - uint64_t getId() const; - - boost::optional<uint64_t> getId(broker::Message&); - - private: - typedef std::map<broker::Message*, uint64_t> MessageIdMap; - // When messages are fanned out to multiple queues, update sends - // them as independenty messages so we can have multiple messages - // with the same expiry ID. - typedef std::multimap<uint64_t, broker::Message*> IdMessageMap; - - struct Expired : public broker::ExpiryPolicy { - bool hasExpired(broker::Message&); - void willExpire(broker::Message&); - }; - - mutable sys::Mutex lock; - MessageIdMap unexpiredByMessage; - IdMessageMap unexpiredById; - uint64_t expiryId; - boost::intrusive_ptr<Expired> expiredPolicy; - Multicaster& mcast; - MemberId memberId; - sys::Timer& timer; -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_EXPIRYPOLICY_H*/ diff --git a/cpp/src/qpid/cluster/FailoverExchange.cpp b/cpp/src/qpid/cluster/FailoverExchange.cpp deleted file mode 100644 index 84232dac1b..0000000000 --- a/cpp/src/qpid/cluster/FailoverExchange.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/FailoverExchange.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/Queue.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/Array.h" -#include <boost/bind.hpp> -#include <algorithm> - -namespace qpid { -namespace cluster { -using namespace std; - -using namespace broker; -using namespace framing; - -const string FailoverExchange::typeName("amq.failover"); - -FailoverExchange::FailoverExchange(management::Manageable* parent, Broker* b) : Exchange(typeName, parent, b ) { - if (mgmtExchange != 0) - mgmtExchange->set_type(typeName); -} - -void FailoverExchange::setUrls(const vector<Url>& u) { - Lock l(lock); - urls = u; -} - -void FailoverExchange::updateUrls(const vector<Url>& u) { - Lock l(lock); - urls=u; - if (urls.empty()) return; - std::for_each(queues.begin(), queues.end(), - boost::bind(&FailoverExchange::sendUpdate, this, _1)); -} - -string FailoverExchange::getType() const { return typeName; } - -bool FailoverExchange::bind(Queue::shared_ptr queue, const string&, const framing::FieldTable*) { - Lock l(lock); - sendUpdate(queue); - return queues.insert(queue).second; -} - -bool FailoverExchange::unbind(Queue::shared_ptr queue, const string&, const framing::FieldTable*) { - Lock l(lock); - return queues.erase(queue); -} - -bool FailoverExchange::isBound(Queue::shared_ptr queue, const string* const, const framing::FieldTable*) { - Lock l(lock); - return queues.find(queue) != queues.end(); -} - -void FailoverExchange::route(Deliverable&, const string& , const framing::FieldTable* ) { - QPID_LOG(warning, "Message received by exchange " << typeName << " ignoring"); -} - -void FailoverExchange::sendUpdate(const Queue::shared_ptr& queue) { - // Called with lock held. - if (urls.empty()) return; - framing::Array array(0x95); - for (Urls::const_iterator i = urls.begin(); i != urls.end(); ++i) - array.add(boost::shared_ptr<Str16Value>(new Str16Value(i->str()))); - const ProtocolVersion v; - boost::intrusive_ptr<Message> msg(new Message); - AMQFrame command(MessageTransferBody(v, typeName, 1, 0)); - command.setLastSegment(false); - msg->getFrames().append(command); - AMQHeaderBody header; - header.get<MessageProperties>(true)->setContentLength(0); - header.get<MessageProperties>(true)->getApplicationHeaders().setArray(typeName, array); - AMQFrame headerFrame(header); - headerFrame.setFirstSegment(false); - msg->getFrames().append(headerFrame); - DeliverableMessage(msg).deliverTo(queue); -} - - -}} // namespace cluster diff --git a/cpp/src/qpid/cluster/FailoverExchange.h b/cpp/src/qpid/cluster/FailoverExchange.h deleted file mode 100644 index 2e1edfc0ae..0000000000 --- a/cpp/src/qpid/cluster/FailoverExchange.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef QPID_CLUSTER_FAILOVEREXCHANGE_H -#define QPID_CLUSTER_FAILOVEREXCHANGE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Exchange.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/Url.h" - -#include <vector> -#include <set> - -namespace qpid { -namespace cluster { - -/** - * Failover exchange provides failover host list, as specified in AMQP 0-10. - */ -class FailoverExchange : public broker::Exchange -{ - public: - static const std::string typeName; - - FailoverExchange(management::Manageable* parent, broker::Broker* b); - - /** Set the URLs but don't send an update.*/ - void setUrls(const std::vector<Url>&); - /** Set the URLs and send an update.*/ - void updateUrls(const std::vector<Url>&); - - // Exchange overrides - std::string getType() const; - bool bind(boost::shared_ptr<broker::Queue> queue, const std::string& routingKey, const framing::FieldTable* args); - bool unbind(boost::shared_ptr<broker::Queue> queue, const std::string& routingKey, const framing::FieldTable* args); - bool isBound(boost::shared_ptr<broker::Queue> queue, const std::string* const routingKey, const framing::FieldTable* const args); - void route(broker::Deliverable& msg, const std::string& routingKey, const framing::FieldTable* args); - - private: - void sendUpdate(const boost::shared_ptr<broker::Queue>&); - - typedef sys::Mutex::ScopedLock Lock; - typedef std::vector<Url> Urls; - typedef std::set<boost::shared_ptr<broker::Queue> > Queues; - - sys::Mutex lock; - Urls urls; - Queues queues; - -}; -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_FAILOVEREXCHANGE_H*/ diff --git a/cpp/src/qpid/cluster/InitialStatusMap.cpp b/cpp/src/qpid/cluster/InitialStatusMap.cpp deleted file mode 100644 index c8ecc13f2c..0000000000 --- a/cpp/src/qpid/cluster/InitialStatusMap.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "InitialStatusMap.h" -#include "StoreStatus.h" -#include "qpid/log/Statement.h" -#include <algorithm> -#include <vector> -#include <boost/bind.hpp> - -namespace qpid { -namespace cluster { - -using namespace std; -using namespace boost; -using namespace framing::cluster; -using namespace framing; - -InitialStatusMap::InitialStatusMap(const MemberId& self_, size_t size_) - : self(self_), completed(), resendNeeded(), size(size_) -{} - -void InitialStatusMap::configChange(const MemberSet& members) { - resendNeeded = false; - bool wasComplete = isComplete(); - if (firstConfig.empty()) firstConfig = members; - MemberSet::const_iterator i = members.begin(); - Map::iterator j = map.begin(); - while (i != members.end() || j != map.end()) { - if (i == members.end()) { // j not in members, member left - firstConfig.erase(j->first); - Map::iterator k = j++; - map.erase(k); - } - else if (j == map.end()) { // i not in map, member joined - resendNeeded = true; - map[*i] = optional<Status>(); - ++i; - } - else if (*i < j->first) { // i not in map, member joined - resendNeeded = true; - map[*i] = optional<Status>(); - ++i; - } - else if (*i > j->first) { // j not in members, member left - firstConfig.erase(j->first); - Map::iterator k = j++; - map.erase(k); - } - else { - i++; j++; - } - } - if (resendNeeded) { // Clear all status - for (Map::iterator i = map.begin(); i != map.end(); ++i) - i->second = optional<Status>(); - } - completed = isComplete() && !wasComplete; // Set completed on the transition. -} - -void InitialStatusMap::received(const MemberId& m, const Status& s){ - bool wasComplete = isComplete(); - map[m] = s; - completed = isComplete() && !wasComplete; // Set completed on the transition. -} - -bool InitialStatusMap::notInitialized(const Map::value_type& v) { - return !v.second; -} - -bool InitialStatusMap::isComplete() const { - return !map.empty() && find_if(map.begin(), map.end(), ¬Initialized) == map.end(); -} - -bool InitialStatusMap::transitionToComplete() { - return completed; -} - -bool InitialStatusMap::isResendNeeded() { - bool ret = resendNeeded; - resendNeeded = false; - return ret; -} - -bool InitialStatusMap::isActiveEntry(const Map::value_type& v) { - return v.second && v.second->getActive(); -} - -bool InitialStatusMap::hasStore(const Map::value_type& v) { - return v.second && - (v.second->getStoreState() == STORE_STATE_CLEAN_STORE || - v.second->getStoreState() == STORE_STATE_DIRTY_STORE); -} - -bool InitialStatusMap::isActive() { - assert(isComplete()); - return (find_if(map.begin(), map.end(), &isActiveEntry) != map.end()); -} - -bool InitialStatusMap::isUpdateNeeded() { - assert(isComplete()); - // We need an update if there are any active members. - if (isActive()) return true; - - // Otherwise it depends on store status, get my own status: - Map::iterator me = map.find(self); - assert(me != map.end()); - assert(me->second); - switch (me->second->getStoreState()) { - case STORE_STATE_NO_STORE: - case STORE_STATE_EMPTY_STORE: - // If anybody has a store then we need an update. - return find_if(map.begin(), map.end(), &hasStore) != map.end(); - case STORE_STATE_DIRTY_STORE: return true; - case STORE_STATE_CLEAN_STORE: return false; // Use our own store - } - return false; -} - -MemberSet InitialStatusMap::getElders() const { - assert(isComplete()); - MemberSet elders; - for (MemberSet::const_iterator i = firstConfig.begin(); i != firstConfig.end(); ++i) { - // *i is in my first config, so a potential elder. - if (*i == self) continue; // Not my own elder - Map::const_iterator j = map.find(*i); - assert(j != map.end()); - assert(j->second); - const Status& s = *j->second; - // If I'm not in i's first config then i is older than me. - // Otherwise we were born in the same configuration so use - // member ID to break the tie. - MemberSet iFirstConfig = decodeMemberSet(s.getFirstConfig()); - if (iFirstConfig.find(self) == iFirstConfig.end() || *i > self) - elders.insert(*i); - } - return elders; -} - -// Get cluster ID from an active member or the youngest newcomer. -Uuid InitialStatusMap::getClusterId() { - assert(isComplete()); - assert(!map.empty()); - Map::iterator i = find_if(map.begin(), map.end(), &isActiveEntry); - if (i != map.end()) - return i->second->getClusterId(); // An active member - else - return map.begin()->second->getClusterId(); // Youngest newcomer in node-id order -} - -void checkId(Uuid& expect, const Uuid& actual, const string& msg) { - if (!expect) expect = actual; - assert(expect); - if (expect != actual) - throw Exception(msg); -} - -void InitialStatusMap::checkConsistent() { - assert(isComplete()); - int clean = 0; - int dirty = 0; - int empty = 0; - int none = 0; - int active = 0; - Uuid clusterId; - Uuid shutdownId; - - bool initialCluster = !isActive(); - for (Map::iterator i = map.begin(); i != map.end(); ++i) { - assert(i->second); - if (i->second->getActive()) ++active; - switch (i->second->getStoreState()) { - case STORE_STATE_NO_STORE: ++none; break; - case STORE_STATE_EMPTY_STORE: ++empty; break; - case STORE_STATE_DIRTY_STORE: - ++dirty; - checkId(clusterId, i->second->getClusterId(), - "Cluster-ID mismatch. Stores belong to different clusters."); - break; - case STORE_STATE_CLEAN_STORE: - ++clean; - checkId(clusterId, i->second->getClusterId(), - "Cluster-ID mismatch. Stores belong to different clusters."); - // Only need shutdownId to match if we are in an initially forming cluster. - if (initialCluster) - checkId(shutdownId, i->second->getShutdownId(), - "Shutdown-ID mismatch. Stores were not shut down together"); - break; - } - } - // Can't mix transient and persistent members. - if (none && (clean+dirty+empty)) - throw Exception("Mixing transient and persistent brokers in a cluster"); - - if (map.size() >= size) { - // All initial members are present. If there are no active - // members and there are dirty stores there must be at least - // one clean store. - if (!active && dirty && !clean) - throw Exception("Cannot recover, no clean store."); - } -} - -std::string InitialStatusMap::getFirstConfigStr() const { - assert(!firstConfig.empty()); - return encodeMemberSet(firstConfig); -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/InitialStatusMap.h b/cpp/src/qpid/cluster/InitialStatusMap.h deleted file mode 100644 index a5a600365e..0000000000 --- a/cpp/src/qpid/cluster/InitialStatusMap.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef QPID_CLUSTER_INITIALSTATUSMAP_H -#define QPID_CLUSTER_INITIALSTATUSMAP_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "MemberSet.h" -#include <qpid/framing/ClusterInitialStatusBody.h> -#include <boost/optional.hpp> - -namespace qpid { -namespace cluster { - -/** - * Track status of cluster members during initialization. - * - * When a new member joins the CPG cluster, all members send an initial-status - * control. This map tracks those controls and provides data to make descisions - * about joining the cluster. - * - */ -class InitialStatusMap -{ - public: - typedef framing::ClusterInitialStatusBody Status; - - InitialStatusMap(const MemberId& self, size_t size); - /** Process a config change. May make isResendNeeded() true. */ - void configChange(const MemberSet& newConfig); - /** @return true if we need to re-send status */ - bool isResendNeeded(); - - /** Process received status */ - void received(const MemberId&, const Status& is); - - /**@return true if the map has an entry for all current cluster members. */ - bool isComplete() const; - - size_t getActualSize() const { return map.size(); } - size_t getRequiredSize() const { return size; } - - /**@return true if the map was completed by the last config change or received. */ - bool transitionToComplete(); - /**@pre isComplete(). @return this node's elders */ - MemberSet getElders() const; - /**@pre isComplete(). @return True if there are active members of the cluster. */ - bool isActive(); - /**@pre isComplete(). @return True if we need to request an update. */ - bool isUpdateNeeded(); - /**@pre isComplete(). @return Cluster-wide cluster ID. */ - framing::Uuid getClusterId(); - /**@pre isComplete(). @throw Exception if there are any inconsistencies. */ - void checkConsistent(); - - /** Get first config-change for this member, encoded as a string. - *@pre configChange has been called at least once. - */ - std::string getFirstConfigStr() const; - private: - typedef std::map<MemberId, boost::optional<Status> > Map; - static bool notInitialized(const Map::value_type&); - static bool isActiveEntry(const Map::value_type&); - static bool hasStore(const Map::value_type&); - - Map map; - MemberSet firstConfig; - MemberId self; - bool completed, resendNeeded; - size_t size; -}; -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_INITIALSTATUSMAP_H*/ diff --git a/cpp/src/qpid/cluster/LockedConnectionMap.h b/cpp/src/qpid/cluster/LockedConnectionMap.h deleted file mode 100644 index ac744d4f94..0000000000 --- a/cpp/src/qpid/cluster/LockedConnectionMap.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef QPID_CLUSTER_LOCKEDCONNECTIONMAP_H -#define QPID_CLUSTER_LOCKEDCONNECTIONMAP_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/types.h" -#include "qpid/sys/Mutex.h" -#include "qpid/cluster/Connection.h" - -namespace qpid { -namespace cluster { - -/** - * Thread safe map of connections. - */ -class LockedConnectionMap -{ - public: - void insert(const ConnectionPtr& c) { - sys::Mutex::ScopedLock l(lock); - assert(map.find(c->getId()) == map.end()); - map[c->getId()] = c; - } - - ConnectionPtr getErase(const ConnectionId& c) { - sys::Mutex::ScopedLock l(lock); - Map::iterator i = map.find(c); - if (i != map.end()) { - ConnectionPtr cp = i->second; - map.erase(i); - return cp; - } - else - return 0; - } - - void clear() { sys::Mutex::ScopedLock l(lock); map.clear(); } - - private: - typedef std::map<ConnectionId, ConnectionPtr> Map; - mutable sys::Mutex lock; - Map map; -}; -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_LOCKEDCONNECTIONMAP_H*/ diff --git a/cpp/src/qpid/cluster/McastFrameHandler.h b/cpp/src/qpid/cluster/McastFrameHandler.h deleted file mode 100644 index 17e4c2e9f0..0000000000 --- a/cpp/src/qpid/cluster/McastFrameHandler.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef QPID_CLUSTER_MCASTFRAMEHANDLER_H -#define QPID_CLUSTER_MCASTFRAMEHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/types.h" -#include "qpid/cluster/Multicaster.h" -#include "qpid/framing/FrameHandler.h" - -namespace qpid { -namespace cluster { - -/** - * A frame handler that multicasts frames as CONTROL events. - */ -class McastFrameHandler : public framing::FrameHandler -{ - public: - McastFrameHandler(Multicaster& m, const ConnectionId& cid) : mcast(m), connection(cid) {} - void handle(framing::AMQFrame& frame) { mcast.mcastControl(frame, connection); } - private: - Multicaster& mcast; - ConnectionId connection; -}; -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_MCASTFRAMEHANDLER_H*/ diff --git a/cpp/src/qpid/cluster/MemberSet.cpp b/cpp/src/qpid/cluster/MemberSet.cpp deleted file mode 100644 index 97748947b3..0000000000 --- a/cpp/src/qpid/cluster/MemberSet.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "MemberSet.h" -#include <ostream> -#include <iterator> -#include <algorithm> - -namespace qpid { -namespace cluster { - -std::string encodeMemberSet(const MemberSet& m) { - std::string addresses; - for (MemberSet::const_iterator i = m.begin(); i != m.end(); ++i) - addresses.append(i->str()); - return addresses; -} - -MemberSet decodeMemberSet(const std::string& s) { - MemberSet set; - for (std::string::const_iterator i = s.begin(); i < s.end(); i += 8) { - assert(size_t(i-s.begin())+8 <= s.size()); - set.insert(MemberId(std::string(i, i+8))); - } - return set; -} - -MemberSet intersection(const MemberSet& a, const MemberSet& b) -{ - MemberSet intersection; - std::set_intersection(a.begin(), a.end(), - b.begin(), b.end(), - std::inserter(intersection, intersection.begin())); - return intersection; - -} - -std::ostream& operator<<(std::ostream& o, const MemberSet& ms) { - copy(ms.begin(), ms.end(), std::ostream_iterator<MemberId>(o, " ")); - return o; -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/MemberSet.h b/cpp/src/qpid/cluster/MemberSet.h deleted file mode 100644 index 7c97145dc1..0000000000 --- a/cpp/src/qpid/cluster/MemberSet.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_CLUSTER_MEMBERSET_H -#define QPID_CLUSTER_MEMBERSET_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "types.h" -#include <set> -#include <iosfwd> - -namespace qpid { -namespace cluster { - -typedef std::set<MemberId> MemberSet; - -std::string encodeMemberSet(const MemberSet&); - -MemberSet decodeMemberSet(const std::string&); - -MemberSet intersection(const MemberSet& a, const MemberSet& b); - -std::ostream& operator<<(std::ostream& o, const MemberSet& ms); - - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_MEMBERSET_H*/ diff --git a/cpp/src/qpid/cluster/Multicaster.cpp b/cpp/src/qpid/cluster/Multicaster.cpp deleted file mode 100644 index 8916de9628..0000000000 --- a/cpp/src/qpid/cluster/Multicaster.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/Multicaster.h" -#include "qpid/cluster/Cpg.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/AMQFrame.h" - -namespace qpid { -namespace cluster { - -Multicaster::Multicaster(Cpg& cpg_, - const boost::shared_ptr<sys::Poller>& poller, - boost::function<void()> onError_) : - onError(onError_), cpg(cpg_), - queue(boost::bind(&Multicaster::sendMcast, this, _1), poller), - ready(false), bypass(true) -{} - -void Multicaster::mcastControl(const framing::AMQBody& body, const ConnectionId& id) { - mcast(Event::control(body, id)); -} - -void Multicaster::mcastControl(const framing::AMQFrame& frame, const ConnectionId& id) { - mcast(Event::control(frame, id)); -} - -void Multicaster::mcastBuffer(const char* data, size_t size, const ConnectionId& id) { - Event e(DATA, id, size); - memcpy(e.getData(), data, size); - mcast(e); -} - -void Multicaster::mcast(const Event& e) { - { - sys::Mutex::ScopedLock l(lock); - if (!ready && e.isConnection()) { - holdingQueue.push_back(e); - return; - } - } - QPID_LOG(trace, "MCAST " << e); - if (bypass) { // direct, don't queue - iovec iov = e.toIovec(); - while (!cpg.mcast(&iov, 1)) - ; - } - else - queue.push(e); -} - -Multicaster::PollableEventQueue::Batch::const_iterator Multicaster::sendMcast(const PollableEventQueue::Batch& values) { - try { - PollableEventQueue::Batch::const_iterator i = values.begin(); - while( i != values.end()) { - iovec iov = i->toIovec(); - if (!cpg.mcast(&iov, 1)) { - // cpg didn't send because of CPG flow control. - break; - } - ++i; - } - return i; - } - catch (const std::exception& e) { - QPID_LOG(critical, "Multicast error: " << e.what()); - queue.stop(); - onError(); - return values.end(); - } -} - -void Multicaster::start() { - queue.start(); - bypass = false; -} - -void Multicaster::setReady() { - sys::Mutex::ScopedLock l(lock); - ready = true; - std::for_each(holdingQueue.begin(), holdingQueue.end(), boost::bind(&Multicaster::mcast, this, _1)); - holdingQueue.clear(); -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/Multicaster.h b/cpp/src/qpid/cluster/Multicaster.h deleted file mode 100644 index f70bd5ca31..0000000000 --- a/cpp/src/qpid/cluster/Multicaster.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef QPID_CLUSTER_MULTICASTER_H -#define QPID_CLUSTER_MULTICASTER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/types.h" -#include "qpid/cluster/Event.h" -#include "qpid/sys/PollableQueue.h" -#include "qpid/sys/Mutex.h" -#include <boost/shared_ptr.hpp> -#include <deque> - -namespace qpid { - -namespace sys { -class Poller; -} - -namespace cluster { - -class Cpg; - -/** - * Multicast to the cluster. Shared, thread safe object. - * - * holding mode: Hold connection events for later multicast. Cluster - * events are never held. Used during PRE_INIT/INIT state when we - * want to hold any connection traffic till we are read in the - * cluster. - * - * bypass mode: Multicast cluster events directly in the calling - * thread. This mode is used by cluster in PRE_INIT state the poller - * is not yet be active. - * - * Multicaster is created in bypass+holding mode, they are disabled by - * start and setReady respectively. - */ -class Multicaster -{ - public: - /** Starts in initializing mode. */ - Multicaster(Cpg& cpg_, - const boost::shared_ptr<sys::Poller>&, - boost::function<void()> onError - ); - void mcastControl(const framing::AMQBody& controlBody, const ConnectionId&); - void mcastControl(const framing::AMQFrame& controlFrame, const ConnectionId&); - void mcastBuffer(const char*, size_t, const ConnectionId&); - void mcast(const Event& e); - - /** Start the pollable queue, turn off bypass mode. */ - void start(); - /** Switch to ready mode, release held messages. */ - void setReady(); - - private: - typedef sys::PollableQueue<Event> PollableEventQueue; - typedef std::deque<Event> PlainEventQueue; - - PollableEventQueue::Batch::const_iterator sendMcast(const PollableEventQueue::Batch& ); - - sys::Mutex lock; - boost::function<void()> onError; - Cpg& cpg; - PollableEventQueue queue; - bool ready; - PlainEventQueue holdingQueue; - std::vector<struct ::iovec> ioVector; - bool bypass; -}; -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_MULTICASTER_H*/ diff --git a/cpp/src/qpid/cluster/NoOpConnectionOutputHandler.h b/cpp/src/qpid/cluster/NoOpConnectionOutputHandler.h deleted file mode 100644 index 566a82476e..0000000000 --- a/cpp/src/qpid/cluster/NoOpConnectionOutputHandler.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_CLUSTER_NOOPCONNECTIONOUTPUTHANDLER_H -#define QPID_CLUSTER_NOOPCONNECTIONOUTPUTHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <qpid/sys/ConnectionOutputHandler.h> - -namespace qpid { - -namespace framing { class AMQFrame; } - -namespace cluster { - -/** - * Output handler shadow connections, simply discards frames. - */ -class NoOpConnectionOutputHandler : public sys::ConnectionOutputHandler -{ - public: - virtual void send(framing::AMQFrame&) {} - virtual void close() {} - virtual void abort() {} - virtual void activateOutput() {} - virtual void giveReadCredit(int32_t) {} -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_NOOPCONNECTIONOUTPUTHANDLER_H*/ diff --git a/cpp/src/qpid/cluster/Numbering.h b/cpp/src/qpid/cluster/Numbering.h deleted file mode 100644 index 99e152c212..0000000000 --- a/cpp/src/qpid/cluster/Numbering.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_CLUSTER_NUMBERING_H -#define QPID_CLUSTER_NUMBERING_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <map> -#include <vector> - -namespace qpid { -namespace cluster { - -/** - * A set of numbered T, with two way mapping number->T T->number - * Used to construct numberings of objects by code sending and receiving updates. - */ -template <class T> class Numbering -{ - public: - size_t size() const { return byNumber.size(); } - - size_t add(const T& t) { - size_t n = (*this)[t]; // Already in the set? - if (n == size()) { - byObject[t] = n; - byNumber.push_back(t); - } - return n; - } - - void clear() { byObject.clear(); byNumber.clear(); } - - /**@return object at index n or T() if n > size() */ - T operator[](size_t n) const { return(n < size()) ? byNumber[n] : T(); } - - /**@return index of t or size() if t is not in the map */ - size_t operator[](const T& t) const { - typename Map::const_iterator i = byObject.find(t); - return (i != byObject.end()) ? i->second : size(); - } - - private: - typedef std::map<T, size_t> Map; - Map byObject; - std::vector<T> byNumber; -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_NUMBERING_H*/ diff --git a/cpp/src/qpid/cluster/OutputInterceptor.cpp b/cpp/src/qpid/cluster/OutputInterceptor.cpp deleted file mode 100644 index 4bf03eefa2..0000000000 --- a/cpp/src/qpid/cluster/OutputInterceptor.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/OutputInterceptor.h" -#include "qpid/cluster/Connection.h" -#include "qpid/cluster/Cluster.h" -#include "qpid/framing/ClusterConnectionDeliverDoOutputBody.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/log/Statement.h" -#include <boost/current_function.hpp> - - -namespace qpid { -namespace cluster { - -using namespace framing; -using namespace std; - -NoOpConnectionOutputHandler OutputInterceptor::discardHandler; - -OutputInterceptor::OutputInterceptor(Connection& p, sys::ConnectionOutputHandler& h) - : parent(p), closing(false), next(&h), sendMax(2048), sent(0), sentDoOutput(false) -{} - -void OutputInterceptor::send(framing::AMQFrame& f) { - sys::Mutex::ScopedLock l(lock); - next->send(f); -} - -void OutputInterceptor::activateOutput() { - sys::Mutex::ScopedLock l(lock); - if (parent.isCatchUp()) - next->activateOutput(); - else - sendDoOutput(sendMax, l); -} - -void OutputInterceptor::abort() { - sys::Mutex::ScopedLock l(lock); - if (parent.isLocal()) { - next->abort(); - } -} - -void OutputInterceptor::giveReadCredit(int32_t credit) { - sys::Mutex::ScopedLock l(lock); - next->giveReadCredit(credit); -} - -// Called in write thread when the IO layer has no more data to write. -// We only process IO callbacks in the write thread during catch-up. -// Normally we run doOutput only on delivery of doOutput requests. -bool OutputInterceptor::doOutput() { - parent.doCatchupIoCallbacks(); - return false; -} - -// Send output up to limit, calculate new limit. -void OutputInterceptor::deliverDoOutput(uint32_t limit) { - sys::Mutex::ScopedLock l(lock); - sentDoOutput = false; - sendMax = limit; - size_t newLimit = limit; - if (parent.isLocal()) { - size_t buffered = next->getBuffered(); - if (buffered == 0 && sent == sendMax) // Could have sent more, increase the limit. - newLimit = sendMax*2; - else if (buffered > 0 && sent > 1) // Data left unsent, reduce the limit. - newLimit = (sendMax + sent) / 2; - } - sent = 0; - while (sent < limit) { - { - sys::Mutex::ScopedUnlock u(lock); - if (!parent.getBrokerConnection()->doOutput()) break; - } - ++sent; - } - if (sent == limit) sendDoOutput(newLimit, l); -} - -void OutputInterceptor::sendDoOutput(size_t newLimit, const sys::Mutex::ScopedLock&) { - if (parent.isLocal() && !sentDoOutput && !closing) { - sentDoOutput = true; - parent.getCluster().getMulticast().mcastControl( - ClusterConnectionDeliverDoOutputBody(ProtocolVersion(), newLimit), - parent.getId()); - } -} - -// Called in connection thread when local connection closes. -void OutputInterceptor::closeOutput() { - sys::Mutex::ScopedLock l(lock); - closing = true; - next = &discardHandler; -} - -void OutputInterceptor::close() { - sys::Mutex::ScopedLock l(lock); - next->close(); -} - -size_t OutputInterceptor::getBuffered() const { - sys::Mutex::ScopedLock l(lock); - return next->getBuffered(); -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/OutputInterceptor.h b/cpp/src/qpid/cluster/OutputInterceptor.h deleted file mode 100644 index 3abf5273a0..0000000000 --- a/cpp/src/qpid/cluster/OutputInterceptor.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef QPID_CLUSTER_OUTPUTINTERCEPTOR_H -#define QPID_CLUSTER_OUTPUTINTERCEPTOR_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/NoOpConnectionOutputHandler.h" -#include "qpid/sys/ConnectionOutputHandler.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/ConnectionFactory.h" -#include <boost/function.hpp> - -namespace qpid { -namespace framing { class AMQFrame; } -namespace cluster { - -class Connection; - -/** - * Interceptor for connection OutputHandler, manages outgoing message replication. - */ -class OutputInterceptor : public sys::ConnectionOutputHandler { - public: - OutputInterceptor(cluster::Connection& p, sys::ConnectionOutputHandler& h); - - // sys::ConnectionOutputHandler functions - void send(framing::AMQFrame& f); - void abort(); - void activateOutput(); - void giveReadCredit(int32_t); - void close(); - size_t getBuffered() const; - - // Delivery point for doOutput requests. - void deliverDoOutput(uint32_t limit); - // Intercept doOutput requests on Connection. - bool doOutput(); - - void closeOutput(); - - uint32_t getSendMax() const { return sendMax; } - void setSendMax(uint32_t sendMax_) { sendMax=sendMax_; } - - cluster::Connection& parent; - - private: - typedef sys::Mutex::ScopedLock Locker; - - void sendDoOutput(size_t newLimit, const sys::Mutex::ScopedLock&); - - mutable sys::Mutex lock; - bool closing; - sys::ConnectionOutputHandler* next; - static NoOpConnectionOutputHandler discardHandler; - uint32_t sendMax, sent; - bool sentDoOutput; -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_OUTPUTINTERCEPTOR_H*/ diff --git a/cpp/src/qpid/cluster/PollableQueue.h b/cpp/src/qpid/cluster/PollableQueue.h deleted file mode 100644 index 10e2ed6ac3..0000000000 --- a/cpp/src/qpid/cluster/PollableQueue.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef QPID_CLUSTER_POLLABLEQUEUE_H -#define QPID_CLUSTER_POLLABLEQUEUE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/PollableQueue.h" -#include <qpid/log/Statement.h> - -namespace qpid { -namespace cluster { - -/** - * More convenient version of PollableQueue that handles iterating - * over the batch and error handling. - * - * Constructed in "bypass" mode where items are processed directly - * rather than put on the queue. This is important for the - * PRE_INIT stage when Cluster is pumping CPG dispatch directly - * before the poller has started. - * - * Calling start() starts the pollable queue and disabled bypass mode. - */ -template <class T> class PollableQueue : public sys::PollableQueue<T> { - public: - typedef boost::function<void (const T&)> Callback; - typedef boost::function<void()> ErrorCallback; - - PollableQueue(Callback f, ErrorCallback err, const std::string& msg, - const boost::shared_ptr<sys::Poller>& poller) - : sys::PollableQueue<T>(boost::bind(&PollableQueue<T>::handleBatch, this, _1), - poller), - callback(f), error(err), message(msg), bypass(true) - {} - - typename sys::PollableQueue<T>::Batch::const_iterator - handleBatch(const typename sys::PollableQueue<T>::Batch& values) { - try { - typename sys::PollableQueue<T>::Batch::const_iterator i = values.begin(); - while (i != values.end() && !this->isStopped()) { - callback(*i); - ++i; - } - return i; - } - catch (const std::exception& e) { - QPID_LOG(critical, message << ": " << e.what()); - this->stop(); - error(); - return values.end(); - } - } - - void push(const T& t) { - if (bypass) callback(t); - else sys::PollableQueue<T>::push(t); - } - - void bypassOff() { bypass = false; } - - private: - Callback callback; - ErrorCallback error; - std::string message; - bool bypass; -}; - - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_POLLABLEQUEUE_H*/ diff --git a/cpp/src/qpid/cluster/PollerDispatch.cpp b/cpp/src/qpid/cluster/PollerDispatch.cpp deleted file mode 100644 index b8d94b95a5..0000000000 --- a/cpp/src/qpid/cluster/PollerDispatch.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/PollerDispatch.h" - -#include "qpid/log/Statement.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace cluster { - -PollerDispatch::PollerDispatch(Cpg& c, boost::shared_ptr<sys::Poller> p, - boost::function<void()> e) - : cpg(c), poller(p), onError(e), - dispatchHandle(cpg, - boost::bind(&PollerDispatch::dispatch, this, _1), // read - 0, // write - boost::bind(&PollerDispatch::disconnect, this, _1) // disconnect - ), - started(false) -{} - -PollerDispatch::~PollerDispatch() { - if (started) - dispatchHandle.stopWatch(); -} - -void PollerDispatch::start() { - dispatchHandle.startWatch(poller); - started = true; -} - -// Entry point: called by IO to dispatch CPG events. -void PollerDispatch::dispatch(sys::DispatchHandle& h) { - try { - cpg.dispatchAll(); - h.rewatch(); - } catch (const std::exception& e) { - QPID_LOG(critical, "Error in cluster dispatch: " << e.what()); - onError(); - } -} - -// Entry point: called if disconnected from CPG. -void PollerDispatch::disconnect(sys::DispatchHandle& ) { - if (!poller->hasShutdown()) { - QPID_LOG(critical, "Disconnected from cluster"); - onError(); - } -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/PollerDispatch.h b/cpp/src/qpid/cluster/PollerDispatch.h deleted file mode 100644 index 63801e0de9..0000000000 --- a/cpp/src/qpid/cluster/PollerDispatch.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_CLUSTER_POLLERDISPATCH_H -#define QPID_CLUSTER_POLLERDISPATCH_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/Cpg.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/DispatchHandle.h" -#include <boost/function.hpp> - -namespace qpid { -namespace cluster { - -/** - * Dispatch CPG events via the poller. - */ -class PollerDispatch { - public: - PollerDispatch(Cpg&, boost::shared_ptr<sys::Poller> poller, - boost::function<void()> onError) ; - - ~PollerDispatch(); - - void start(); - - private: - // Poller callbacks - void dispatch(sys::DispatchHandle&); // Dispatch CPG events. - void disconnect(sys::DispatchHandle&); // CPG was disconnected - - Cpg& cpg; - boost::shared_ptr<sys::Poller> poller; - boost::function<void()> onError; - sys::DispatchHandleRef dispatchHandle; - bool started; - - -}; -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_POLLERDISPATCH_H*/ diff --git a/cpp/src/qpid/cluster/ProxyInputHandler.h b/cpp/src/qpid/cluster/ProxyInputHandler.h deleted file mode 100644 index ad7f2c44bd..0000000000 --- a/cpp/src/qpid/cluster/ProxyInputHandler.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef QPID_CLUSTER_PROXYINPUTHANDLER_H -#define QPID_CLUSTER_PROXYINPUTHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ConnectionInputHandler.h" -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - -namespace framing { class AMQFrame; } - -namespace cluster { - -/** - * Proxies ConnectionInputHandler functions and ensures target.closed() - * is called, on deletion if not before. - */ -class ProxyInputHandler : public sys::ConnectionInputHandler -{ - public: - ProxyInputHandler(boost::intrusive_ptr<cluster::Connection> t) : target(t) {} - ~ProxyInputHandler() { closed(); } - - void received(framing::AMQFrame& f) { target->received(f); } - void closed() { if (target) target->closed(); target = 0; } - void idleOut() { target->idleOut(); } - void idleIn() { target->idleIn(); } - bool doOutput() { return target->doOutput(); } - - private: - boost::intrusive_ptr<cluster::Connection> target; -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_PROXYINPUTHANDLER_H*/ diff --git a/cpp/src/qpid/cluster/Quorum.h b/cpp/src/qpid/cluster/Quorum.h deleted file mode 100644 index bbfa473f94..0000000000 --- a/cpp/src/qpid/cluster/Quorum.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef QPID_CLUSTER_QUORUM_H -#define QPID_CLUSTER_QUORUM_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "config.h" - -#if HAVE_LIBCMAN_H -#include "qpid/cluster/Quorum_cman.h" -#else -#include "qpid/cluster/Quorum_null.h" -#endif - -#endif /*!QPID_CLUSTER_QUORUM_H*/ diff --git a/cpp/src/qpid/cluster/Quorum_cman.cpp b/cpp/src/qpid/cluster/Quorum_cman.cpp deleted file mode 100644 index 728f824b16..0000000000 --- a/cpp/src/qpid/cluster/Quorum_cman.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/Quorum_cman.h" -#include "qpid/cluster/Cluster.h" -#include "qpid/log/Statement.h" -#include "qpid/Options.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/posix/PrivatePosix.h" - -namespace qpid { -namespace cluster { - -namespace { - -boost::function<void()> errorFn; - -void cmanCallbackFn(cman_handle_t handle, void */*privdata*/, int reason, int /*arg*/) { - if (reason == CMAN_REASON_STATECHANGE && !cman_is_quorate(handle)) { - QPID_LOG(critical, "Lost contact with cluster quorum."); - if (errorFn) errorFn(); - cman_stop_notification(handle); - } -} -} - -Quorum::Quorum(boost::function<void()> err) : cman(0), cmanFd(0) { - errorFn = err; -} - -Quorum::~Quorum() { - if (dispatchHandle.get()) dispatchHandle->stopWatch(); - dispatchHandle.reset(); - if (cman) cman_finish(cman); -} - -void Quorum::start(boost::shared_ptr<sys::Poller> p) { - poller = p; - QPID_LOG(debug, "Connecting to quorum service."); - cman = cman_init(0); - if (cman == 0) throw ErrnoException("Can't connect to cman service"); - if (!cman_is_quorate(cman)) { - QPID_LOG(notice, "Waiting for cluster quorum."); - while(!cman_is_quorate(cman)) sys::sleep(5); - } - int err = cman_start_notification(cman, cmanCallbackFn); - if (err != 0) throw ErrnoException("Can't register for cman notifications"); - watch(getFd()); -} - -void Quorum::watch(int fd) { - cmanFd = fd; - if (dispatchHandle.get()) dispatchHandle->stopWatch(); - ioHandle.reset(new sys::PosixIOHandle(cmanFd)); - dispatchHandle.reset( - new sys::DispatchHandleRef( - *ioHandle, // This must outlive the dispatchHandleRef - boost::bind(&Quorum::dispatch, this, _1), // read - 0, // write - boost::bind(&Quorum::disconnect, this, _1) // disconnect - )); - dispatchHandle->startWatch(poller); -} - -int Quorum::getFd() { - int fd = cman_get_fd(cman); - if (fd == 0) throw ErrnoException("Can't get cman file descriptor"); - return fd; -} - -void Quorum::dispatch(sys::DispatchHandle&) { - try { - cman_dispatch(cman, CMAN_DISPATCH_ALL); - int fd = getFd(); - if (fd != cmanFd) watch(fd); - } catch (const std::exception& e) { - QPID_LOG(critical, "Error in quorum dispatch: " << e.what()); - errorFn(); - } -} - -void Quorum::disconnect(sys::DispatchHandle&) { - QPID_LOG(critical, "Disconnected from quorum service"); - errorFn(); -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/Quorum_cman.h b/cpp/src/qpid/cluster/Quorum_cman.h deleted file mode 100644 index 98e6baee89..0000000000 --- a/cpp/src/qpid/cluster/Quorum_cman.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef QPID_CLUSTER_QUORUM_CMAN_H -#define QPID_CLUSTER_QUORUM_CMAN_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/sys/DispatchHandle.h> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include <memory> - -extern "C" { -#include <libcman.h> -} - -namespace qpid { -namespace sys { -class Poller; -class PosixIOHandle; -} - -namespace cluster { -class Cluster; - -class Quorum { - public: - Quorum(boost::function<void ()> onError); - ~Quorum(); - void start(boost::shared_ptr<sys::Poller>); - - private: - void dispatch(sys::DispatchHandle&); - void disconnect(sys::DispatchHandle&); - int getFd(); - void watch(int fd); - - cman_handle_t cman; - int cmanFd; - std::auto_ptr<sys::PosixIOHandle> ioHandle; - std::auto_ptr<sys::DispatchHandleRef> dispatchHandle; - boost::shared_ptr<sys::Poller> poller; -}; - - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_QUORUM_CMAN_H*/ diff --git a/cpp/src/qpid/cluster/Quorum_null.h b/cpp/src/qpid/cluster/Quorum_null.h deleted file mode 100644 index dc27f0a43b..0000000000 --- a/cpp/src/qpid/cluster/Quorum_null.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_CLUSTER_QUORUM_NULL_H -#define QPID_CLUSTER_QUORUM_NULL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include <boost/function.hpp> - -namespace qpid { -namespace cluster { -class Cluster; - -/** Null implementation of quorum. */ - -class Quorum { - public: - Quorum(boost::function<void ()>) {} - void start(boost::shared_ptr<sys::Poller>) {} -}; - -#endif /*!QPID_CLUSTER_QUORUM_NULL_H*/ - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/RetractClient.cpp b/cpp/src/qpid/cluster/RetractClient.cpp deleted file mode 100644 index a8c4b0d543..0000000000 --- a/cpp/src/qpid/cluster/RetractClient.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/RetractClient.h" -#include "qpid/cluster/UpdateClient.h" -#include "qpid/framing/ClusterConnectionRetractOfferBody.h" -#include "qpid/client/ConnectionAccess.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace cluster { - -using namespace framing; - -namespace { - -struct AutoClose { - client::Connection& connection; - AutoClose(client::Connection& c) : connection(c) {} - ~AutoClose() { connection.close(); } -}; -} - -RetractClient::RetractClient(const Url& u, const client::ConnectionSettings& cs) - : url(u), connectionSettings(cs) -{} - -RetractClient::~RetractClient() { delete this; } - - -void RetractClient::run() { - try { - client::Connection c = UpdateClient::catchUpConnection(); - c.open(url, connectionSettings); - AutoClose ac(c); - AMQFrame retract((ClusterConnectionRetractOfferBody())); - client::ConnectionAccess::getImpl(c)->expand(retract.encodedSize(), false); - client::ConnectionAccess::getImpl(c)->handle(retract); - } catch (const std::exception& e) { - QPID_LOG(error, " while retracting retract to " << url << ": " << e.what()); - } -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/RetractClient.h b/cpp/src/qpid/cluster/RetractClient.h deleted file mode 100644 index 533fc3f7ef..0000000000 --- a/cpp/src/qpid/cluster/RetractClient.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_CLUSTER_RETRACTCLIENT_H -#define QPID_CLUSTER_RETRACTCLIENT_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ConnectionSettings.h" -#include "qpid/sys/Runnable.h" -#include "qpid/Url.h" - - -namespace qpid { -namespace cluster { - -/** - * A client that retracts an offer to a remote broker using AMQP. @see UpdateClient - */ -class RetractClient : public sys::Runnable { - public: - - RetractClient(const Url&, const client::ConnectionSettings&); - ~RetractClient(); - void run(); // Will delete this when finished. - - private: - Url url; - client::ConnectionSettings connectionSettings; -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_RETRACTCLIENT_H*/ diff --git a/cpp/src/qpid/cluster/SecureConnectionFactory.cpp b/cpp/src/qpid/cluster/SecureConnectionFactory.cpp deleted file mode 100644 index 6ddef66226..0000000000 --- a/cpp/src/qpid/cluster/SecureConnectionFactory.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/cluster/SecureConnectionFactory.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/cluster/ConnectionCodec.h" -#include "qpid/broker/SecureConnection.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/log/Statement.h" -#include <memory> - - -namespace qpid { -namespace cluster { - -using framing::ProtocolVersion; -using qpid::sys::SecuritySettings; -using qpid::broker::SecureConnection; - -typedef std::auto_ptr<qpid::broker::SecureConnection> SecureConnectionPtr; -typedef std::auto_ptr<qpid::sys::ConnectionCodec> CodecPtr; - -SecureConnectionFactory::SecureConnectionFactory(CodecFactoryPtr f) : codecFactory(f) { -} - -sys::ConnectionCodec* -SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - CodecPtr codec(codecFactory->create(v, out, id, external)); - ConnectionCodec* clusterCodec = dynamic_cast<qpid::cluster::ConnectionCodec*>(codec.get()); - if (clusterCodec) { - SecureConnectionPtr sc(new SecureConnection()); - clusterCodec->setSecureConnection(sc.get()); - sc->setCodec(codec); - return sc.release(); - } - return 0; -} - -sys::ConnectionCodec* -SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - // used to create connections from one broker to another - CodecPtr codec(codecFactory->create(out, id, external)); - ConnectionCodec* clusterCodec = dynamic_cast<qpid::cluster::ConnectionCodec*>(codec.get()); - if (clusterCodec) { - SecureConnectionPtr sc(new SecureConnection()); - clusterCodec->setSecureConnection(sc.get()); - sc->setCodec(codec); - return sc.release(); - } - return 0; -} - - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/SecureConnectionFactory.h b/cpp/src/qpid/cluster/SecureConnectionFactory.h deleted file mode 100644 index 24d1fcfee5..0000000000 --- a/cpp/src/qpid/cluster/SecureConnectionFactory.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef QPID_CLUSTER_SecureconnectionFactory -#define QPID_CLUSTER_SecureconnectionFactory - -#include "qpid/sys/ConnectionCodec.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { - -namespace broker { - class Broker; -} - -namespace cluster { - -class SecureConnectionFactory : public qpid::sys::ConnectionCodec::Factory -{ - public: - typedef boost::shared_ptr<qpid::sys::ConnectionCodec::Factory> CodecFactoryPtr; - SecureConnectionFactory(CodecFactoryPtr f); - - qpid::sys::ConnectionCodec* create( - framing::ProtocolVersion, qpid::sys::OutputControl&, const std::string& id, - const qpid::sys::SecuritySettings& - ); - - /** Return "preferred" codec for outbound connections. */ - qpid::sys::ConnectionCodec* create( - qpid::sys::OutputControl&, const std::string& id, const qpid::sys::SecuritySettings& - ); - - private: - CodecFactoryPtr codecFactory; -}; - -}} // namespace qpid::cluster - - -#endif // QPID_CLUSTER_SecureconnectionFactory diff --git a/cpp/src/qpid/cluster/StoreStatus.cpp b/cpp/src/qpid/cluster/StoreStatus.cpp deleted file mode 100644 index 14c999bb05..0000000000 --- a/cpp/src/qpid/cluster/StoreStatus.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "StoreStatus.h" -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include "qpid/log/Statement.h" -#include <boost/filesystem/path.hpp> -#include <boost/filesystem/fstream.hpp> -#include <boost/filesystem/operations.hpp> -#include <boost/scoped_array.hpp> -#include <fstream> -#include <sstream> - -namespace qpid { -namespace cluster { - -using framing::Uuid; -using namespace framing::cluster; -namespace fs=boost::filesystem; -using namespace std; - -StoreStatus::StoreStatus(const std::string& d) - : state(STORE_STATE_NO_STORE), dataDir(d) -{} - -namespace { - -const char* SUBDIR="cluster"; -const char* STORE_STATUS="store.status"; - -string readFile(const fs::path& path) { - fs::ifstream is; - is.exceptions(std::ios::badbit | std::ios::failbit); - is.open(path); - // get length of file: - is.seekg (0, ios::end); - size_t length = is.tellg(); - is.seekg (0, ios::beg); - // load data - boost::scoped_array<char> buffer(new char[length]); - is.read(buffer.get(), length); - is.close(); - return string(buffer.get(), length); -} - -void writeFile(const fs::path& path, const string& data) { - fs::ofstream os; - os.exceptions(std::ios::badbit | std::ios::failbit); - os.open(path); - os.write(data.data(), data.size()); - os.close(); -} - -} // namespace - - -void StoreStatus::load() { - if (dataDir.empty()) { - throw Exception(QPID_MSG("No data-dir: When a store is loaded together with clustering, --data-dir must be specified.")); - } - try { - fs::path dir = fs::path(dataDir, fs::native)/SUBDIR; - create_directory(dir); - fs::path file = dir/STORE_STATUS; - if (fs::exists(file)) { - string data = readFile(file); - istringstream is(data); - is.exceptions(std::ios::badbit | std::ios::failbit); - is >> ws >> clusterId >> ws >> shutdownId; - if (!clusterId) - throw Exception(QPID_MSG("Invalid cluster store state, no cluster-id")); - if (shutdownId) state = STORE_STATE_CLEAN_STORE; - else state = STORE_STATE_DIRTY_STORE; - } - else { // Starting from empty store - clusterId = Uuid(true); - save(); - state = STORE_STATE_EMPTY_STORE; - } - } - catch (const std::exception&e) { - throw Exception(QPID_MSG("Cannot load cluster store status: " << e.what())); - } -} - -void StoreStatus::save() { - if (dataDir.empty()) return; - try { - ostringstream os; - os << clusterId << endl << shutdownId << endl; - fs::path file = fs::path(dataDir, fs::native)/SUBDIR/STORE_STATUS; - writeFile(file, os.str()); - } - catch (const std::exception& e) { - throw Exception(QPID_MSG("Cannot save cluster store status: " << e.what())); - } -} - -bool StoreStatus::hasStore() const { - return state != framing::cluster::STORE_STATE_NO_STORE; -} - -void StoreStatus::dirty() { - assert(hasStore()); - if (shutdownId) { - shutdownId = Uuid(); - save(); - } - state = STORE_STATE_DIRTY_STORE; -} - -void StoreStatus::clean(const Uuid& shutdownId_) { - assert(hasStore()); - assert(shutdownId_); - if (shutdownId_ != shutdownId) { - shutdownId = shutdownId_; - save(); - } - state = STORE_STATE_CLEAN_STORE; -} - -void StoreStatus::setClusterId(const Uuid& clusterId_) { - clusterId = clusterId_; - save(); -} - -const char* stateName(StoreState s) { - switch (s) { - case STORE_STATE_NO_STORE: return "none"; - case STORE_STATE_EMPTY_STORE: return "empty"; - case STORE_STATE_DIRTY_STORE: return "dirty"; - case STORE_STATE_CLEAN_STORE: return "clean"; - } - assert(0); - return "unknown"; -} - -ostream& operator<<(ostream& o, framing::cluster::StoreState s) { return o << stateName(s); } - -ostream& operator<<(ostream& o, const StoreStatus& s) { - o << s.getState(); - if (s.getState() == STORE_STATE_DIRTY_STORE) - o << " cluster-id=" << s.getClusterId(); - if (s.getState() == STORE_STATE_CLEAN_STORE) { - o << " cluster-id=" << s.getClusterId() - << " shutdown-id=" << s.getShutdownId(); - } - return o; -} - -}} // namespace qpid::cluster - diff --git a/cpp/src/qpid/cluster/StoreStatus.h b/cpp/src/qpid/cluster/StoreStatus.h deleted file mode 100644 index 7442fcf02c..0000000000 --- a/cpp/src/qpid/cluster/StoreStatus.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_CLUSTER_STORESTATE_H -#define QPID_CLUSTER_STORESTATE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/Uuid.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/enum.h" -#include <iosfwd> - -namespace qpid { -namespace cluster { - -/** - * State of the store for cluster purposes. - */ -class StoreStatus -{ - public: - typedef framing::Uuid Uuid; - typedef framing::cluster::StoreState StoreState; - - StoreStatus(const std::string& dir); - - framing::cluster::StoreState getState() const { return state; } - - const Uuid& getClusterId() const { return clusterId; } - void setClusterId(const Uuid&); - const Uuid& getShutdownId() const { return shutdownId; } - - void load(); - void dirty(); // Mark the store in use. - void clean(const Uuid& shutdownId); // Mark the store clean. - bool hasStore() const; - - private: - void save(); - - framing::cluster::StoreState state; - Uuid clusterId, shutdownId; - std::string dataDir; -}; - -const char* stateName(framing::cluster::StoreState); -std::ostream& operator<<(std::ostream&, framing::cluster::StoreState); -std::ostream& operator<<(std::ostream&, const StoreStatus&); -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_STORESTATE_H*/ diff --git a/cpp/src/qpid/cluster/UpdateClient.cpp b/cpp/src/qpid/cluster/UpdateClient.cpp deleted file mode 100644 index a15c14ff48..0000000000 --- a/cpp/src/qpid/cluster/UpdateClient.cpp +++ /dev/null @@ -1,641 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/cluster/UpdateClient.h" -#include "qpid/cluster/Cluster.h" -#include "qpid/cluster/ClusterMap.h" -#include "qpid/cluster/Connection.h" -#include "qpid/cluster/Decoder.h" -#include "qpid/cluster/ExpiryPolicy.h" -#include "qpid/cluster/UpdateDataExchange.h" -#include "qpid/client/SessionBase_0_10Access.h" -#include "qpid/client/ConnectionAccess.h" -#include "qpid/client/SessionImpl.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/Future.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Fairshare.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/SessionHandler.h" -#include "qpid/broker/SessionState.h" -#include "qpid/broker/TxOpVisitor.h" -#include "qpid/broker/DtxAck.h" -#include "qpid/broker/TxAccept.h" -#include "qpid/broker/TxPublish.h" -#include "qpid/broker/RecoveredDequeue.h" -#include "qpid/broker/RecoveredEnqueue.h" -#include "qpid/broker/StatefulQueueObserver.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/ClusterConnectionMembershipBody.h" -#include "qpid/framing/ClusterConnectionShadowReadyBody.h" -#include "qpid/framing/ClusterConnectionSessionStateBody.h" -#include "qpid/framing/ClusterConnectionConsumerStateBody.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/framing/TypeCode.h" -#include "qpid/log/Statement.h" -#include "qpid/types/Variant.h" -#include "qpid/Url.h" -#include "qmf/org/apache/qpid/broker/ManagementSetupState.h" -#include <boost/bind.hpp> -#include <boost/cast.hpp> -#include <algorithm> -#include <sstream> - -namespace qpid { -namespace cluster { - -using amqp_0_10::ListCodec; -using broker::Broker; -using broker::Exchange; -using broker::Queue; -using broker::QueueBinding; -using broker::Message; -using broker::SemanticState; -using types::Variant; - -using namespace framing; -namespace arg=client::arg; -using client::SessionBase_0_10Access; - -std::ostream& operator<<(std::ostream& o, const UpdateClient& c) { - return o << "cluster(" << c.updaterId << " UPDATER)"; -} - -struct ClusterConnectionProxy : public AMQP_AllProxy::ClusterConnection, public framing::FrameHandler -{ - boost::shared_ptr<qpid::client::ConnectionImpl> connection; - - ClusterConnectionProxy(client::Connection c) : - AMQP_AllProxy::ClusterConnection(*static_cast<framing::FrameHandler*>(this)), - connection(client::ConnectionAccess::getImpl(c)) {} - ClusterConnectionProxy(client::AsyncSession s) : - AMQP_AllProxy::ClusterConnection(SessionBase_0_10Access(s).get()->out) {} - - void handle(framing::AMQFrame& f) - { - assert(connection); - connection->expand(f.encodedSize(), false); - connection->handle(f); - } -}; - -// Create a connection with special version that marks it as a catch-up connection. -client::Connection UpdateClient::catchUpConnection() { - client::Connection c; - client::ConnectionAccess::setVersion(c, ProtocolVersion(0x80 , 0x80 + 10)); - return c; -} - -// Send a control body directly to the session. -void send(client::AsyncSession& s, const AMQBody& body) { - client::SessionBase_0_10Access sb(s); - sb.get()->send(body); -} - -// TODO aconway 2008-09-24: optimization: update connections/sessions in parallel. - -UpdateClient::UpdateClient(const MemberId& updater, const MemberId& updatee, const Url& url, - broker::Broker& broker, const ClusterMap& m, ExpiryPolicy& expiry_, - const Cluster::ConnectionVector& cons, Decoder& decoder_, - const boost::function<void()>& ok, - const boost::function<void(const std::exception&)>& fail, - const client::ConnectionSettings& cs -) - : updaterId(updater), updateeId(updatee), updateeUrl(url), updaterBroker(broker), map(m), - expiry(expiry_), connections(cons), decoder(decoder_), - connection(catchUpConnection()), shadowConnection(catchUpConnection()), - done(ok), failed(fail), connectionSettings(cs) -{} - -UpdateClient::~UpdateClient() {} - -// Reserved exchange/queue name for catch-up, avoid clashes with user queues/exchanges. -const std::string UpdateClient::UPDATE("qpid.cluster-update"); - -void UpdateClient::run() { - try { - connection.open(updateeUrl, connectionSettings); - session = connection.newSession(UPDATE); - update(); - done(); - } catch (const std::exception& e) { - failed(e); - } - delete this; -} - -void UpdateClient::update() { - QPID_LOG(debug, *this << " updating state to " << updateeId - << " at " << updateeUrl); - Broker& b = updaterBroker; - - updateManagementSetupState(); - - b.getExchanges().eachExchange(boost::bind(&UpdateClient::updateExchange, this, _1)); - b.getQueues().eachQueue(boost::bind(&UpdateClient::updateNonExclusiveQueue, this, _1)); - - // Update queue is used to transfer acquired messages that are no - // longer on their original queue. - session.queueDeclare(arg::queue=UPDATE, arg::autoDelete=true); - session.sync(); - std::for_each(connections.begin(), connections.end(), - boost::bind(&UpdateClient::updateConnection, this, _1)); - session.queueDelete(arg::queue=UPDATE); - - // some Queue Observers need session state & msgs synced first, so sync observers now - b.getQueues().eachQueue(boost::bind(&UpdateClient::updateQueueObservers, this, _1)); - - // Update queue listeners: must come after sessions so consumerNumbering is populated - b.getQueues().eachQueue(boost::bind(&UpdateClient::updateQueueListeners, this, _1)); - - ClusterConnectionProxy(session).expiryId(expiry.getId()); - updateLinks(); - updateManagementAgent(); - - session.close(); - - ClusterConnectionMembershipBody membership; - map.toMethodBody(membership); - AMQFrame frame(membership); - client::ConnectionAccess::getImpl(connection)->expand(frame.encodedSize(), false); - client::ConnectionAccess::getImpl(connection)->handle(frame); - - // NOTE: connection will be closed from the other end, don't close - // it here as that causes a race. - - // TODO aconway 2010-03-15: This sleep avoids the race condition - // described in // https://bugzilla.redhat.com/show_bug.cgi?id=568831. - // It allows the connection to fully close before destroying the - // Connection object. Remove when the bug is fixed. - // - sys::usleep(10*1000); - - QPID_LOG(debug, *this << " update completed to " << updateeId << " at " << updateeUrl); -} - -namespace { -template <class T> std::string encode(const T& t) { - std::string encoded; - encoded.resize(t.encodedSize()); - framing::Buffer buf(const_cast<char*>(encoded.data()), encoded.size()); - t.encode(buf); - return encoded; -} - -template <class T> std::string encode(const T& t, bool encodeKind) { - std::string encoded; - encoded.resize(t.encodedSize()); - framing::Buffer buf(const_cast<char*>(encoded.data()), encoded.size()); - t.encode(buf, encodeKind); - return encoded; -} -} // namespace - - -// Propagate the management state -void UpdateClient::updateManagementSetupState() -{ - management::ManagementAgent* agent = updaterBroker.getManagementAgent(); - if (!agent) return; - - QPID_LOG(debug, *this << " updating management setup-state."); - std::string vendor, product, instance; - agent->getName(vendor, product, instance); - ClusterConnectionProxy(session).managementSetupState( - agent->getNextObjectId(), agent->getBootSequence(), agent->getUuid(), - vendor, product, instance); -} - -void UpdateClient::updateManagementAgent() -{ - management::ManagementAgent* agent = updaterBroker.getManagementAgent(); - if (!agent) return; - string data; - - QPID_LOG(debug, *this << " updating management schemas. ") - agent->exportSchemas(data); - session.messageTransfer( - arg::content=client::Message(data, UpdateDataExchange::MANAGEMENT_SCHEMAS_KEY), - arg::destination=UpdateDataExchange::EXCHANGE_NAME); - - QPID_LOG(debug, *this << " updating management agents. ") - agent->exportAgents(data); - session.messageTransfer( - arg::content=client::Message(data, UpdateDataExchange::MANAGEMENT_AGENTS_KEY), - arg::destination=UpdateDataExchange::EXCHANGE_NAME); - - QPID_LOG(debug, *this << " updating management deleted objects. ") - typedef management::ManagementAgent::DeletedObjectList DeletedObjectList; - DeletedObjectList deleted; - agent->exportDeletedObjects(deleted); - Variant::List list; - for (DeletedObjectList::iterator i = deleted.begin(); i != deleted.end(); ++i) { - string encoded; - (*i)->encode(encoded); - list.push_back(encoded); - } - ListCodec::encode(list, data); - session.messageTransfer( - arg::content=client::Message(data, UpdateDataExchange::MANAGEMENT_DELETED_OBJECTS_KEY), - arg::destination=UpdateDataExchange::EXCHANGE_NAME); -} - -void UpdateClient::updateExchange(const boost::shared_ptr<Exchange>& ex) { - QPID_LOG(debug, *this << " updating exchange " << ex->getName()); - ClusterConnectionProxy(session).exchange(encode(*ex)); -} - -/** Bind a queue to the update exchange and update messges to it - * setting the message possition as needed. - */ -class MessageUpdater { - std::string queue; - bool haveLastPos; - framing::SequenceNumber lastPos; - client::AsyncSession session; - ExpiryPolicy& expiry; - - public: - - MessageUpdater(const string& q, const client::AsyncSession s, ExpiryPolicy& expiry_) : queue(q), haveLastPos(false), session(s), expiry(expiry_) { - session.exchangeBind(queue, UpdateClient::UPDATE); - } - - ~MessageUpdater() { - try { - session.exchangeUnbind(queue, UpdateClient::UPDATE); - } - catch (const std::exception& e) { - // Don't throw in a destructor. - QPID_LOG(error, "Unbinding update queue " << queue << ": " << e.what()); - } - } - - - void updateQueuedMessage(const broker::QueuedMessage& message) { - // Send the queue position if necessary. - if (!haveLastPos || message.position - lastPos != 1) { - ClusterConnectionProxy(session).queuePosition(queue, message.position.getValue()-1); - haveLastPos = true; - } - lastPos = message.position; - - // Send the expiry ID if necessary. - if (message.payload->getProperties<DeliveryProperties>()->getTtl()) { - boost::optional<uint64_t> expiryId = expiry.getId(*message.payload); - ClusterConnectionProxy(session).expiryId(expiryId?*expiryId:0); - } - - // We can't send a broker::Message via the normal client API, - // and it would be expensive to copy it into a client::Message - // so we go a bit under the client API covers here. - // - SessionBase_0_10Access sb(session); - // Disable client code that clears the delivery-properties.exchange - sb.get()->setDoClearDeliveryPropertiesExchange(false); - framing::MessageTransferBody transfer( - *message.payload->getFrames().as<framing::MessageTransferBody>()); - transfer.setDestination(UpdateClient::UPDATE); - - sb.get()->send(transfer, message.payload->getFrames(), - !message.payload->isContentReleased()); - if (message.payload->isContentReleased()){ - uint16_t maxFrameSize = sb.get()->getConnection()->getNegotiatedSettings().maxFrameSize; - uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead(); - bool morecontent = true; - for (uint64_t offset = 0; morecontent; offset += maxContentSize) - { - AMQFrame frame((AMQContentBody())); - morecontent = message.payload->getContentFrame(*(message.queue), frame, maxContentSize, offset); - sb.get()->sendRawFrame(frame); - } - } - } - - void updateMessage(const boost::intrusive_ptr<broker::Message>& message) { - updateQueuedMessage(broker::QueuedMessage(0, message, haveLastPos? lastPos.getValue()+1 : 1)); - } -}; - -void UpdateClient::updateQueue(client::AsyncSession& s, const boost::shared_ptr<Queue>& q) { - broker::Exchange::shared_ptr alternateExchange = q->getAlternateExchange(); - s.queueDeclare( - arg::queue = q->getName(), - arg::durable = q->isDurable(), - arg::autoDelete = q->isAutoDelete(), - arg::alternateExchange = alternateExchange ? alternateExchange->getName() : "", - arg::arguments = q->getSettings(), - arg::exclusive = q->hasExclusiveOwner() - ); - MessageUpdater updater(q->getName(), s, expiry); - q->eachMessage(boost::bind(&MessageUpdater::updateQueuedMessage, &updater, _1)); - q->eachBinding(boost::bind(&UpdateClient::updateBinding, this, s, q->getName(), _1)); - ClusterConnectionProxy(s).queuePosition(q->getName(), q->getPosition()); - uint priority, count; - if (qpid::broker::Fairshare::getState(q->getMessages(), priority, count)) { - ClusterConnectionProxy(s).queueFairshareState(q->getName(), priority, count); - } -} - -void UpdateClient::updateExclusiveQueue(const boost::shared_ptr<broker::Queue>& q) { - QPID_LOG(debug, *this << " updating exclusive queue " << q->getName() << " on " << shadowSession.getId()); - updateQueue(shadowSession, q); -} - -void UpdateClient::updateNonExclusiveQueue(const boost::shared_ptr<broker::Queue>& q) { - if (!q->hasExclusiveOwner()) { - QPID_LOG(debug, *this << " updating queue " << q->getName()); - updateQueue(session, q); - }//else queue will be updated as part of session state of owning session -} - -void UpdateClient::updateBinding(client::AsyncSession& s, const std::string& queue, const QueueBinding& binding) { - s.exchangeBind(queue, binding.exchange, binding.key, binding.args); -} - -void UpdateClient::updateOutputTask(const sys::OutputTask* task) { - const SemanticState::ConsumerImpl* cci = - boost::polymorphic_downcast<const SemanticState::ConsumerImpl*> (task); - SemanticState::ConsumerImpl* ci = const_cast<SemanticState::ConsumerImpl*>(cci); - uint16_t channel = ci->getParent().getSession().getChannel(); - ClusterConnectionProxy(shadowConnection).outputTask(channel, ci->getName()); - QPID_LOG(debug, *this << " updating output task " << ci->getName() - << " channel=" << channel); -} - -void UpdateClient::updateConnection(const boost::intrusive_ptr<Connection>& updateConnection) { - QPID_LOG(debug, *this << " updating connection " << *updateConnection); - assert(updateConnection->getBrokerConnection()); - broker::Connection& bc = *updateConnection->getBrokerConnection(); - - // Send the management ID first on the main connection. - std::string mgmtId = updateConnection->getBrokerConnection()->getMgmtId(); - ClusterConnectionProxy(session).shadowPrepare(mgmtId); - // Make sure its received before opening shadow connection - session.sync(); - - // Open shadow connection and update it. - shadowConnection = catchUpConnection(); - - connectionSettings.maxFrameSize = bc.getFrameMax(); - shadowConnection.open(updateeUrl, connectionSettings); - ClusterConnectionProxy(shadowConnection).shadowSetUser(bc.getUserId()); - - bc.eachSessionHandler(boost::bind(&UpdateClient::updateSession, this, _1)); - // Safe to use decoder here because we are stalled for update. - std::pair<const char*, size_t> fragment = decoder.get(updateConnection->getId()).getFragment(); - bc.getOutputTasks().eachOutput( - boost::bind(&UpdateClient::updateOutputTask, this, _1)); - ClusterConnectionProxy(shadowConnection).shadowReady( - updateConnection->getId().getMember(), - updateConnection->getId().getNumber(), - bc.getMgmtId(), - bc.getUserId(), - string(fragment.first, fragment.second), - updateConnection->getOutput().getSendMax() - ); - shadowConnection.close(); - QPID_LOG(debug, *this << " updated connection " << *updateConnection); -} - -void UpdateClient::updateSession(broker::SessionHandler& sh) { - broker::SessionState* ss = sh.getSession(); - if (!ss) return; // no session. - - QPID_LOG(debug, *this << " updating session " << ss->getId()); - - // Create a client session to update session state. - boost::shared_ptr<client::ConnectionImpl> cimpl = client::ConnectionAccess::getImpl(shadowConnection); - boost::shared_ptr<client::SessionImpl> simpl = cimpl->newSession(ss->getId().getName(), ss->getTimeout(), sh.getChannel()); - simpl->disableAutoDetach(); - client::SessionBase_0_10Access(shadowSession).set(simpl); - AMQP_AllProxy::ClusterConnection proxy(simpl->out); - - // Re-create session state on remote connection. - - QPID_LOG(debug, *this << " updating exclusive queues."); - ss->getSessionAdapter().eachExclusiveQueue(boost::bind(&UpdateClient::updateExclusiveQueue, this, _1)); - - QPID_LOG(debug, *this << " updating consumers."); - ss->getSemanticState().eachConsumer( - boost::bind(&UpdateClient::updateConsumer, this, _1)); - - QPID_LOG(debug, *this << " updating unacknowledged messages."); - broker::DeliveryRecords& drs = ss->getSemanticState().getUnacked(); - std::for_each(drs.begin(), drs.end(), - boost::bind(&UpdateClient::updateUnacked, this, _1)); - - updateTxState(ss->getSemanticState()); // Tx transaction state. - - // Adjust command counter for message in progress, will be sent after state update. - boost::intrusive_ptr<Message> inProgress = ss->getMessageInProgress(); - SequenceNumber received = ss->receiverGetReceived().command; - if (inProgress) - --received; - - // Sync the session to ensure all responses from broker have been processed. - shadowSession.sync(); - - // Reset command-sequence state. - proxy.sessionState( - ss->senderGetReplayPoint().command, - ss->senderGetCommandPoint().command, - ss->senderGetIncomplete(), - std::max(received, ss->receiverGetExpected().command), - received, - ss->receiverGetUnknownComplete(), - ss->receiverGetIncomplete() - ); - - // Send frames for partial message in progress. - if (inProgress) { - inProgress->getFrames().map(simpl->out); - } - QPID_LOG(debug, *this << " updated session " << sh.getSession()->getId()); -} - -void UpdateClient::updateConsumer( - const broker::SemanticState::ConsumerImpl::shared_ptr& ci) -{ - QPID_LOG(debug, *this << " updating consumer " << ci->getName() << " on " - << shadowSession.getId()); - - using namespace message; - shadowSession.messageSubscribe( - arg::queue = ci->getQueue()->getName(), - arg::destination = ci->getName(), - arg::acceptMode = ci->isAckExpected() ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE, - arg::acquireMode = ci->isAcquire() ? ACQUIRE_MODE_PRE_ACQUIRED : ACQUIRE_MODE_NOT_ACQUIRED, - arg::exclusive = ci->isExclusive(), - arg::resumeId = ci->getResumeId(), - arg::resumeTtl = ci->getResumeTtl(), - arg::arguments = ci->getArguments() - ); - shadowSession.messageSetFlowMode(ci->getName(), ci->isWindowing() ? FLOW_MODE_WINDOW : FLOW_MODE_CREDIT); - shadowSession.messageFlow(ci->getName(), CREDIT_UNIT_MESSAGE, ci->getMsgCredit()); - shadowSession.messageFlow(ci->getName(), CREDIT_UNIT_BYTE, ci->getByteCredit()); - ClusterConnectionProxy(shadowSession).consumerState( - ci->getName(), - ci->isBlocked(), - ci->isNotifyEnabled(), - ci->position - ); - consumerNumbering.add(ci.get()); - - QPID_LOG(debug, *this << " updated consumer " << ci->getName() - << " on " << shadowSession.getId()); -} - -void UpdateClient::updateUnacked(const broker::DeliveryRecord& dr) { - if (!dr.isEnded() && dr.isAcquired() && dr.getMessage().payload) { - // If the message is acquired then it is no longer on the - // updatees queue, put it on the update queue for updatee to pick up. - // - MessageUpdater(UPDATE, shadowSession, expiry).updateQueuedMessage(dr.getMessage()); - } - ClusterConnectionProxy(shadowSession).deliveryRecord( - dr.getQueue()->getName(), - dr.getMessage().position, - dr.getTag(), - dr.getId(), - dr.isAcquired(), - dr.isAccepted(), - dr.isCancelled(), - dr.isComplete(), - dr.isEnded(), - dr.isWindowing(), - dr.getQueue()->isEnqueued(dr.getMessage()), - dr.getCredit() - ); -} - -class TxOpUpdater : public broker::TxOpConstVisitor, public MessageUpdater { - public: - TxOpUpdater(UpdateClient& dc, client::AsyncSession s, ExpiryPolicy& expiry) - : MessageUpdater(UpdateClient::UPDATE, s, expiry), parent(dc), session(s), proxy(s) {} - - void operator()(const broker::DtxAck& ) { - throw InternalErrorException("DTX transactions not currently supported by cluster."); - } - - void operator()(const broker::RecoveredDequeue& rdeq) { - updateMessage(rdeq.getMessage()); - proxy.txEnqueue(rdeq.getQueue()->getName()); - } - - void operator()(const broker::RecoveredEnqueue& renq) { - updateMessage(renq.getMessage()); - proxy.txEnqueue(renq.getQueue()->getName()); - } - - void operator()(const broker::TxAccept& txAccept) { - proxy.txAccept(txAccept.getAcked()); - } - - void operator()(const broker::TxPublish& txPub) { - updateMessage(txPub.getMessage()); - typedef std::list<Queue::shared_ptr> QueueList; - const QueueList& qlist = txPub.getQueues(); - Array qarray(TYPE_CODE_STR8); - for (QueueList::const_iterator i = qlist.begin(); i != qlist.end(); ++i) - qarray.push_back(Array::ValuePtr(new Str8Value((*i)->getName()))); - proxy.txPublish(qarray, txPub.delivered); - } - - private: - UpdateClient& parent; - client::AsyncSession session; - ClusterConnectionProxy proxy; -}; - -void UpdateClient::updateTxState(broker::SemanticState& s) { - QPID_LOG(debug, *this << " updating TX transaction state."); - ClusterConnectionProxy proxy(shadowSession); - proxy.accumulatedAck(s.getAccumulatedAck()); - broker::TxBuffer::shared_ptr txBuffer = s.getTxBuffer(); - if (txBuffer) { - proxy.txStart(); - TxOpUpdater updater(*this, shadowSession, expiry); - txBuffer->accept(updater); - proxy.txEnd(); - } -} - -void UpdateClient::updateQueueListeners(const boost::shared_ptr<broker::Queue>& queue) { - queue->getListeners().eachListener( - boost::bind(&UpdateClient::updateQueueListener, this, queue->getName(), _1)); -} - -void UpdateClient::updateQueueListener(std::string& q, - const boost::shared_ptr<broker::Consumer>& c) -{ - SemanticState::ConsumerImpl* ci = dynamic_cast<SemanticState::ConsumerImpl*>(c.get()); - size_t n = consumerNumbering[ci]; - if (n >= consumerNumbering.size()) - throw Exception(QPID_MSG("Unexpected listener on queue " << q)); - ClusterConnectionProxy(session).addQueueListener(q, n); -} - -void UpdateClient::updateLinks() { - broker::LinkRegistry& links = updaterBroker.getLinks(); - links.eachLink(boost::bind(&UpdateClient::updateLink, this, _1)); - links.eachBridge(boost::bind(&UpdateClient::updateBridge, this, _1)); -} - -void UpdateClient::updateLink(const boost::shared_ptr<broker::Link>& link) { - QPID_LOG(debug, *this << " updating link " - << link->getHost() << ":" << link->getPort()); - ClusterConnectionProxy(session).config(encode(*link)); -} - -void UpdateClient::updateBridge(const boost::shared_ptr<broker::Bridge>& bridge) { - QPID_LOG(debug, *this << " updating bridge " << bridge->getName()); - ClusterConnectionProxy(session).config(encode(*bridge)); -} - -void UpdateClient::updateQueueObservers(const boost::shared_ptr<broker::Queue>& q) -{ - q->eachObserver(boost::bind(&UpdateClient::updateObserver, this, q, _1)); -} - -void UpdateClient::updateObserver(const boost::shared_ptr<broker::Queue>& q, - boost::shared_ptr<broker::QueueObserver> o) -{ - qpid::framing::FieldTable state; - broker::StatefulQueueObserver *so = dynamic_cast<broker::StatefulQueueObserver *>(o.get()); - if (so) { - so->getState( state ); - std::string id(so->getId()); - QPID_LOG(debug, *this << " updating queue " << q->getName() << "'s observer " << id); - ClusterConnectionProxy(session).queueObserverState( q->getName(), id, state ); - } -} - - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/UpdateClient.h b/cpp/src/qpid/cluster/UpdateClient.h deleted file mode 100644 index b72d090d73..0000000000 --- a/cpp/src/qpid/cluster/UpdateClient.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef QPID_CLUSTER_UPDATECLIENT_H -#define QPID_CLUSTER_UPDATECLIENT_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/ClusterMap.h" -#include "qpid/cluster/Numbering.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/sys/Runnable.h" -#include <boost/shared_ptr.hpp> -#include <iosfwd> - -namespace qpid { - -struct Url; - -namespace broker { - -class Broker; -class Queue; -class Exchange; -class QueueBindings; -struct QueueBinding; -struct QueuedMessage; -class SessionHandler; -class DeliveryRecord; -class SessionState; -class SemanticState; -class Decoder; -class Link; -class Bridge; -class QueueObserver; - -} // namespace broker - -namespace cluster { - -class Cluster; -class Connection; -class ClusterMap; -class Decoder; -class ExpiryPolicy; - -/** - * A client that updates the contents of a local broker to a remote one using AMQP. - */ -class UpdateClient : public sys::Runnable { - public: - static const std::string UPDATE; // Name for special update queue and exchange. - static client::Connection catchUpConnection(); - - UpdateClient(const MemberId& updater, const MemberId& updatee, const Url&, - broker::Broker& donor, const ClusterMap& map, ExpiryPolicy& expiry, - const std::vector<boost::intrusive_ptr<Connection> >&, Decoder&, - const boost::function<void()>& done, - const boost::function<void(const std::exception&)>& fail, - const client::ConnectionSettings& - ); - - ~UpdateClient(); - void update(); - void run(); // Will delete this when finished. - - void updateUnacked(const broker::DeliveryRecord&); - - private: - void updateQueue(client::AsyncSession&, const boost::shared_ptr<broker::Queue>&); - void updateNonExclusiveQueue(const boost::shared_ptr<broker::Queue>&); - void updateExclusiveQueue(const boost::shared_ptr<broker::Queue>&); - void updateExchange(const boost::shared_ptr<broker::Exchange>&); - void updateMessage(const broker::QueuedMessage&); - void updateMessageTo(const broker::QueuedMessage&, const std::string& queue, client::Session s); - void updateBinding(client::AsyncSession&, const std::string& queue, const broker::QueueBinding& binding); - void updateConnection(const boost::intrusive_ptr<Connection>& connection); - void updateSession(broker::SessionHandler& s); - void updateTxState(broker::SemanticState& s); - void updateOutputTask(const sys::OutputTask* task); - void updateConsumer(const broker::SemanticState::ConsumerImpl::shared_ptr&); - void updateQueueListeners(const boost::shared_ptr<broker::Queue>&); - void updateQueueListener(std::string& q, const boost::shared_ptr<broker::Consumer>& c); - void updateManagementSetupState(); - void updateManagementAgent(); - void updateLinks(); - void updateLink(const boost::shared_ptr<broker::Link>&); - void updateBridge(const boost::shared_ptr<broker::Bridge>&); - void updateQueueObservers(const boost::shared_ptr<broker::Queue>&); - void updateObserver(const boost::shared_ptr<broker::Queue>&, boost::shared_ptr<broker::QueueObserver>); - - - Numbering<broker::SemanticState::ConsumerImpl*> consumerNumbering; - MemberId updaterId; - MemberId updateeId; - Url updateeUrl; - broker::Broker& updaterBroker; - ClusterMap map; - ExpiryPolicy& expiry; - std::vector<boost::intrusive_ptr<Connection> > connections; - Decoder& decoder; - client::Connection connection, shadowConnection; - client::AsyncSession session, shadowSession; - boost::function<void()> done; - boost::function<void(const std::exception& e)> failed; - client::ConnectionSettings connectionSettings; - - friend std::ostream& operator<<(std::ostream&, const UpdateClient&); -}; - - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_UPDATECLIENT_H*/ diff --git a/cpp/src/qpid/cluster/UpdateDataExchange.cpp b/cpp/src/qpid/cluster/UpdateDataExchange.cpp deleted file mode 100644 index e5cd82e3d3..0000000000 --- a/cpp/src/qpid/cluster/UpdateDataExchange.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "UpdateDataExchange.h" -#include "Cluster.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/types/Variant.h" - -namespace qpid { -namespace cluster { - -const std::string UpdateDataExchange::EXCHANGE_NAME("qpid.cluster-update-data"); -const std::string UpdateDataExchange::EXCHANGE_TYPE("qpid.cluster-update-data"); -const std::string UpdateDataExchange::MANAGEMENT_AGENTS_KEY("management-agents"); -const std::string UpdateDataExchange::MANAGEMENT_SCHEMAS_KEY("management-schemas"); -const std::string UpdateDataExchange::MANAGEMENT_DELETED_OBJECTS_KEY("management-deleted-objects"); - -UpdateDataExchange::UpdateDataExchange(Cluster& cluster) : - Exchange(EXCHANGE_NAME, &cluster) -{} - -void UpdateDataExchange::route(broker::Deliverable& msg, const std::string& routingKey, - const qpid::framing::FieldTable* ) -{ - std::string data = msg.getMessage().getFrames().getContent(); - if (routingKey == MANAGEMENT_AGENTS_KEY) managementAgents = data; - else if (routingKey == MANAGEMENT_SCHEMAS_KEY) managementSchemas = data; - else if (routingKey == MANAGEMENT_DELETED_OBJECTS_KEY) managementDeletedObjects = data; - else throw Exception( - QPID_MSG("Cluster update-data exchange received unknown routing-key: " - << routingKey)); -} - -void UpdateDataExchange::updateManagementAgent(management::ManagementAgent* agent) { - if (!agent) return; - - framing::Buffer buf1(const_cast<char*>(managementAgents.data()), managementAgents.size()); - agent->importAgents(buf1); - - framing::Buffer buf2(const_cast<char*>(managementSchemas.data()), managementSchemas.size()); - agent->importSchemas(buf2); - - using amqp_0_10::ListCodec; - using types::Variant; - Variant::List encoded; - ListCodec::decode(managementDeletedObjects, encoded); - management::ManagementAgent::DeletedObjectList objects; - for (Variant::List::iterator i = encoded.begin(); i != encoded.end(); ++i) { - objects.push_back(management::ManagementAgent::DeletedObject::shared_ptr( - new management::ManagementAgent::DeletedObject(*i))); - } - agent->importDeletedObjects(objects); -} - - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/UpdateDataExchange.h b/cpp/src/qpid/cluster/UpdateDataExchange.h deleted file mode 100644 index d2f6c35ad0..0000000000 --- a/cpp/src/qpid/cluster/UpdateDataExchange.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef QPID_CLUSTER_UPDATEDATAEXCHANGE_H -#define QPID_CLUSTER_UPDATEDATAEXCHANGE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Exchange.h" -#include "types.h" -#include <iosfwd> - -namespace qpid { - -namespace management { -class ManagementAgent; -} - -namespace cluster { -class Cluster; - -/** - * An exchange used to send data that is to large for a control - * during update. The routing key indicates the type of data. - */ -class UpdateDataExchange : public broker::Exchange -{ - public: - static const std::string EXCHANGE_NAME; - static const std::string EXCHANGE_TYPE; - static const std::string MANAGEMENT_AGENTS_KEY; - static const std::string MANAGEMENT_SCHEMAS_KEY; - static const std::string MANAGEMENT_DELETED_OBJECTS_KEY; - - UpdateDataExchange(Cluster& parent); - - void route(broker::Deliverable& msg, const std::string& routingKey, - const framing::FieldTable* args); - - // Not implemented - std::string getType() const { return EXCHANGE_TYPE; } - - bool bind(boost::shared_ptr<broker::Queue>, - const std::string&, - const qpid::framing::FieldTable*) - { return false; } - - bool unbind(boost::shared_ptr<broker::Queue>, - const std::string&, - const qpid::framing::FieldTable*) - { return false; } - - bool isBound(boost::shared_ptr<broker::Queue>, - const std::string*, - const qpid::framing::FieldTable*) - { return false; } - - void updateManagementAgent(management::ManagementAgent* agent); - - private: - std::string managementAgents; - std::string managementSchemas; - std::string managementDeletedObjects; -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_UPDATEDATAEXCHANGE_H*/ diff --git a/cpp/src/qpid/cluster/UpdateExchange.cpp b/cpp/src/qpid/cluster/UpdateExchange.cpp deleted file mode 100644 index 11937f296f..0000000000 --- a/cpp/src/qpid/cluster/UpdateExchange.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/broker/Message.h" -#include "UpdateExchange.h" - -namespace qpid { -namespace cluster { - -using framing::MessageTransferBody; -using framing::DeliveryProperties; - -UpdateExchange::UpdateExchange(management::Manageable* parent) - : broker::Exchange(UpdateClient::UPDATE, parent), - broker::FanOutExchange(UpdateClient::UPDATE, parent) {} - - -void UpdateExchange::setProperties(const boost::intrusive_ptr<broker::Message>& msg) { - MessageTransferBody* transfer = msg->getMethod<MessageTransferBody>(); - assert(transfer); - const DeliveryProperties* props = msg->getProperties<DeliveryProperties>(); - assert(props); - if (props->hasExchange()) - transfer->setDestination(props->getExchange()); - else - transfer->clearDestinationFlag(); -} - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/UpdateExchange.h b/cpp/src/qpid/cluster/UpdateExchange.h deleted file mode 100644 index 9d7d9ee5fc..0000000000 --- a/cpp/src/qpid/cluster/UpdateExchange.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_CLUSTER_UPDATEEXCHANGE_H -#define QPID_CLUSTER_UPDATEEXCHANGE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/cluster/UpdateClient.h" -#include "qpid/broker/FanOutExchange.h" - - -namespace qpid { -namespace cluster { - -/** - * A keyless exchange (like fanout exchange) that does not modify - * delivery-properties.exchange but copies it to the MessageTransfer. - */ -class UpdateExchange : public broker::FanOutExchange -{ - public: - UpdateExchange(management::Manageable* parent); - void setProperties(const boost::intrusive_ptr<broker::Message>&); -}; - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_UPDATEEXCHANGE_H*/ diff --git a/cpp/src/qpid/cluster/UpdateReceiver.h b/cpp/src/qpid/cluster/UpdateReceiver.h deleted file mode 100644 index 7e8ce47662..0000000000 --- a/cpp/src/qpid/cluster/UpdateReceiver.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_CLUSTER_UPDATESTATE_H -#define QPID_CLUSTER_UPDATESTATE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "Numbering.h" -#include "qpid/broker/SemanticState.h" - -namespace qpid { -namespace cluster { - -/** - * Cluster-wide state used when receiving an update. - */ -class UpdateReceiver { - public: - /** Numbering used to identify Queue listeners as consumers */ - typedef Numbering<boost::shared_ptr<broker::SemanticState::ConsumerImpl> > ConsumerNumbering; - ConsumerNumbering consumerNumbering; - - /** Management-id for the next shadow connection */ - std::string nextShadowMgmtId; -}; -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_UPDATESTATE_H*/ diff --git a/cpp/src/qpid/cluster/WatchDogPlugin.cpp b/cpp/src/qpid/cluster/WatchDogPlugin.cpp deleted file mode 100644 index 57ba5cf2fd..0000000000 --- a/cpp/src/qpid/cluster/WatchDogPlugin.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/**@file - - The watchdog plug-in will kill the qpidd broker process if it - becomes stuck for longer than a configured interval. - - If the watchdog plugin is loaded and the --watchdog-interval=N - option is set then the broker starts a watchdog process and signals - it every N/2 seconds. - - The watchdog process runs a very simple program that starts a timer - for N seconds, and resets the timer to N seconds whenever it is - signalled by the broker. If the timer ever reaches 0 the watchdog - kills the broker process (with kill -9) and exits. - - This is useful in a cluster setting because in some insttances - (e.g. while resolving an error) it's possible for a stuck process - to hang other cluster members that are waiting for it to send a - message. Using the watchdog, the stuck process is terminated and - removed fromt the cluster allowing other members to continue and - clients of the stuck process to fail over to other members. - -*/ -#include "config.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/broker/Broker.h" -#include "qpid/sys/Timer.h" -#include "qpid/sys/Fork.h" -#include <sys/types.h> -#include <sys/wait.h> -#include <signal.h> - -namespace qpid { -namespace cluster { - -using broker::Broker; - -struct Settings { - Settings() : interval(0) {} - int interval; -}; - -struct WatchDogOptions : public qpid::Options { - Settings& settings; - - WatchDogOptions(Settings& s) : settings(s) { - addOptions() - ("watchdog-interval", optValue(settings.interval, "N"), - "broker is automatically killed if it is hung for more than \ - N seconds. 0 disables watchdog."); - } -}; - -struct WatchDogTask : public sys::TimerTask { - int pid; - sys::Timer& timer; - int interval; - - WatchDogTask(int pid_, sys::Timer& t, int _interval) - : TimerTask(_interval*sys::TIME_SEC/2,"WatchDog"), pid(pid_), timer(t), interval(_interval) {} - - void fire() { - timer.add (new WatchDogTask(pid, timer, interval)); - QPID_LOG(debug, "Sending keepalive signal to watchdog"); - ::kill(pid, SIGUSR1); - } -}; - -struct WatchDogPlugin : public qpid::Plugin, public qpid::sys::Fork { - Settings settings; - WatchDogOptions options; - Broker* broker; - int watchdogPid; - - WatchDogPlugin() : options(settings), broker(0), watchdogPid(0) {} - - ~WatchDogPlugin() { - if (watchdogPid) ::kill(watchdogPid, SIGTERM); - ::waitpid(watchdogPid, 0, 0); - } - - Options* getOptions() { return &options; } - - void earlyInitialize(qpid::Plugin::Target& target) { - broker = dynamic_cast<Broker*>(&target); - if (broker && settings.interval) { - QPID_LOG(notice, "Starting watchdog process with interval of " << - settings.interval << " seconds"); - fork(); - } - } - - void initialize(Target&) {} - - protected: - - void child() { // Child of fork - const char* watchdog = ::getenv("QPID_WATCHDOG_EXEC"); // For use in tests - if (!watchdog) watchdog=QPID_LIBEXEC_DIR "/qpidd_watchdog"; - std::string interval = boost::lexical_cast<std::string>(settings.interval); - ::execl(watchdog, watchdog, interval.c_str(), NULL); - QPID_LOG(critical, "Failed to exec watchdog program " << watchdog ); - ::kill(::getppid(), SIGKILL); - exit(1); - } - - void parent(int pid) { // Parent of fork - watchdogPid = pid; - broker->getTimer().add( - new WatchDogTask(watchdogPid, broker->getTimer(), settings.interval)); - // TODO aconway 2009-08-10: to be extra safe, we could monitor - // the watchdog child and re-start it if it exits. - } -}; - -static WatchDogPlugin instance; // Static initialization. - -}} // namespace qpid::cluster diff --git a/cpp/src/qpid/cluster/management-schema.xml b/cpp/src/qpid/cluster/management-schema.xml deleted file mode 100644 index a6292e9113..0000000000 --- a/cpp/src/qpid/cluster/management-schema.xml +++ /dev/null @@ -1,61 +0,0 @@ -<schema package="org.apache.qpid.cluster"> - - <!-- - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - --> - - <!-- Type information: - -Numeric types with "_wm" suffix are watermarked numbers. These are compound -values containing a current value, and a low and high water mark for the reporting -interval. The low and high water marks are set to the current value at the -beginning of each interval and track the minimum and maximum values of the statistic -over the interval respectively. - -Access rights for configuration elements: - -RO => Read Only -RC => Read/Create, can be set at create time only, read-only thereafter -RW => Read/Write - -If access rights are omitted for a property, they are assumed to be RO. - - --> - - <class name="Cluster"> - <property name="brokerRef" type="objId" references="Broker" access="RC" index="y" parentRef="y"/> - <property name="clusterName" type="sstr" access="RC" desc="Name of cluster this server is a member of"/> - <property name="clusterID" type="sstr" access="RO" desc="Globally unique ID (UUID) for this cluster instance"/> - <property name="memberID" type="sstr" access="RO" desc="ID of this member of the cluster"/> - <property name="publishedURL" type="sstr" access="RC" desc="URL this node advertizes itself as"/> - <property name="clusterSize" type="uint16" access="RO" desc="Number of brokers currently in the cluster"/> - <property name="status" type="sstr" access="RO" desc="Cluster node status (STALLED,ACTIVE,JOINING)"/> - <property name="members" type="lstr" access="RO" desc="List of member URLs delimited by ';'"/> - <property name="memberIDs" type="lstr" access="RO" desc="List of member IDs delimited by ';'"/> - - <method name="stopClusterNode"> - <arg name="brokerId" type="sstr" dir="I"/> - </method> - <method name="stopFullCluster"/> - - </class> - - - -</schema> - diff --git a/cpp/src/qpid/cluster/qpidd_watchdog.cpp b/cpp/src/qpid/cluster/qpidd_watchdog.cpp deleted file mode 100644 index 51c5ed4b3f..0000000000 --- a/cpp/src/qpid/cluster/qpidd_watchdog.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** @file helper executable for WatchDogPlugin.cpp */ - -#include <sys/types.h> -#include <sys/time.h> -#include <signal.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <limits.h> - -long timeout; - -void killParent(int) { - ::kill(getppid(), SIGKILL); - ::fprintf(stderr, "Watchdog killed unresponsive broker, pid=%d\n", ::getppid()); - ::exit(1); -} - -void resetTimer(int) { - struct ::itimerval itval = { { 0, 0 }, { timeout, 0 } }; - if (::setitimer(ITIMER_REAL, &itval, 0) !=0) { - ::perror("Watchdog failed to set timer"); - killParent(0); - ::exit(1); - } -} - -/** Simple watchdog program: kill parent process if timeout - * expires without a SIGUSR1. - * Will be killed with SIGHUP when parent shuts down. - * Args: timeout in seconds. - */ -int main(int argc, char** argv) { - if(argc != 2 || (timeout = atoi(argv[1])) == 0) { - ::fprintf(stderr, "Usage: %s <timeout_seconds>\n", argv[0]); - ::exit(1); - } - ::signal(SIGUSR1, resetTimer); - ::signal(SIGALRM, killParent); - resetTimer(0); - while (true) { sleep(INT_MAX); } -} diff --git a/cpp/src/qpid/cluster/types.h b/cpp/src/qpid/cluster/types.h deleted file mode 100644 index bfb4fd5b9e..0000000000 --- a/cpp/src/qpid/cluster/types.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef QPID_CLUSTER_TYPES_H -#define QPID_CLUSTER_TYPES_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "config.h" -#include "qpid/Url.h" -#include "qpid/RefCounted.h" -#include "qpid/sys/IntegerTypes.h" -#include <boost/intrusive_ptr.hpp> -#include <utility> -#include <iosfwd> -#include <string> - -extern "C" { -#if defined (HAVE_OPENAIS_CPG_H) -# include <openais/cpg.h> -#elif defined (HAVE_COROSYNC_CPG_H) -# include <corosync/cpg.h> -#else -# error "No cpg.h header file available" -#endif -} - -namespace qpid { -namespace cluster { - -class Connection; -typedef boost::intrusive_ptr<Connection> ConnectionPtr; - -/** Types of cluster event. */ -enum EventType { DATA, CONTROL }; - -/** first=node-id, second=pid */ -struct MemberId : std::pair<uint32_t, uint32_t> { - MemberId(uint64_t n=0) : std::pair<uint32_t,uint32_t>( n >> 32, n & 0xffffffff) {} - MemberId(uint32_t node, uint32_t pid) : std::pair<uint32_t,uint32_t>(node, pid) {} - MemberId(const cpg_address& caddr) : std::pair<uint32_t,uint32_t>(caddr.nodeid, caddr.pid) {} - MemberId(const std::string&); // Decode from string. - uint32_t getNode() const { return first; } - uint32_t getPid() const { return second; } - operator uint64_t() const { return (uint64_t(first)<<32ull) + second; } - - // MemberId as byte string, network byte order. Not human readable. - std::string str() const; -}; - -inline bool operator==(const cpg_address& caddr, const MemberId& id) { return id == MemberId(caddr); } - -std::ostream& operator<<(std::ostream&, const MemberId&); - -struct ConnectionId : public std::pair<MemberId, uint64_t> { - ConnectionId(const MemberId& m=MemberId(), uint64_t c=0) : std::pair<MemberId, uint64_t> (m,c) {} - ConnectionId(uint64_t m, uint64_t c) : std::pair<MemberId, uint64_t>(MemberId(m), c) {} - MemberId getMember() const { return first; } - uint64_t getNumber() const { return second; } -}; - -std::ostream& operator<<(std::ostream&, const ConnectionId&); - -std::ostream& operator<<(std::ostream&, EventType); - -}} // namespace qpid::cluster - -#endif /*!QPID_CLUSTER_TYPES_H*/ diff --git a/cpp/src/qpid/console/Agent.cpp b/cpp/src/qpid/console/Agent.cpp deleted file mode 100644 index fa76a13583..0000000000 --- a/cpp/src/qpid/console/Agent.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/Agent.h" - -std::ostream& qpid::console::operator<<(std::ostream& o, const Agent& agent) -{ - o << "Agent at bank " << agent.getBrokerBank() << "." << agent.getAgentBank() << - " (" << agent.getLabel() << ")"; - return o; -} - diff --git a/cpp/src/qpid/console/Broker.cpp b/cpp/src/qpid/console/Broker.cpp deleted file mode 100644 index 86a17d4a10..0000000000 --- a/cpp/src/qpid/console/Broker.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/Broker.h" -#include "qpid/console/Object.h" -#include "qpid/console/Value.h" -#include "qpid/console/SessionManager.h" -#include "qpid/console/ConsoleListener.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SystemInfo.h" - -using namespace qpid::client; -using namespace qpid::console; -using namespace qpid::framing; -using namespace qpid::sys; -using namespace std; - -Broker::Broker(SessionManager& sm, ConnectionSettings& settings) : - sessionManager(sm), connected(false), connectionSettings(settings), - reqsOutstanding(1), syncInFlight(false), topicBound(false), methodObject(0), - connThreadBody(*this), connThread(connThreadBody) -{ - string osName; - string nodeName; - string release; - string version; - string machine; - - sys::SystemInfo::getSystemId(osName, nodeName, release, version, machine); - uint32_t pid = sys::SystemInfo::getParentProcessId(); - - stringstream text; - - text << "qmfc-cpp-" << nodeName << "-" << pid; - amqpSessionId = string(text.str()); - - QPID_LOG(debug, "Broker::Broker: constructed, amqpSessionId=" << amqpSessionId); -} - -Broker::~Broker() -{ - connThreadBody.shutdown(); - connThread.join(); - resetAgents(); - // resetAgents() does not delete the broker agent... - for (AgentMap::iterator iter = agents.begin(); iter != agents.end(); iter++) { - delete iter->second; - } -} - -string Broker::getUrl() const -{ - stringstream url; - url << connectionSettings.host << ":" << connectionSettings.port; - return url.str(); -} - -void Broker::encodeHeader(Buffer& buf, uint8_t opcode, uint32_t seq) const -{ - buf.putOctet('A'); - buf.putOctet('M'); - buf.putOctet('2'); - buf.putOctet(opcode); - buf.putLong (seq); -} - -bool Broker::checkHeader(Buffer& buf, uint8_t *opcode, uint32_t *seq) const -{ - if (buf.getSize() < 8) - return false; - - uint8_t h1 = buf.getOctet(); - uint8_t h2 = buf.getOctet(); - uint8_t h3 = buf.getOctet(); - - *opcode = buf.getOctet(); - *seq = buf.getLong(); - - return h1 == 'A' && h2 == 'M' && h3 == '2'; -} - -void Broker::received(qpid::client::Message& msg) -{ -#define QMF_HEADER_SIZE 8 - string data = msg.getData(); - Buffer inBuffer(const_cast<char*>(data.c_str()), data.size()); - uint8_t opcode; - uint32_t sequence; - - while (inBuffer.available() >= QMF_HEADER_SIZE) { - if (checkHeader(inBuffer, &opcode, &sequence)) { - QPID_LOG(trace, "Broker::received: opcode=" << opcode << " seq=" << sequence); - - if (opcode == 'b') sessionManager.handleBrokerResp(this, inBuffer, sequence); - else if (opcode == 'p') sessionManager.handlePackageInd(this, inBuffer, sequence); - else if (opcode == 'z') sessionManager.handleCommandComplete(this, inBuffer, sequence); - else if (opcode == 'q') sessionManager.handleClassInd(this, inBuffer, sequence); - else if (opcode == 'm') sessionManager.handleMethodResp(this, inBuffer, sequence); - else if (opcode == 'h') sessionManager.handleHeartbeatInd(this, inBuffer, sequence); - else if (opcode == 'e') sessionManager.handleEventInd(this, inBuffer, sequence); - else if (opcode == 's') sessionManager.handleSchemaResp(this, inBuffer, sequence); - else if (opcode == 'c') sessionManager.handleContentInd(this, inBuffer, sequence, true, false); - else if (opcode == 'i') sessionManager.handleContentInd(this, inBuffer, sequence, false, true); - else if (opcode == 'g') sessionManager.handleContentInd(this, inBuffer, sequence, true, true); - } else - return; - } -} - -void Broker::resetAgents() -{ - for (AgentMap::iterator iter = agents.begin(); iter != agents.end(); iter++) { - if (sessionManager.listener != 0) - sessionManager.listener->delAgent(*(iter->second)); - delete iter->second; - } - - agents.clear(); - agents[0x0000000100000000LL] = new Agent(this, 0, "BrokerAgent"); -} - -void Broker::updateAgent(const Object& object) -{ - uint32_t brokerBank = object.attrUint("brokerBank"); - uint32_t agentBank = object.attrUint("agentBank"); - uint64_t agentKey = ((uint64_t) brokerBank << 32) | (uint64_t) agentBank; - AgentMap::iterator iter = agents.find(agentKey); - - if (object.isDeleted()) { - if (iter != agents.end()) { - if (sessionManager.listener != 0) - sessionManager.listener->delAgent(*(iter->second)); - delete iter->second; - agents.erase(iter); - } - } else { - if (iter == agents.end()) { - Agent* agent = new Agent(this, agentBank, object.attrString("label")); - agents[agentKey] = agent; - if (sessionManager.listener != 0) - sessionManager.listener->newAgent(*agent); - } - } -} - -void Broker::ConnectionThread::run() -{ - static const int delayMin(1); - static const int delayMax(128); - static const int delayFactor(2); - int delay(delayMin); - string dest("qmfc"); - - sessionId.generate(); - queueName << "qmfc-" << sessionId; - - while (true) { - try { - broker.topicBound = false; - broker.reqsOutstanding = 1; - connection.open(broker.connectionSettings); - session = connection.newSession(queueName.str()); - subscriptions = new client::SubscriptionManager(session); - - session.queueDeclare(arg::queue=queueName.str(), arg::autoDelete=true, - arg::exclusive=true); - session.exchangeBind(arg::exchange="amq.direct", arg::queue=queueName.str(), - arg::bindingKey=queueName.str()); - - subscriptions->setAcceptMode(ACCEPT_MODE_NONE); - subscriptions->setAcquireMode(ACQUIRE_MODE_PRE_ACQUIRED); - subscriptions->subscribe(broker, queueName.str(), dest); - subscriptions->setFlowControl(dest, FlowControl::unlimited()); - { - Mutex::ScopedLock _lock(connLock); - if (shuttingDown) - return; - operational = true; - broker.resetAgents(); - broker.connected = true; - broker.sessionManager.handleBrokerConnect(&broker); - broker.sessionManager.startProtocol(&broker); - try { - Mutex::ScopedUnlock _unlock(connLock); - subscriptions->run(); - } catch (std::exception) {} - - operational = false; - broker.connected = false; - broker.sessionManager.handleBrokerDisconnect(&broker); - } - delay = delayMin; - connection.close(); - delete subscriptions; - subscriptions = 0; - } catch (std::exception &e) { - QPID_LOG(debug, " outer exception: " << e.what()); - if (delay < delayMax) - delay *= delayFactor; - } - - { - Mutex::ScopedLock _lock(connLock); - if (shuttingDown) - return; - { - Mutex::ScopedUnlock _unlock(connLock); - ::sleep(delay); - } - if (shuttingDown) - return; - } - } -} - -Broker::ConnectionThread::~ConnectionThread() -{ - if (subscriptions != 0) { - delete subscriptions; - } -} - -void Broker::ConnectionThread::sendBuffer(Buffer& buf, uint32_t length, - const string& exchange, const string& routingKey) -{ - { - Mutex::ScopedLock _lock(connLock); - if (!operational) - return; - } - - client::Message msg; - string data; - - buf.getRawData(data, length); - msg.getDeliveryProperties().setRoutingKey(routingKey); - msg.getMessageProperties().setReplyTo(ReplyTo("amq.direct", queueName.str())); - msg.setData(data); - try { - session.messageTransfer(arg::content=msg, arg::destination=exchange); - } catch(std::exception&) {} -} - -void Broker::ConnectionThread::bindExchange(const std::string& exchange, const std::string& key) -{ - { - Mutex::ScopedLock _lock(connLock); - if (!operational) - return; - } - - QPID_LOG(debug, "Broker::ConnectionThread::bindExchange: exchange=" << exchange << " key=" << key); - session.exchangeBind(arg::exchange=exchange, arg::queue=queueName.str(), - arg::bindingKey=key); -} - -void Broker::ConnectionThread::shutdown() -{ - { - Mutex::ScopedLock _lock(connLock); - shuttingDown = true; - } - if (subscriptions) - subscriptions->stop(); -} - -void Broker::waitForStable() -{ - Mutex::ScopedLock l(lock); - if (reqsOutstanding == 0) - return; - syncInFlight = true; - while (reqsOutstanding != 0) { - bool result = cond.wait(lock, AbsTime(now(), TIME_SEC * sessionManager.settings.getTimeout)); - if (!result) - throw(Exception("Timed out waiting for broker to synchronize")); - } -} - -void Broker::incOutstanding() -{ - Mutex::ScopedLock l(lock); - reqsOutstanding++; -} - -void Broker::decOutstanding() -{ - Mutex::ScopedLock l(lock); - reqsOutstanding--; - if (reqsOutstanding == 0) { - if (!topicBound) { - topicBound = true; - for (vector<string>::const_iterator iter = sessionManager.bindingKeyList.begin(); - iter != sessionManager.bindingKeyList.end(); iter++) - connThreadBody.bindExchange("qpid.management", *iter); - } - if (syncInFlight) { - syncInFlight = false; - cond.notify(); - } - } -} - -void Broker::appendAgents(Agent::Vector& agentlist) const -{ - for (AgentMap::const_iterator iter = agents.begin(); iter != agents.end(); iter++) { - agentlist.push_back(iter->second); - } -} - -ostream& qpid::console::operator<<(ostream& o, const Broker& k) -{ - o << "Broker: " << k.connectionSettings.host << ":" << k.connectionSettings.port; - return o; -} diff --git a/cpp/src/qpid/console/ClassKey.cpp b/cpp/src/qpid/console/ClassKey.cpp deleted file mode 100644 index 7a16113bae..0000000000 --- a/cpp/src/qpid/console/ClassKey.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/ClassKey.h" -#include <string.h> -#include <cstdio> - -using namespace std; -using namespace qpid::console; - -ClassKey::ClassKey(const string& _package, const string& _name, const uint8_t* _hash) : - package(_package), name(_name) -{ - ::memcpy(hash, _hash, HASH_SIZE); -} - -string ClassKey::getHashString() const -{ - char cstr[36]; - ::sprintf(cstr, "%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x", - hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], - hash[8], hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]); - return string(cstr); -} - -string ClassKey::str() const -{ - string result(package + ":" + name + "(" + getHashString() + ")"); - return result; -} - -bool ClassKey::operator==(const ClassKey& other) const -{ - return ::memcmp(hash, other.hash, HASH_SIZE) == 0 && - name == other.name && - package == other.package; -} - -bool ClassKey::operator!=(const ClassKey& other) const -{ - return !(*this == other); -} - -bool ClassKey::operator<(const ClassKey& other) const -{ - int cmp = ::memcmp(hash, other.hash, HASH_SIZE); - if (cmp != 0) - return cmp < 0; - cmp = name.compare(other.name); - if (cmp != 0) - return cmp < 0; - return package < other.package; -} - -bool ClassKey::operator>(const ClassKey& other) const -{ - int cmp = ::memcmp(hash, other.hash, HASH_SIZE); - if (cmp != 0) - return cmp > 0; - cmp = name.compare(other.name); - if (cmp != 0) - return cmp > 0; - return package > other.package; -} - -bool ClassKey::operator<=(const ClassKey& other) const -{ - return !(*this > other); -} - -bool ClassKey::operator>=(const ClassKey& other) const -{ - return !(*this < other); -} - -void ClassKey::encode(qpid::framing::Buffer& buffer) const -{ - buffer.putShortString(package); - buffer.putShortString(name); - buffer.putBin128(const_cast<uint8_t*>(hash)); -} - -ostream& qpid::console::operator<<(ostream& o, const ClassKey& k) -{ - o << k.str(); - return o; -} diff --git a/cpp/src/qpid/console/Event.cpp b/cpp/src/qpid/console/Event.cpp deleted file mode 100644 index 3e14804b35..0000000000 --- a/cpp/src/qpid/console/Event.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/Broker.h" -#include "qpid/console/ClassKey.h" -#include "qpid/console/Schema.h" -#include "qpid/console/Event.h" -#include "qpid/console/Value.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/Buffer.h" - -using namespace qpid::console; -using namespace std; -using qpid::framing::Uuid; -using qpid::framing::FieldTable; - -Event::Event(Broker* _broker, SchemaClass* _schema, qpid::framing::Buffer& buffer) : - broker(_broker), schema(_schema) -{ - timestamp = buffer.getLongLong(); - severity = (Severity) buffer.getOctet(); - for (vector<SchemaArgument*>::const_iterator aIter = schema->arguments.begin(); - aIter != schema->arguments.end(); aIter++) { - SchemaArgument* argument = *aIter; - attributes[argument->name] = argument->decodeValue(buffer); - } -} - -const ClassKey& Event::getClassKey() const -{ - return schema->getClassKey(); -} - -string Event::getSeverityString() const -{ - switch (severity) { - case SEV_EMERGENCY : return string("EMER"); - case SEV_ALERT : return string("ALERT"); - case SEV_CRITICAL : return string("CRIT"); - case SEV_ERROR : return string("ERROR"); - case SEV_WARNING : return string("WARN"); - case SEV_NOTICE : return string("NOTIC"); - case SEV_INFO : return string("INFO"); - case SEV_DEBUG : return string("DEBUG"); - } - return string("<UNKNOWN>"); -} - -ObjectId Event::attrRef(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return ObjectId(); - Value::Ptr val = iter->second; - if (!val->isObjectId()) - return ObjectId(); - return val->asObjectId(); -} - -uint32_t Event::attrUint(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0; - Value::Ptr val = iter->second; - if (!val->isUint()) - return 0; - return val->asUint(); -} - -int32_t Event::attrInt(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0; - Value::Ptr val = iter->second; - if (!val->isInt()) - return 0; - return val->asInt(); -} - -uint64_t Event::attrUint64(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0; - Value::Ptr val = iter->second; - if (!val->isUint64()) - return 0; - return val->asUint64(); -} - -int64_t Event::attrInt64(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0; - Value::Ptr val = iter->second; - if (!val->isInt64()) - return 0; - return val->asInt64(); -} - -string Event::attrString(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return string(); - Value::Ptr val = iter->second; - if (!val->isString()) - return string(); - return val->asString(); -} - -bool Event::attrBool(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return false; - Value::Ptr val = iter->second; - if (!val->isBool()) - return false; - return val->asBool(); -} - -float Event::attrFloat(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0.0; - Value::Ptr val = iter->second; - if (!val->isFloat()) - return 0.0; - return val->asFloat(); -} - -double Event::attrDouble(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0.0; - Value::Ptr val = iter->second; - if (!val->isDouble()) - return 0.0; - return val->asDouble(); -} - -Uuid Event::attrUuid(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return Uuid(); - Value::Ptr val = iter->second; - if (!val->isUuid()) - return Uuid(); - return val->asUuid(); -} - -FieldTable Event::attrMap(const string& key) const -{ - Object::AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return FieldTable(); - Value::Ptr val = iter->second; - if (!val->isMap()) - return FieldTable(); - return val->asMap(); -} - - -std::ostream& qpid::console::operator<<(std::ostream& o, const Event& event) -{ - const ClassKey& key = event.getClassKey(); - sys::AbsTime aTime(sys::AbsTime(), sys::Duration(event.getTimestamp())); - o << aTime << " " << event.getSeverityString() << " " << - key.getPackageName() << ":" << key.getClassName() << - " broker=" << event.getBroker()->getUrl(); - - const Object::AttributeMap& attributes = event.getAttributes(); - for (Object::AttributeMap::const_iterator iter = attributes.begin(); - iter != attributes.end(); iter++) { - o << " " << iter->first << "=" << iter->second->str(); - } - return o; -} - - diff --git a/cpp/src/qpid/console/Object.cpp b/cpp/src/qpid/console/Object.cpp deleted file mode 100644 index 6570e293ab..0000000000 --- a/cpp/src/qpid/console/Object.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/SessionManager.h" -#include "qpid/console/Broker.h" -#include "qpid/console/Object.h" -#include "qpid/console/Schema.h" -#include "qpid/console/ClassKey.h" -#include "qpid/console/Value.h" -#include "qpid/framing/Buffer.h" -#include "qpid/sys/Mutex.h" - -using namespace qpid::console; -using namespace qpid::sys; -using namespace qpid; -using namespace std; -using qpid::framing::Uuid; -using qpid::framing::FieldTable; - -void Object::AttributeMap::addRef(const string& key, const ObjectId& val) -{ - (*this)[key] = Value::Ptr(new RefValue(val)); -} - -void Object::AttributeMap::addUint(const string& key, uint32_t val) -{ - (*this)[key] = Value::Ptr(new UintValue(val)); -} - -void Object::AttributeMap::addInt(const string& key, int32_t val) -{ - (*this)[key] = Value::Ptr(new IntValue(val)); -} - -void Object::AttributeMap::addUint64(const string& key, uint64_t val) -{ - (*this)[key] = Value::Ptr(new Uint64Value(val)); -} - -void Object::AttributeMap::addInt64(const string& key, int64_t val) -{ - (*this)[key] = Value::Ptr(new Int64Value(val)); -} - -void Object::AttributeMap::addString(const string& key, const string& val) -{ - (*this)[key] = Value::Ptr(new StringValue(val)); -} - -void Object::AttributeMap::addBool(const string& key, bool val) -{ - (*this)[key] = Value::Ptr(new BoolValue(val)); -} - -void Object::AttributeMap::addFloat(const string& key, float val) -{ - (*this)[key] = Value::Ptr(new FloatValue(val)); -} - -void Object::AttributeMap::addDouble(const string& key, double val) -{ - (*this)[key] = Value::Ptr(new DoubleValue(val)); -} - -void Object::AttributeMap::addUuid(const string& key, const Uuid& val) -{ - (*this)[key] = Value::Ptr(new UuidValue(val)); -} - -void Object::AttributeMap::addMap(const string& key, const FieldTable& val) -{ - (*this)[key] = Value::Ptr(new MapValue(val)); -} - -Object::Object(Broker* b, SchemaClass* s, framing::Buffer& buffer, bool prop, bool stat) : - broker(b), schema(s), pendingMethod(0) -{ - currentTime = buffer.getLongLong(); - createTime = buffer.getLongLong(); - deleteTime = buffer.getLongLong(); - objectId.decode(buffer); - - if (prop) { - set<string> excludes; - parsePresenceMasks(buffer, excludes); - for (vector<SchemaProperty*>::const_iterator pIter = schema->properties.begin(); - pIter != schema->properties.end(); pIter++) { - SchemaProperty* property = *pIter; - if (excludes.count(property->name) != 0) { - attributes[property->name] = Value::Ptr(new NullValue()); - } else { - attributes[property->name] = property->decodeValue(buffer); - } - } - } - - if (stat) { - for (vector<SchemaStatistic*>::const_iterator sIter = schema->statistics.begin(); - sIter != schema->statistics.end(); sIter++) { - SchemaStatistic* statistic = *sIter; - attributes[statistic->name] = statistic->decodeValue(buffer); - } - } -} - -Object::~Object() {} - -const ClassKey& Object::getClassKey() const -{ - return schema->getClassKey(); -} - -string Object::getIndex() const -{ - string result; - - for (vector<SchemaProperty*>::const_iterator pIter = schema->properties.begin(); - pIter != schema->properties.end(); pIter++) { - SchemaProperty* property = *pIter; - if (property->isIndex) { - AttributeMap::const_iterator vIter = attributes.find(property->name); - if (vIter != attributes.end()) { - if (!result.empty()) - result += ":"; - result += vIter->second->str(); - } - } - } - return result; -} - -void Object::mergeUpdate(const Object& /*updated*/) -{ - // TODO -} - -void Object::invokeMethod(const string name, const AttributeMap& args, MethodResponse& result) -{ - for (vector<SchemaMethod*>::const_iterator iter = schema->methods.begin(); - iter != schema->methods.end(); iter++) { - if ((*iter)->name == name) { - SchemaMethod* method = *iter; - char rawbuffer[65536]; - framing::Buffer buffer(rawbuffer, 65536); - uint32_t sequence = broker->sessionManager.sequenceManager.reserve("method"); - pendingMethod = method; - broker->methodObject = this; - broker->encodeHeader(buffer, 'M', sequence); - objectId.encode(buffer); - schema->key.encode(buffer); - buffer.putShortString(name); - - for (vector<SchemaArgument*>::const_iterator aIter = method->arguments.begin(); - aIter != method->arguments.end(); aIter++) { - SchemaArgument* arg = *aIter; - if (arg->dirInput) { - AttributeMap::const_iterator attr = args.find(arg->name); - if (attr != args.end()) { - ValueFactory::encodeValue(arg->typeCode, attr->second, buffer); - } else { - // TODO Use the default value instead of throwing - throw Exception("Missing arguments in method call"); - } - } - } - - uint32_t length = buffer.getPosition(); - buffer.reset(); - stringstream routingKey; - routingKey << "agent." << objectId.getBrokerBank() << "." << objectId.getAgentBank(); - broker->connThreadBody.sendBuffer(buffer, length, "qpid.management", routingKey.str()); - - { - Mutex::ScopedLock l(broker->lock); - bool ok = true; - while (pendingMethod != 0 && ok) { - ok = broker->cond.wait(broker->lock, AbsTime(now(), broker->sessionManager.settings.methodTimeout * TIME_SEC)); - } - - if (!ok) { - result.code = 0x1001; - result.text.assign("Method call timed out"); - result.arguments.clear(); - } else { - result = methodResponse; - } - } - } - } -} - -void Object::handleMethodResp(framing::Buffer& buffer, uint32_t sequence) -{ - broker->sessionManager.sequenceManager.release(sequence); - methodResponse.code = buffer.getLong(); - buffer.getMediumString(methodResponse.text); - methodResponse.arguments.clear(); - - for (vector<SchemaArgument*>::const_iterator aIter = pendingMethod->arguments.begin(); - aIter != pendingMethod->arguments.end(); aIter++) { - SchemaArgument* arg = *aIter; - if (arg->dirOutput) { - methodResponse.arguments[arg->name] = arg->decodeValue(buffer); - } - } - - { - Mutex::ScopedLock l(broker->lock); - pendingMethod = 0; - broker->cond.notify(); - } -} - -ObjectId Object::attrRef(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return ObjectId(); - Value::Ptr val = iter->second; - if (!val->isObjectId()) - return ObjectId(); - return val->asObjectId(); -} - -uint32_t Object::attrUint(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0; - Value::Ptr val = iter->second; - if (!val->isUint()) - return 0; - return val->asUint(); -} - -int32_t Object::attrInt(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0; - Value::Ptr val = iter->second; - if (!val->isInt()) - return 0; - return val->asInt(); -} - -uint64_t Object::attrUint64(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0; - Value::Ptr val = iter->second; - if (!val->isUint64()) - return 0; - return val->asUint64(); -} - -int64_t Object::attrInt64(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0; - Value::Ptr val = iter->second; - if (!val->isInt64()) - return 0; - return val->asInt64(); -} - -string Object::attrString(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return string(); - Value::Ptr val = iter->second; - if (!val->isString()) - return string(); - return val->asString(); -} - -bool Object::attrBool(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return false; - Value::Ptr val = iter->second; - if (!val->isBool()) - return false; - return val->asBool(); -} - -float Object::attrFloat(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0.0; - Value::Ptr val = iter->second; - if (!val->isFloat()) - return 0.0; - return val->asFloat(); -} - -double Object::attrDouble(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return 0.0; - Value::Ptr val = iter->second; - if (!val->isDouble()) - return 0.0; - return val->asDouble(); -} - -Uuid Object::attrUuid(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return Uuid(); - Value::Ptr val = iter->second; - if (!val->isUuid()) - return Uuid(); - return val->asUuid(); -} - -FieldTable Object::attrMap(const string& key) const -{ - AttributeMap::const_iterator iter = attributes.find(key); - if (iter == attributes.end()) - return FieldTable(); - Value::Ptr val = iter->second; - if (!val->isMap()) - return FieldTable(); - return val->asMap(); -} - -void Object::parsePresenceMasks(framing::Buffer& buffer, set<string>& excludeList) -{ - excludeList.clear(); - uint8_t bit = 0; - uint8_t mask = 0; - - for (vector<SchemaProperty*>::const_iterator pIter = schema->properties.begin(); - pIter != schema->properties.end(); pIter++) { - SchemaProperty* property = *pIter; - if (property->isOptional) { - if (bit == 0) { - mask = buffer.getOctet(); - bit = 1; - } - if ((mask & bit) == 0) - excludeList.insert(property->name); - if (bit == 0x80) - bit = 0; - else - bit = bit << 1; - } - } -} - -ostream& qpid::console::operator<<(ostream& o, const Object& object) -{ - const ClassKey& key = object.getClassKey(); - o << key.getPackageName() << ":" << key.getClassName() << "[" << object.getObjectId() << "] " << - object.getIndex(); - return o; -} - diff --git a/cpp/src/qpid/console/ObjectId.cpp b/cpp/src/qpid/console/ObjectId.cpp deleted file mode 100644 index fbaad20d57..0000000000 --- a/cpp/src/qpid/console/ObjectId.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/ObjectId.h" -#include "qpid/framing/Buffer.h" - -using namespace qpid::console; -using namespace qpid; -using namespace std; - -ObjectId::ObjectId(framing::Buffer& buffer) -{ - decode(buffer); -} - -void ObjectId::decode(framing::Buffer& buffer) -{ - first = buffer.getLongLong(); - second = buffer.getLongLong(); -} - -void ObjectId::encode(framing::Buffer& buffer) -{ - buffer.putLongLong(first); - buffer.putLongLong(second); -} - -bool ObjectId::operator==(const ObjectId& other) const -{ - return second == other.second && first == other.first; -} - -bool ObjectId::operator!=(const ObjectId& other) const -{ - return !(*this == other); -} - -bool ObjectId::operator<(const ObjectId& other) const -{ - if (first < other.first) - return true; - if (first > other.first) - return false; - return second < other.second; -} - -bool ObjectId::operator>(const ObjectId& other) const -{ - if (first > other.first) - return true; - if (first < other.first) - return false; - return second > other.second; -} - -bool ObjectId::operator<=(const ObjectId& other) const -{ - return !(*this > other); -} - -bool ObjectId::operator>=(const ObjectId& other) const -{ - return !(*this < other); -} - -ostream& qpid::console::operator<<(ostream& o, const ObjectId& id) -{ - o << (int) id.getFlags() << "-" << id.getSequence() << "-" << id.getBrokerBank() << "-" << - id.getAgentBank() << "-" << id.getObject(); - return o; -} - - diff --git a/cpp/src/qpid/console/Package.cpp b/cpp/src/qpid/console/Package.cpp deleted file mode 100644 index e5d6fa29fd..0000000000 --- a/cpp/src/qpid/console/Package.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/Package.h" - -using namespace qpid::console; - -SchemaClass* Package::getClass(const std::string& className, uint8_t* hash) -{ - NameHash key(className, hash); - ClassMap::iterator iter = classes.find(key); - if (iter != classes.end()) - return iter->second; - return 0; -} - -void Package::addClass(const std::string& className, uint8_t* hash, SchemaClass* schemaClass) -{ - NameHash key(className, hash); - ClassMap::iterator iter = classes.find(key); - if (iter == classes.end()) - classes[key] = schemaClass; -} diff --git a/cpp/src/qpid/console/Schema.cpp b/cpp/src/qpid/console/Schema.cpp deleted file mode 100644 index a3dbd91201..0000000000 --- a/cpp/src/qpid/console/Schema.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/Schema.h" -#include "qpid/console/Value.h" -#include "qpid/framing/FieldTable.h" - -using namespace qpid::console; -using namespace qpid; -using std::string; -using std::vector; - -SchemaArgument::SchemaArgument(framing::Buffer& buffer, bool forMethod) -{ - framing::FieldTable map; - map.decode(buffer); - - name = map.getAsString("name"); - typeCode = map.getAsInt("type"); - unit = map.getAsString("unit"); - min = map.getAsInt("min"); - max = map.getAsInt("max"); - maxLen = map.getAsInt("maxlen"); - desc = map.getAsString("desc"); - - dirInput = false; - dirOutput = false; - if (forMethod) { - string dir(map.getAsString("dir")); - if (dir.find('I') != dir.npos || dir.find('i') != dir.npos) - dirInput = true; - if (dir.find('O') != dir.npos || dir.find('o') != dir.npos) - dirOutput = true; - } -} - -Value::Ptr SchemaArgument::decodeValue(framing::Buffer& buffer) -{ - return ValueFactory::newValue(typeCode, buffer); -} - -SchemaProperty::SchemaProperty(framing::Buffer& buffer) -{ - framing::FieldTable map; - map.decode(buffer); - - name = map.getAsString("name"); - typeCode = map.getAsInt("type"); - accessCode = map.getAsInt("access"); - isIndex = map.getAsInt("index") != 0; - isOptional = map.getAsInt("optional") != 0; - unit = map.getAsString("unit"); - min = map.getAsInt("min"); - max = map.getAsInt("max"); - maxLen = map.getAsInt("maxlen"); - desc = map.getAsString("desc"); -} - -Value::Ptr SchemaProperty::decodeValue(framing::Buffer& buffer) -{ - return ValueFactory::newValue(typeCode, buffer); -} - -SchemaStatistic::SchemaStatistic(framing::Buffer& buffer) -{ - framing::FieldTable map; - map.decode(buffer); - - name = map.getAsString("name"); - typeCode = map.getAsInt("type"); - unit = map.getAsString("unit"); - desc = map.getAsString("desc"); -} - -Value::Ptr SchemaStatistic::decodeValue(framing::Buffer& buffer) -{ - return ValueFactory::newValue(typeCode, buffer); -} - -SchemaMethod::SchemaMethod(framing::Buffer& buffer) -{ - framing::FieldTable map; - map.decode(buffer); - - name = map.getAsString("name"); - desc = map.getAsString("desc"); - int argCount = map.getAsInt("argCount"); - - for (int i = 0; i < argCount; i++) - arguments.push_back(new SchemaArgument(buffer, true)); -} - -SchemaMethod::~SchemaMethod() -{ - for (vector<SchemaArgument*>::iterator iter = arguments.begin(); - iter != arguments.end(); iter++) - delete *iter; -} - -SchemaClass::SchemaClass(const uint8_t _kind, const ClassKey& _key, framing::Buffer& buffer) : - kind(_kind), key(_key) -{ - if (kind == KIND_TABLE) { - uint8_t hasSupertype = 0; //buffer.getOctet(); - uint16_t propCount = buffer.getShort(); - uint16_t statCount = buffer.getShort(); - uint16_t methodCount = buffer.getShort(); - - if (hasSupertype) { - string unused; - buffer.getShortString(unused); - buffer.getShortString(unused); - buffer.getLongLong(); - buffer.getLongLong(); - } - - for (uint16_t idx = 0; idx < propCount; idx++) - properties.push_back(new SchemaProperty(buffer)); - for (uint16_t idx = 0; idx < statCount; idx++) - statistics.push_back(new SchemaStatistic(buffer)); - for (uint16_t idx = 0; idx < methodCount; idx++) - methods.push_back(new SchemaMethod(buffer)); - - } else if (kind == KIND_EVENT) { - uint16_t argCount = buffer.getShort(); - - for (uint16_t idx = 0; idx < argCount; idx++) - arguments.push_back(new SchemaArgument(buffer)); - } -} - -SchemaClass::~SchemaClass() -{ - for (vector<SchemaProperty*>::iterator iter = properties.begin(); - iter != properties.end(); iter++) - delete *iter; - for (vector<SchemaStatistic*>::iterator iter = statistics.begin(); - iter != statistics.end(); iter++) - delete *iter; - for (vector<SchemaMethod*>::iterator iter = methods.begin(); - iter != methods.end(); iter++) - delete *iter; - for (vector<SchemaArgument*>::iterator iter = arguments.begin(); - iter != arguments.end(); iter++) - delete *iter; -} - diff --git a/cpp/src/qpid/console/SequenceManager.cpp b/cpp/src/qpid/console/SequenceManager.cpp deleted file mode 100644 index 86ea829749..0000000000 --- a/cpp/src/qpid/console/SequenceManager.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/SequenceManager.h" - -using namespace qpid::console; -using namespace qpid::sys; -using std::string; -using std::cout; -using std::endl; - -uint32_t SequenceManager::reserve(const std::string& context) -{ - Mutex::ScopedLock l(lock); - uint32_t result = sequence++; - pending[result] = context; - return result; -} - -std::string SequenceManager::release(uint32_t seq) -{ - Mutex::ScopedLock l(lock); - std::map<uint32_t, string>::iterator iter = pending.find(seq); - if (iter == pending.end()) - return string(); - string result(iter->second); - pending.erase(iter); - return result; -} - diff --git a/cpp/src/qpid/console/SessionManager.cpp b/cpp/src/qpid/console/SessionManager.cpp deleted file mode 100644 index 80c5959417..0000000000 --- a/cpp/src/qpid/console/SessionManager.cpp +++ /dev/null @@ -1,517 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/console/SessionManager.h" -#include "qpid/console/Schema.h" -#include "qpid/console/Agent.h" -#include "qpid/console/ConsoleListener.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/Uuid.h" -#include "qpid/framing/FieldTable.h" - -using namespace qpid::console; -using namespace qpid::sys; -using namespace qpid; -using namespace std; -using qpid::framing::Buffer; -using qpid::framing::FieldTable; - -SessionManager::SessionManager(ConsoleListener* _listener, Settings _settings) : - listener(_listener), settings(_settings) -{ - bindingKeys(); -} - -SessionManager::~SessionManager() -{ - for (vector<Broker*>::iterator iter = brokers.begin(); - iter != brokers.end(); iter++) - delete *iter; - - for (map<string, Package*>::iterator iter = packages.begin(); - iter != packages.end(); iter++) { - for (Package::ClassMap::iterator citer = iter->second->classes.begin(); - citer != iter->second->classes.end(); - citer++) - delete citer->second; - delete iter->second; - } -} - -Broker* SessionManager::addBroker(client::ConnectionSettings& settings) -{ - Broker* broker(new Broker(*this, settings)); - { - Mutex::ScopedLock l(brokerListLock); - brokers.push_back(broker); - } - return broker; -} - -void SessionManager::delBroker(Broker* broker) -{ - Mutex::ScopedLock l(brokerListLock); - for (vector<Broker*>::iterator iter = brokers.begin(); - iter != brokers.end(); iter++) - if (*iter == broker) { - brokers.erase(iter); - delete broker; - return; - } -} - -void SessionManager::getPackages(NameVector& packageNames) -{ - allBrokersStable(); - packageNames.clear(); - { - Mutex::ScopedLock l(lock); - for (map<string, Package*>::iterator iter = packages.begin(); - iter != packages.end(); iter++) - packageNames.push_back(iter->first); - } -} - -void SessionManager::getClasses(KeyVector& classKeys, const std::string& packageName) -{ - allBrokersStable(); - classKeys.clear(); - map<string, Package*>::iterator iter = packages.find(packageName); - if (iter == packages.end()) - return; - - Package& package = *(iter->second); - for (Package::ClassMap::const_iterator piter = package.classes.begin(); - piter != package.classes.end(); piter++) { - ClassKey key(piter->second->getClassKey()); - classKeys.push_back(key); - } -} - -SchemaClass& SessionManager::getSchema(const ClassKey& classKey) -{ - allBrokersStable(); - map<string, Package*>::iterator iter = packages.find(classKey.getPackageName()); - if (iter == packages.end()) - throw Exception("Unknown package"); - - Package& package = *(iter->second); - Package::NameHash key(classKey.getClassName(), classKey.getHash()); - Package::ClassMap::iterator cIter = package.classes.find(key); - if (cIter == package.classes.end()) - throw Exception("Unknown class"); - - return *(cIter->second); -} - -void SessionManager::bindPackage(const std::string& packageName) -{ - stringstream key; - key << "console.obj.*.*." << packageName << ".#"; - bindingKeyList.push_back(key.str()); - for (vector<Broker*>::iterator iter = brokers.begin(); iter != brokers.end(); iter++) - (*iter)->addBinding(key.str()); -} - -void SessionManager::bindClass(const ClassKey& classKey) -{ - bindClass(classKey.getPackageName(), classKey.getClassName()); -} - -void SessionManager::bindClass(const std::string& packageName, const std::string& className) -{ - stringstream key; - key << "console.obj.*.*." << packageName << "." << className << ".#"; - bindingKeyList.push_back(key.str()); - for (vector<Broker*>::iterator iter = brokers.begin(); - iter != brokers.end(); iter++) - (*iter)->addBinding(key.str()); -} - - -void SessionManager::bindEvent(const ClassKey& classKey) -{ - bindEvent(classKey.getPackageName(), classKey.getClassName()); -} - - -void SessionManager::bindEvent(const std::string& packageName, const std::string& eventName) -{ - if (!settings.userBindings) throw Exception("Session not configured for userBindings."); - if (settings.rcvEvents) throw Exception("Session already configured to receive all events."); - - stringstream key; - key << "console.event.*.*." << packageName; - if (eventName.length()) { - key << "." << eventName << ".#"; - } else { - key << ".#"; - } - - bindingKeyList.push_back(key.str()); - for (vector<Broker*>::iterator iter = brokers.begin(); - iter != brokers.end(); iter++) - (*iter)->addBinding(key.str()); -} - - -void SessionManager::getAgents(Agent::Vector& agents, Broker* broker) -{ - agents.clear(); - if (broker != 0) { - broker->appendAgents(agents); - } else { - for (vector<Broker*>::iterator iter = brokers.begin(); iter != brokers.end(); iter++) { - (*iter)->appendAgents(agents); - } - } -} - -void SessionManager::getObjects(Object::Vector& objects, const std::string& className, - Broker* _broker, Agent* _agent) -{ - Agent::Vector agentList; - - if (_agent != 0) { - agentList.push_back(_agent); - _agent->getBroker()->waitForStable(); - } else { - if (_broker != 0) { - _broker->appendAgents(agentList); - _broker->waitForStable(); - } else { - allBrokersStable(); - Mutex::ScopedLock _lock(brokerListLock); - for (vector<Broker*>::iterator iter = brokers.begin(); iter != brokers.end(); iter++) { - (*iter)->appendAgents(agentList); - } - } - } - - FieldTable ft; - uint32_t sequence; - ft.setString("_class", className); - - getResult.clear(); - syncSequenceList.clear(); - error = string(); - - if (agentList.empty()) { - objects = getResult; - return; - } - - for (Agent::Vector::iterator iter = agentList.begin(); iter != agentList.end(); iter++) { - Agent* agent = *iter; - char rawbuffer[512]; - Buffer buffer(rawbuffer, 512); - stringstream routingKey; - routingKey << "agent." << agent->getBrokerBank() << "." << agent->getAgentBank(); - { - Mutex::ScopedLock _lock(lock); - sequence = sequenceManager.reserve("multiget"); - syncSequenceList.insert(sequence); - } - agent->getBroker()->encodeHeader(buffer, 'G', sequence); - ft.encode(buffer); - uint32_t length = buffer.getPosition(); - buffer.reset(); - agent->getBroker()->connThreadBody.sendBuffer(buffer, length, "qpid.management", routingKey.str()); - } - - { - Mutex::ScopedLock _lock(lock); - sys::AbsTime startTime = sys::now(); - while (!syncSequenceList.empty() && error.empty()) { - cv.wait(lock, AbsTime(now(), settings.getTimeout * TIME_SEC)); - sys::AbsTime currTime = sys::now(); - if (sys::Duration(startTime, currTime) > settings.getTimeout * TIME_SEC) - break; - } - } - - objects = getResult; -} - -void SessionManager::bindingKeys() -{ - bindingKeyList.push_back("schema.#"); - if (settings.rcvObjects && settings.rcvEvents && settings.rcvHeartbeats && !settings.userBindings) { - bindingKeyList.push_back("console.#"); - } else { - if (settings.rcvObjects && !settings.userBindings) - bindingKeyList.push_back("console.obj.#"); - else - bindingKeyList.push_back("console.obj.*.*.org.apache.qpid.broker.agent"); - if (settings.rcvEvents) - bindingKeyList.push_back("console.event.#"); - if (settings.rcvHeartbeats) - bindingKeyList.push_back("console.heartbeat"); - } -} - -void SessionManager::allBrokersStable() -{ - Mutex::ScopedLock l(brokerListLock); - for (vector<Broker*>::iterator iter = brokers.begin(); - iter != brokers.end(); iter++) - if ((*iter)->isConnected()) - (*iter)->waitForStable(); -} - -void SessionManager::startProtocol(Broker* broker) -{ - char rawbuffer[512]; - Buffer buffer(rawbuffer, 512); - - broker->encodeHeader(buffer, 'B'); - uint32_t length = 512 - buffer.available(); - buffer.reset(); - broker->connThreadBody.sendBuffer(buffer, length); -} - - -void SessionManager::handleBrokerResp(Broker* broker, Buffer& inBuffer, uint32_t) -{ - framing::Uuid brokerId; - - brokerId.decode(inBuffer); - broker->setBrokerId(brokerId); - - char rawbuffer[512]; - Buffer buffer(rawbuffer, 512); - - uint32_t sequence = sequenceManager.reserve("startup"); - broker->encodeHeader(buffer, 'P', sequence); - uint32_t length = 512 - buffer.available(); - buffer.reset(); - broker->connThreadBody.sendBuffer(buffer, length); - - if (listener != 0) { - listener->brokerInfo(*broker); - } -} - -void SessionManager::handlePackageInd(Broker* broker, Buffer& inBuffer, uint32_t) -{ - string packageName; - inBuffer.getShortString(packageName); - - { - Mutex::ScopedLock l(lock); - map<string, Package*>::iterator iter = packages.find(packageName); - if (iter == packages.end()) { - packages[packageName] = new Package(packageName); - if (listener != 0) - listener->newPackage(packageName); - } - } - - broker->incOutstanding(); - char rawbuffer[512]; - Buffer buffer(rawbuffer, 512); - - uint32_t sequence = sequenceManager.reserve("startup"); - broker->encodeHeader(buffer, 'Q', sequence); - buffer.putShortString(packageName); - uint32_t length = 512 - buffer.available(); - buffer.reset(); - broker->connThreadBody.sendBuffer(buffer, length); -} - -void SessionManager::handleCommandComplete(Broker* broker, Buffer& inBuffer, uint32_t sequence) -{ - Mutex::ScopedLock l(lock); - uint32_t resultCode = inBuffer.getLong(); - string resultText; - inBuffer.getShortString(resultText); - string context = sequenceManager.release(sequence); - if (resultCode != 0) - QPID_LOG(debug, "Received error in completion: " << resultCode << " " << resultText); - if (context == "startup") { - broker->decOutstanding(); - } else if (context == "multiget") { - if (syncSequenceList.count(sequence) == 1) { - syncSequenceList.erase(sequence); - if (syncSequenceList.empty()) { - cv.notify(); - } - } - } - // TODO: Other context cases -} - -void SessionManager::handleClassInd(Broker* broker, Buffer& inBuffer, uint32_t) -{ - uint8_t kind; - string packageName; - string className; - uint8_t hash[16]; - - kind = inBuffer.getOctet(); - inBuffer.getShortString(packageName); - inBuffer.getShortString(className); - inBuffer.getBin128(hash); - - { - Mutex::ScopedLock l(lock); - map<string, Package*>::iterator pIter = packages.find(packageName); - if (pIter == packages.end() || pIter->second->getClass(className, hash)) - return; - } - - broker->incOutstanding(); - char rawbuffer[512]; - Buffer buffer(rawbuffer, 512); - - uint32_t sequence = sequenceManager.reserve("startup"); - broker->encodeHeader(buffer, 'S', sequence); - buffer.putShortString(packageName); - buffer.putShortString(className); - buffer.putBin128(hash); - uint32_t length = 512 - buffer.available(); - buffer.reset(); - broker->connThreadBody.sendBuffer(buffer, length); -} - -void SessionManager::handleMethodResp(Broker* broker, Buffer& buffer, uint32_t sequence) -{ - if (broker->methodObject) { - broker->methodObject->handleMethodResp(buffer, sequence); - } -} - -void SessionManager::handleHeartbeatInd(Broker* /*broker*/, Buffer& /*inBuffer*/, uint32_t /*sequence*/) -{ -} - -void SessionManager::handleEventInd(Broker* broker, Buffer& buffer, uint32_t /*sequence*/) -{ - string packageName; - string className; - uint8_t hash[16]; - SchemaClass* schemaClass; - - buffer.getShortString(packageName); - buffer.getShortString(className); - buffer.getBin128(hash); - - { - Mutex::ScopedLock l(lock); - map<string, Package*>::iterator pIter = packages.find(packageName); - if (pIter == packages.end()) - return; - schemaClass = pIter->second->getClass(className, hash); - if (schemaClass == 0) - return; - } - - Event event(broker, schemaClass, buffer); - - if (listener) - listener->event(event); -} - -void SessionManager::handleSchemaResp(Broker* broker, Buffer& inBuffer, uint32_t sequence) -{ - uint8_t kind; - string packageName; - string className; - uint8_t hash[16]; - - kind = inBuffer.getOctet(); - inBuffer.getShortString(packageName); - inBuffer.getShortString(className); - inBuffer.getBin128(hash); - - { - Mutex::ScopedLock l(lock); - map<string, Package*>::iterator pIter = packages.find(packageName); - if (pIter != packages.end() && !pIter->second->getClass(className, hash)) { - ClassKey key(packageName, className, hash); - SchemaClass* schemaClass(new SchemaClass(kind, key, inBuffer)); - pIter->second->addClass(className, hash, schemaClass); - if (listener != 0) { - listener->newClass(schemaClass->getClassKey()); - } - } - } - - sequenceManager.release(sequence); - broker->decOutstanding(); -} - -void SessionManager::handleContentInd(Broker* broker, Buffer& buffer, uint32_t sequence, bool prop, bool stat) -{ - string packageName; - string className; - uint8_t hash[16]; - SchemaClass* schemaClass; - - buffer.getShortString(packageName); - buffer.getShortString(className); - buffer.getBin128(hash); - - { - Mutex::ScopedLock l(lock); - map<string, Package*>::iterator pIter = packages.find(packageName); - if (pIter == packages.end()) - return; - schemaClass = pIter->second->getClass(className, hash); - if (schemaClass == 0) - return; - } - - Object object(broker, schemaClass, buffer, prop, stat); - - if (prop && className == "agent" && packageName == "org.apache.qpid.broker") - broker->updateAgent(object); - - { - Mutex::ScopedLock l(lock); - if (syncSequenceList.count(sequence) == 1) { - if (!object.isDeleted()) - getResult.push_back(object); - return; - } - } - - if (listener) { - if (prop) - listener->objectProps(*broker, object); - if (stat) - listener->objectStats(*broker, object); - } -} - -void SessionManager::handleBrokerConnect(Broker* broker) -{ - if (listener != 0) - listener->brokerConnected(*broker); -} - -void SessionManager::handleBrokerDisconnect(Broker* broker) -{ - if (listener != 0) - listener->brokerDisconnected(*broker); -} - diff --git a/cpp/src/qpid/console/Value.cpp b/cpp/src/qpid/console/Value.cpp deleted file mode 100644 index 47c6a4ce57..0000000000 --- a/cpp/src/qpid/console/Value.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/Value.h" -#include "qpid/framing/Buffer.h" - -#include <sstream> - -using namespace qpid; -using namespace qpid::console; -using namespace std; - -string NullValue::str() const -{ - return "<Null>"; -} - -RefValue::RefValue(framing::Buffer& buffer) -{ - uint64_t first = buffer.getLongLong(); - uint64_t second = buffer.getLongLong(); - value.setValue(first, second); -} - -string RefValue::str() const -{ - stringstream s; - s << value; - return s.str(); -} - -string UintValue::str() const -{ - stringstream s; - s << value; - return s.str(); -} - -string IntValue::str() const -{ - stringstream s; - s << value; - return s.str(); -} - -string Uint64Value::str() const -{ - stringstream s; - s << value; - return s.str(); -} - -string Int64Value::str() const -{ - stringstream s; - s << value; - return s.str(); -} - -StringValue::StringValue(framing::Buffer& buffer, int tc) -{ - if (tc == 6) - buffer.getShortString(value); - else - buffer.getMediumString(value); -} - -string BoolValue::str() const -{ - return value ? "T" : "F"; -} - -string FloatValue::str() const -{ - stringstream s; - s << value; - return s.str(); -} - -string DoubleValue::str() const -{ - stringstream s; - s << value; - return s.str(); -} - -UuidValue::UuidValue(framing::Buffer& buffer) -{ - value.decode(buffer); -} - -string MapValue::str() const -{ - stringstream s; - s << value; - return s.str(); -} - -MapValue::MapValue(framing::Buffer& buffer) -{ - value.decode(buffer); -} - - -Value::Ptr ValueFactory::newValue(int typeCode, framing::Buffer& buffer) -{ - switch (typeCode) { - case 1: return Value::Ptr(new UintValue(buffer.getOctet())); // U8 - case 2: return Value::Ptr(new UintValue(buffer.getShort())); // U16 - case 3: return Value::Ptr(new UintValue(buffer.getLong())); // U32 - case 4: return Value::Ptr(new Uint64Value(buffer.getLongLong())); // U64 - case 6: return Value::Ptr(new StringValue(buffer, 6)); // SSTR - case 7: return Value::Ptr(new StringValue(buffer, 7)); // LSTR - case 8: return Value::Ptr(new Int64Value(buffer.getLongLong())); // ABSTIME - case 9: return Value::Ptr(new Uint64Value(buffer.getLongLong())); // DELTATIME - case 10: return Value::Ptr(new RefValue(buffer)); // REF - case 11: return Value::Ptr(new BoolValue(buffer.getOctet())); // BOOL - case 12: return Value::Ptr(new FloatValue(buffer.getFloat())); // FLOAT - case 13: return Value::Ptr(new DoubleValue(buffer.getDouble())); // DOUBLE - case 14: return Value::Ptr(new UuidValue(buffer)); // UUID - case 15: return Value::Ptr(new MapValue(buffer)); // MAP - case 16: return Value::Ptr(new IntValue(buffer.getOctet())); // S8 - case 17: return Value::Ptr(new IntValue(buffer.getShort())); // S16 - case 18: return Value::Ptr(new IntValue(buffer.getLong())); // S32 - case 19: return Value::Ptr(new Int64Value(buffer.getLongLong())); // S64 - } - - return Value::Ptr(); -} - -void ValueFactory::encodeValue(int typeCode, Value::Ptr value, framing::Buffer& buffer) -{ - switch (typeCode) { - case 1: buffer.putOctet(value->asUint()); return; // U8 - case 2: buffer.putShort(value->asUint()); return; // U16 - case 3: buffer.putLong(value->asUint()); return; // U32 - case 4: buffer.putLongLong(value->asUint64()); return; // U64 - case 6: buffer.putShortString(value->asString()); return; // SSTR - case 7: buffer.putMediumString(value->asString()); return; // LSTR - case 8: buffer.putLongLong(value->asInt64()); return; // ABSTIME - case 9: buffer.putLongLong(value->asUint64()); return; // DELTATIME - case 10: value->asObjectId().encode(buffer); return; // REF - case 11: buffer.putOctet(value->asBool() ? 1 : 0); return; // BOOL - case 12: buffer.putFloat(value->asFloat()); return; // FLOAT - case 13: buffer.putDouble(value->asDouble()); return; // DOUBLE - case 14: value->asUuid().encode(buffer); return; // UUID - case 15: value->asMap().encode(buffer); return; // MAP - case 16: buffer.putOctet(value->asInt()); return; // S8 - case 17: buffer.putShort(value->asInt()); return; // S16 - case 18: buffer.putLong(value->asInt()); return; // S32 - case 19: buffer.putLongLong(value->asInt64()); return; // S64 - } -} diff --git a/cpp/src/qpid/framing/AMQBody.cpp b/cpp/src/qpid/framing/AMQBody.cpp deleted file mode 100644 index b3eeae0615..0000000000 --- a/cpp/src/qpid/framing/AMQBody.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeartbeatBody.h" -#include <iostream> - -namespace qpid { -namespace framing { - -std::ostream& operator<<(std::ostream& out, const AMQBody& body) -{ - body.print(out); - return out; -} - -AMQBody::~AMQBody() {} - -namespace { -struct MatchBodies : public AMQBodyConstVisitor { - const AMQBody& body; - bool match; - - MatchBodies(const AMQBody& b) : body(b), match(false) {} - virtual ~MatchBodies() {} - - virtual void visit(const AMQHeaderBody&) { match=dynamic_cast<const AMQHeaderBody*>(&body); } - virtual void visit(const AMQContentBody&) { match=dynamic_cast<const AMQContentBody*>(&body); } - virtual void visit(const AMQHeartbeatBody&) { match=dynamic_cast<const AMQHeartbeatBody*>(&body); } - virtual void visit(const AMQMethodBody& x) { - const AMQMethodBody* y=dynamic_cast<const AMQMethodBody*>(&body); - match = (y && y->amqpMethodId() == x.amqpMethodId() && y->amqpClassId() == x.amqpClassId()); - } -}; - -} -bool AMQBody::match(const AMQBody& a, const AMQBody& b) { - MatchBodies matcher(a); - b.accept(matcher); - return matcher.match; -} - -}} // namespace diff --git a/cpp/src/qpid/framing/AMQBody.h b/cpp/src/qpid/framing/AMQBody.h deleted file mode 100644 index 56d1d250c1..0000000000 --- a/cpp/src/qpid/framing/AMQBody.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef QPID_FRAMING_AMQBODY_H -#define QPID_FRAMING_AMQBODY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/RefCounted.h" -#include "qpid/framing/BodyFactory.h" -#include <boost/intrusive_ptr.hpp> -#include <ostream> -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class Buffer; - -class AMQMethodBody; -class AMQHeaderBody; -class AMQContentBody; -class AMQHeartbeatBody; - -struct AMQBodyConstVisitor { - virtual ~AMQBodyConstVisitor() {} - virtual void visit(const AMQHeaderBody&) = 0; - virtual void visit(const AMQContentBody&) = 0; - virtual void visit(const AMQHeartbeatBody&) = 0; - virtual void visit(const AMQMethodBody&) = 0; -}; - -class QPID_COMMON_CLASS_EXTERN AMQBody : public RefCounted { - public: - AMQBody() {} - QPID_COMMON_EXTERN virtual ~AMQBody(); - - // Make AMQBody copyable even though RefCounted. - AMQBody(const AMQBody&) : RefCounted() {} - AMQBody& operator=(const AMQBody&) { return *this; } - - virtual uint8_t type() const = 0; - - virtual void encode(Buffer& buffer) const = 0; - virtual void decode(Buffer& buffer, uint32_t=0) = 0; - virtual uint32_t encodedSize() const = 0; - - virtual void print(std::ostream& out) const = 0; - virtual void accept(AMQBodyConstVisitor&) const = 0; - - virtual AMQMethodBody* getMethod() { return 0; } - virtual const AMQMethodBody* getMethod() const { return 0; } - - /** Match if same type and same class/method ID for methods */ - static bool match(const AMQBody& , const AMQBody& ); - virtual boost::intrusive_ptr<AMQBody> clone() const = 0; -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& out, const AMQBody& body) ; - -enum BodyTypes { - METHOD_BODY = 1, - HEADER_BODY = 2, - CONTENT_BODY = 3, - HEARTBEAT_BODY = 8 -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_AMQBODY_H*/ diff --git a/cpp/src/qpid/framing/AMQCommandControlBody.h b/cpp/src/qpid/framing/AMQCommandControlBody.h deleted file mode 100644 index d12b70a168..0000000000 --- a/cpp/src/qpid/framing/AMQCommandControlBody.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef QPID_FRAMING_AMQCOMMANDCONTROLBODY_H -#define QPID_FRAMING_AMQCOMMANDCONTROLBODY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/helpers.h" -#include "qpid/framing/AMQBody.h" - -namespace qpid { -namespace framing { - -/** - * AMQBody wrapper for Command and Control. - * Temporary measure to fit with old code. - */ -template <class T> class AMQCommandControlBody : public AMQBody, public T -{ - public: - virtual uint8_t type() const { return 100+T::SEGMENT_TYPE; } - - virtual void encode(Buffer& buffer) const { - Codec::encode(buffer.getIterator(), static_cast<const T&>(*this)); - } - virtual void decode(Buffer& buffer, uint32_t=0) { - Codec::decode(buffer.getIterator(), static_cast<T&>(*this)); - } - virtual uint32_t encodedSize() const { - Codec::size(buffer.getIterator(), static_cast<const T&>(*this)); - } - - virtual void print(std::ostream& out) const { - out << static_cast<const T&>(*this) << endl; - } - virtual void AMQBody::accept(AMQBodyConstVisitor&) const { assert(0); } -}; - -class CommandBody : public AMQCommandControlBody<amqp_0_10::Command> { - using Command::accept; // Hide AMQBody::accept - virtual Command* getCommand() { return this; } - virtual const Command* getCommand() const { return this; } -}; - -class ControlBody : public AMQCommandControlBody<amqp_0_10::Control> { - using Control::accept; // Hide AMQBody::accept - virtual Control* getControl() { return this; } - virtual const Control* getControl() const { return this; } -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_AMQCOMMANDCONTROLBODY_H*/ diff --git a/cpp/src/qpid/framing/AMQContentBody.cpp b/cpp/src/qpid/framing/AMQContentBody.cpp deleted file mode 100644 index 72f7d9978e..0000000000 --- a/cpp/src/qpid/framing/AMQContentBody.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/AMQContentBody.h" -#include <iostream> - -qpid::framing::AMQContentBody::AMQContentBody(){ -} - -qpid::framing::AMQContentBody::AMQContentBody(const string& _data) : data(_data){ -} - -uint32_t qpid::framing::AMQContentBody::encodedSize() const{ - return data.size(); -} -void qpid::framing::AMQContentBody::encode(Buffer& buffer) const{ - buffer.putRawData(data); -} -void qpid::framing::AMQContentBody::decode(Buffer& buffer, uint32_t _size){ - buffer.getRawData(data, _size); -} - -void qpid::framing::AMQContentBody::print(std::ostream& out) const -{ - out << "content (" << encodedSize() << " bytes)"; - const size_t max = 32; - out << " " << data.substr(0, max); - if (data.size() > max) out << "..."; -} diff --git a/cpp/src/qpid/framing/AMQContentBody.h b/cpp/src/qpid/framing/AMQContentBody.h deleted file mode 100644 index e25451e354..0000000000 --- a/cpp/src/qpid/framing/AMQContentBody.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/Buffer.h" -#include "qpid/CommonImportExport.h" - -#ifndef _AMQContentBody_ -#define _AMQContentBody_ - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN AMQContentBody : public AMQBody -{ - string data; - -public: - QPID_COMMON_EXTERN AMQContentBody(); - QPID_COMMON_EXTERN AMQContentBody(const string& data); - inline virtual ~AMQContentBody(){} - inline uint8_t type() const { return CONTENT_BODY; }; - inline const string& getData() const { return data; } - inline string& getData() { return data; } - QPID_COMMON_EXTERN uint32_t encodedSize() const; - QPID_COMMON_EXTERN void encode(Buffer& buffer) const; - QPID_COMMON_EXTERN void decode(Buffer& buffer, uint32_t size); - QPID_COMMON_EXTERN void print(std::ostream& out) const; - void accept(AMQBodyConstVisitor& v) const { v.visit(*this); } - boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); } -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/framing/AMQDataBlock.h b/cpp/src/qpid/framing/AMQDataBlock.h deleted file mode 100644 index 7f0d0dc2b5..0000000000 --- a/cpp/src/qpid/framing/AMQDataBlock.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/Buffer.h" - -#ifndef _AMQDataBlock_ -#define _AMQDataBlock_ - -namespace qpid { -namespace framing { - -class AMQDataBlock -{ -public: - virtual ~AMQDataBlock() {} - virtual void encode(Buffer& buffer) const = 0; - virtual bool decode(Buffer& buffer) = 0; - virtual uint32_t encodedSize() const = 0; -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/framing/AMQFrame.cpp b/cpp/src/qpid/framing/AMQFrame.cpp deleted file mode 100644 index cd60cd971f..0000000000 --- a/cpp/src/qpid/framing/AMQFrame.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/AMQFrame.h" - -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/BodyFactory.h" -#include "qpid/framing/MethodBodyFactory.h" -#include "qpid/Msg.h" - -#include <boost/format.hpp> -#include <iostream> - -namespace qpid { -namespace framing { - -void AMQFrame::init() { bof = eof = bos = eos = true; subchannel=0; channel=0; } - -AMQFrame::AMQFrame(const boost::intrusive_ptr<AMQBody>& b) : body(b) { init(); } - -AMQFrame::AMQFrame(const AMQBody& b) : body(b.clone()) { init(); } - -AMQFrame::~AMQFrame() {} - -void AMQFrame::setMethod(ClassId c, MethodId m) { body = MethodBodyFactory::create(c,m); } - -uint32_t AMQFrame::encodedSize() const { - uint32_t size = frameOverhead() + body->encodedSize(); - if (body->getMethod()) - size += sizeof(ClassId)+sizeof(MethodId); - return size; -} - -uint32_t AMQFrame::frameOverhead() { - return 12 /*frame header*/; -} - -uint16_t AMQFrame::DECODE_SIZE_MIN=4; - -uint16_t AMQFrame::decodeSize(char* data) { - Buffer buf(data+2, DECODE_SIZE_MIN); - return buf.getShort(); -} - -void AMQFrame::encode(Buffer& buffer) const -{ - //set track first (controls on track 0, everything else on 1): - uint8_t track = getBody()->type() ? 1 : 0; - - uint8_t flags = (bof ? 0x08 : 0) | (eof ? 0x04 : 0) | (bos ? 0x02 : 0) | (eos ? 0x01 : 0); - buffer.putOctet(flags); - buffer.putOctet(getBody()->type()); - buffer.putShort(encodedSize()); - buffer.putOctet(0); - buffer.putOctet(0x0f & track); - buffer.putShort(channel); - buffer.putLong(0); - const AMQMethodBody* method=getMethod(); - if (method) { - buffer.putOctet(method->amqpClassId()); - buffer.putOctet(method->amqpMethodId()); - } - body->encode(buffer); -} - -bool AMQFrame::decode(Buffer& buffer) -{ - if(buffer.available() < frameOverhead()) - return false; - buffer.record(); - - uint8_t flags = buffer.getOctet(); - uint8_t framing_version = (flags & 0xc0) >> 6; - if (framing_version != 0) - throw FramingErrorException(QPID_MSG("Framing version unsupported")); - bof = flags & 0x08; - eof = flags & 0x04; - bos = flags & 0x02; - eos = flags & 0x01; - uint8_t type = buffer.getOctet(); - uint16_t frame_size = buffer.getShort(); - if (frame_size < frameOverhead()) - throw FramingErrorException(QPID_MSG("Frame size too small " << frame_size)); - uint8_t reserved1 = buffer.getOctet(); - uint8_t field1 = buffer.getOctet(); - subchannel = field1 & 0x0f; - channel = buffer.getShort(); - (void) buffer.getLong(); // reserved2 - - // Verify that the protocol header meets current spec - // TODO: should we check reserved2 against zero as well? - the - // spec isn't clear - if ((flags & 0x30) != 0 || reserved1 != 0 || (field1 & 0xf0) != 0) - throw FramingErrorException(QPID_MSG("Reserved bits not zero")); - - // TODO: should no longer care about body size and only pass up - // B,E,b,e flags - uint16_t body_size = frame_size - frameOverhead(); - if (buffer.available() < body_size){ - buffer.restore(); - return false; - } - - switch(type) - { - case 0://CONTROL - case METHOD_BODY: { - ClassId c = buffer.getOctet(); - MethodId m = buffer.getOctet(); - body = MethodBodyFactory::create(c, m); - break; - } - case HEADER_BODY: body = BodyFactory::create<AMQHeaderBody>(); break; - case CONTENT_BODY: body = BodyFactory::create<AMQContentBody>(); break; - case HEARTBEAT_BODY: body = BodyFactory::create<AMQHeartbeatBody>(); break; - default: - throw IllegalArgumentException(QPID_MSG("Invalid frame type " << type)); - } - body->decode(buffer, body_size); - - return true; -} - -std::ostream& operator<<(std::ostream& out, const AMQFrame& f) -{ - return - out << "Frame[" - << (f.getBof() ? "B" : "") << (f.getEof() ? "E" : "") - << (f.getBos() ? "b" : "") << (f.getEos() ? "e" : "") << "; " - << "channel=" << f.getChannel() << "; " << *f.getBody() - << "]"; -} - - -}} // namespace qpid::framing diff --git a/cpp/src/qpid/framing/AMQFrame.h b/cpp/src/qpid/framing/AMQFrame.h deleted file mode 100644 index c669d12bc0..0000000000 --- a/cpp/src/qpid/framing/AMQFrame.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef _AMQFrame_ -#define _AMQFrame_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/AMQDataBlock.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeartbeatBody.h" -#include "qpid/framing/ProtocolVersion.h" -#include <boost/intrusive_ptr.hpp> -#include <boost/cast.hpp> -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN AMQFrame : public AMQDataBlock -{ - public: - QPID_COMMON_EXTERN AMQFrame(const boost::intrusive_ptr<AMQBody>& b=0); - QPID_COMMON_EXTERN AMQFrame(const AMQBody& b); - QPID_COMMON_EXTERN ~AMQFrame(); - - ChannelId getChannel() const { return channel; } - void setChannel(ChannelId c) { channel = c; } - - AMQBody* getBody() { return body.get(); } - const AMQBody* getBody() const { return body.get(); } - - AMQMethodBody* getMethod() { return getBody() ? getBody()->getMethod() : 0; } - const AMQMethodBody* getMethod() const { return getBody() ? getBody()->getMethod() : 0; } - - void setMethod(ClassId c, MethodId m); - - template <class T> T* castBody() { - return boost::polymorphic_downcast<T*>(getBody()); - } - - template <class T> const T* castBody() const { - return boost::polymorphic_downcast<const T*>(getBody()); - } - - QPID_COMMON_EXTERN void encode(Buffer& buffer) const; - QPID_COMMON_EXTERN bool decode(Buffer& buffer); - QPID_COMMON_EXTERN uint32_t encodedSize() const; - - // 0-10 terminology: first/last frame (in segment) first/last segment (in assembly) - - bool isFirstSegment() const { return bof; } - bool isLastSegment() const { return eof; } - bool isFirstFrame() const { return bos; } - bool isLastFrame() const { return eos; } - - void setFirstSegment(bool set=true) { bof = set; } - void setLastSegment(bool set=true) { eof = set; } - void setFirstFrame(bool set=true) { bos = set; } - void setLastFrame(bool set=true) { eos = set; } - - // 0-9 terminology: beginning/end of frameset, beginning/end of segment. - - bool getBof() const { return bof; } - void setBof(bool isBof) { bof = isBof; } - bool getEof() const { return eof; } - void setEof(bool isEof) { eof = isEof; } - - bool getBos() const { return bos; } - void setBos(bool isBos) { bos = isBos; } - bool getEos() const { return eos; } - void setEos(bool isEos) { eos = isEos; } - - static uint16_t DECODE_SIZE_MIN; - QPID_COMMON_EXTERN static uint32_t frameOverhead(); - /** Must point to at least DECODE_SIZE_MIN bytes of data */ - static uint16_t decodeSize(char* data); - - private: - void init(); - - boost::intrusive_ptr<AMQBody> body; - uint16_t channel : 16; - uint8_t subchannel : 8; - bool bof : 1; - bool eof : 1; - bool bos : 1; - bool eos : 1; -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const AMQFrame&); - -}} // namespace qpid::framing - - -#endif diff --git a/cpp/src/qpid/framing/AMQHeaderBody.cpp b/cpp/src/qpid/framing/AMQHeaderBody.cpp deleted file mode 100644 index 14218f1b45..0000000000 --- a/cpp/src/qpid/framing/AMQHeaderBody.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" - -uint32_t qpid::framing::AMQHeaderBody::encodedSize() const { - return properties.encodedSize(); -} - -void qpid::framing::AMQHeaderBody::encode(Buffer& buffer) const { - properties.encode(buffer); -} - -void qpid::framing::AMQHeaderBody::decode(Buffer& buffer, uint32_t size) { - uint32_t limit = buffer.available() - size; - while (buffer.available() > limit + 2) { - uint32_t len = buffer.getLong(); - uint16_t type = buffer.getShort(); - if (!properties.decode(buffer, len, type)) { - // TODO: should just skip & keep for later dispatch. - throw Exception(QPID_MSG("Unexpected property type: " << type)); - } - } -} - -uint64_t qpid::framing::AMQHeaderBody::getContentLength() const -{ - const MessageProperties* mProps = get<MessageProperties>(); - if (mProps) - return mProps->getContentLength(); - return 0; -} - -void qpid::framing::AMQHeaderBody::print(std::ostream& out) const -{ - out << "header (" << encodedSize() << " bytes)"; - out << "; properties={"; - properties.print(out); - out << "}"; -} - -void qpid::framing::AMQHeaderBody::accept(AMQBodyConstVisitor& v) const { - v.visit(*this); -} diff --git a/cpp/src/qpid/framing/AMQHeaderBody.h b/cpp/src/qpid/framing/AMQHeaderBody.h deleted file mode 100644 index a8c326969a..0000000000 --- a/cpp/src/qpid/framing/AMQHeaderBody.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef QPID_FRAMING_AMQHEADERBODY_H -#define QPID_FRAMING_AMQHEADERBODY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/CommonImportExport.h" -#include <iostream> - -#include <boost/optional.hpp> - - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN AMQHeaderBody : public AMQBody -{ - template <class T> struct OptProps { boost::optional<T> props; }; - template <class Base, class T> - struct PropSet : public Base, public OptProps<T> { - uint32_t encodedSize() const { - const boost::optional<T>& p=this->OptProps<T>::props; - return (p ? p->encodedSize() : 0) + Base::encodedSize(); - } - void encode(Buffer& buffer) const { - const boost::optional<T>& p=this->OptProps<T>::props; - if (p) p->encode(buffer); - Base::encode(buffer); - } - bool decode(Buffer& buffer, uint32_t size, uint16_t type) { - boost::optional<T>& p=this->OptProps<T>::props; - if (type == T::TYPE) { - p=T(); - p->decodeStructBody(buffer, size); - return true; - } - else - return Base::decode(buffer, size, type); - } - void print(std::ostream& out) const { - const boost::optional<T>& p=this->OptProps<T>::props; - if (p) out << *p; - Base::print(out); - } - }; - - struct Empty { - uint32_t encodedSize() const { return 0; } - void encode(Buffer&) const {}; - bool decode(Buffer&, uint32_t, uint16_t) const { return false; }; - void print(std::ostream&) const {} - }; - - // Could use boost::mpl::fold to construct a larger set. - typedef PropSet<PropSet<Empty, DeliveryProperties>, MessageProperties> Properties; - - Properties properties; - -public: - - inline uint8_t type() const { return HEADER_BODY; } - - QPID_COMMON_EXTERN uint32_t encodedSize() const; - QPID_COMMON_EXTERN void encode(Buffer& buffer) const; - QPID_COMMON_EXTERN void decode(Buffer& buffer, uint32_t size); - QPID_COMMON_EXTERN uint64_t getContentLength() const; - QPID_COMMON_EXTERN void print(std::ostream& out) const; - QPID_COMMON_EXTERN void accept(AMQBodyConstVisitor&) const; - - template <class T> T* get(bool create) { - boost::optional<T>& p=properties.OptProps<T>::props; - if (create && !p) p=T(); - return p.get_ptr(); - } - - template <class T> const T* get() const { - return properties.OptProps<T>::props.get_ptr(); - } - - boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); } -}; - -}} - - - -#endif /*!QPID_FRAMING_AMQHEADERBODY_H*/ diff --git a/cpp/src/qpid/framing/AMQHeartbeatBody.cpp b/cpp/src/qpid/framing/AMQHeartbeatBody.cpp deleted file mode 100644 index 477616221c..0000000000 --- a/cpp/src/qpid/framing/AMQHeartbeatBody.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/AMQHeartbeatBody.h" -#include <iostream> - -qpid::framing::AMQHeartbeatBody::~AMQHeartbeatBody() {} - -void qpid::framing::AMQHeartbeatBody::print(std::ostream& out) const { - out << "heartbeat"; -} diff --git a/cpp/src/qpid/framing/AMQHeartbeatBody.h b/cpp/src/qpid/framing/AMQHeartbeatBody.h deleted file mode 100644 index 19ac2be013..0000000000 --- a/cpp/src/qpid/framing/AMQHeartbeatBody.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/Buffer.h" -#include "qpid/CommonImportExport.h" - -#ifndef _AMQHeartbeatBody_ -#define _AMQHeartbeatBody_ - -namespace qpid { -namespace framing { - -class QPID_COMMON_CLASS_EXTERN AMQHeartbeatBody : public AMQBody -{ -public: - QPID_COMMON_EXTERN virtual ~AMQHeartbeatBody(); - inline uint32_t encodedSize() const { return 0; } - inline uint8_t type() const { return HEARTBEAT_BODY; } - inline void encode(Buffer& ) const {} - inline void decode(Buffer& , uint32_t /*size*/) {} - QPID_COMMON_EXTERN virtual void print(std::ostream& out) const; - void accept(AMQBodyConstVisitor& v) const { v.visit(*this); } - boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); } -}; - -} -} - -#endif diff --git a/cpp/src/qpid/framing/AMQMethodBody.cpp b/cpp/src/qpid/framing/AMQMethodBody.cpp deleted file mode 100644 index 594af4c6dc..0000000000 --- a/cpp/src/qpid/framing/AMQMethodBody.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/AMQMethodBody.h" - -namespace qpid { -namespace framing { - -AMQMethodBody::~AMQMethodBody() {} - -}} // namespace qpid::framing diff --git a/cpp/src/qpid/framing/AMQMethodBody.h b/cpp/src/qpid/framing/AMQMethodBody.h deleted file mode 100644 index c634180712..0000000000 --- a/cpp/src/qpid/framing/AMQMethodBody.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _AMQMethodBody_ -#define _AMQMethodBody_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/CommonImportExport.h" - -#include <boost/shared_ptr.hpp> -#include <ostream> -#include <assert.h> - -namespace qpid { -namespace framing { - -class Buffer; -class AMQP_ServerOperations; -class MethodBodyConstVisitor; - -class AMQMethodBody : public AMQBody { - public: - AMQMethodBody() {} - QPID_COMMON_EXTERN virtual ~AMQMethodBody(); - - virtual void accept(MethodBodyConstVisitor&) const = 0; - - virtual MethodId amqpMethodId() const = 0; - virtual ClassId amqpClassId() const = 0; - virtual bool isContentBearing() const = 0; - virtual bool resultExpected() const = 0; - virtual bool responseExpected() const = 0; - - template <class T> bool isA() const { - return amqpClassId()==T::CLASS_ID && amqpMethodId()==T::METHOD_ID; - } - - virtual uint32_t encodedSize() const = 0; - virtual uint8_t type() const { return METHOD_BODY; } - - virtual bool isSync() const { return false; /*only ModelMethods can have the sync flag set*/ } - virtual void setSync(bool) const { /*only ModelMethods can have the sync flag set*/ } - - AMQMethodBody* getMethod() { return this; } - const AMQMethodBody* getMethod() const { return this; } - void accept(AMQBodyConstVisitor& v) const { v.visit(*this); } -}; - - -}} // namespace qpid::framing - - -#endif diff --git a/cpp/src/qpid/framing/AMQP_HighestVersion.h b/cpp/src/qpid/framing/AMQP_HighestVersion.h deleted file mode 100644 index 42139c7937..0000000000 --- a/cpp/src/qpid/framing/AMQP_HighestVersion.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/* - * This file used to be auto-generated by Qpid Gentools v.0.1 - * its here temporarily until we get a full solution to multi-version support - */ -#ifndef qpid_framing_highestProtocolVersion__ -#define qpid_framing_highestProtocolVersion__ - -#include "qpid/framing/ProtocolVersion.h" - - -namespace qpid { -namespace framing { - -static ProtocolVersion highestProtocolVersion(0, 10); - -} /* namespace framing */ -} /* namespace qpid */ - -#endif diff --git a/cpp/src/qpid/framing/AccumulatedAck.cpp b/cpp/src/qpid/framing/AccumulatedAck.cpp deleted file mode 100644 index 2e6433a82f..0000000000 --- a/cpp/src/qpid/framing/AccumulatedAck.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/AccumulatedAck.h" - -#include <assert.h> -#include <iostream> -#include <boost/bind.hpp> - -using std::list; -using std::max; -using std::min; -using namespace qpid::framing; - -AccumulatedAck::AccumulatedAck(SequenceNumber r) : mark(r) {} - -void AccumulatedAck::update(SequenceNumber first, SequenceNumber last){ - assert(first <= last); - if (last < mark) return; - - - Range r(first, last); - bool handled = false; - bool markMerged = false; - list<Range>::iterator merged = ranges.end(); - if (r.mergeable(mark)) { - mark = r.end; - markMerged = true; - handled = true; - } else { - for (list<Range>::iterator i = ranges.begin(); i != ranges.end() && !handled; i++) { - if (i->merge(r)) { - merged = i; - handled = true; - } else if (r.start < i->start) { - ranges.insert(i, r); - handled = true; - } - } - } - if (!handled) { - ranges.push_back(r); - } else { - while (!ranges.empty() && ranges.front().end <= mark) { - ranges.pop_front(); - } - if (markMerged) { - //new range is incorporated, but may be possible to consolidate - merged = ranges.begin(); - while (merged != ranges.end() && merged->mergeable(mark)) { - mark = merged->end; - merged = ranges.erase(merged); - } - } - if (merged != ranges.end()) { - //consolidate ranges - list<Range>::iterator i = merged; - list<Range>::iterator j = i++; - while (i != ranges.end() && j->merge(*i)) { - j = i++; - } - } - } -} - -void AccumulatedAck::consolidate(){} - -void AccumulatedAck::clear(){ - mark = SequenceNumber(0);//not sure that this is valid when wraparound is a possibility - ranges.clear(); -} - -bool AccumulatedAck::covers(SequenceNumber tag) const{ - if (tag <= mark) return true; - for (list<Range>::const_iterator i = ranges.begin(); i != ranges.end(); i++) { - if (i->contains(tag)) return true; - } - return false; -} - -void AccumulatedAck::collectRanges(SequenceNumberSet& set) const -{ - for (list<Range>::const_iterator i = ranges.begin(); i != ranges.end(); i++) { - set.push_back(i->start); - set.push_back(i->end); - } -} - -void AccumulatedAck::update(const SequenceNumber cumulative, const SequenceNumberSet& range) -{ - update(mark, cumulative); - range.processRanges(*this); -} - - -bool Range::contains(SequenceNumber i) const -{ - return i >= start && i <= end; -} - -bool Range::intersect(const Range& r) const -{ - return r.contains(start) || r.contains(end) || contains(r.start) || contains(r.end); -} - -bool Range::merge(const Range& r) -{ - if (intersect(r) || mergeable(r.end) || r.mergeable(end)) { - start = min(start, r.start); - end = max(end, r.end); - return true; - } else { - return false; - } -} - -bool Range::mergeable(const SequenceNumber& s) const -{ - if (contains(s) || start - s == 1) { - return true; - } else { - return false; - } -} - -Range::Range(SequenceNumber s, SequenceNumber e) : start(s), end(e) {} - - -namespace qpid{ -namespace framing{ - std::ostream& operator<<(std::ostream& out, const Range& r) - { - out << "[" << r.start.getValue() << "-" << r.end.getValue() << "]"; - return out; - } - - std::ostream& operator<<(std::ostream& out, const AccumulatedAck& a) - { - out << "{mark: " << a.mark.getValue() << ", ranges: ("; - for (list<Range>::const_iterator i = a.ranges.begin(); i != a.ranges.end(); i++) { - if (i != a.ranges.begin()) out << ", "; - out << *i; - } - out << ")]"; - return out; - } -}} diff --git a/cpp/src/qpid/framing/AccumulatedAck.h b/cpp/src/qpid/framing/AccumulatedAck.h deleted file mode 100644 index 8e241b4ba1..0000000000 --- a/cpp/src/qpid/framing/AccumulatedAck.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _AccumulatedAck_ -#define _AccumulatedAck_ - -#include <algorithm> -#include <functional> -#include <list> -#include <ostream> -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceNumberSet.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { - namespace framing { - - struct Range - { - SequenceNumber start; - SequenceNumber end; - - Range(SequenceNumber s, SequenceNumber e); - bool contains(SequenceNumber i) const; - bool intersect(const Range& r) const; - bool merge(const Range& r); - bool mergeable(const SequenceNumber& r) const; - }; - /** - * Keeps an accumulated record of acknowledged messages (by delivery - * tag). - */ - class AccumulatedAck { - public: - /** - * Everything up to this value has been acknowledged. - */ - SequenceNumber mark; - /** - * List of individually acknowledged messages greater than the - * 'mark'. - */ - std::list<Range> ranges; - - QPID_COMMON_EXTERN explicit AccumulatedAck(SequenceNumber r = SequenceNumber()); - QPID_COMMON_EXTERN void update(SequenceNumber firstTag, SequenceNumber lastTag); - QPID_COMMON_EXTERN void consolidate(); - QPID_COMMON_EXTERN void clear(); - QPID_COMMON_EXTERN bool covers(SequenceNumber tag) const; - void collectRanges(SequenceNumberSet& set) const; - QPID_COMMON_EXTERN void update(const SequenceNumber cumulative, const SequenceNumberSet& range); - void operator()(SequenceNumber first, SequenceNumber last) { update(first, last); } - }; - QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const Range&); - QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const AccumulatedAck&); - } -} - - -#endif diff --git a/cpp/src/qpid/framing/Array.cpp b/cpp/src/qpid/framing/Array.cpp deleted file mode 100644 index 454e8e298f..0000000000 --- a/cpp/src/qpid/framing/Array.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/Array.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" -#include <assert.h> - -namespace qpid { -namespace framing { - -Array::Array() : type(TYPE_CODE_VOID) {} - -Array::Array(TypeCode t) : type(t) {} - -Array::Array(uint8_t t) : type(typeCode(t)) {} - -Array::Array(const std::vector<std::string>& in) -{ - type = TYPE_CODE_STR16; - for (std::vector<std::string>::const_iterator i = in.begin(); i != in.end(); ++i) { - ValuePtr value(new Str16Value(*i)); - values.push_back(value); - } -} - -uint32_t Array::encodedSize() const { - //note: size is only included when used as a 'top level' type - uint32_t len(4/*size*/ + 1/*type*/ + 4/*count*/); - for(ValueVector::const_iterator i = values.begin(); i != values.end(); ++i) { - len += (*i)->getData().encodedSize(); - } - return len; -} - -int Array::count() const { - return values.size(); -} - -std::ostream& operator<<(std::ostream& out, const Array& a) { - out << typeName(a.getType()) << "{"; - for(Array::ValueVector::const_iterator i = a.values.begin(); i != a.values.end(); ++i) { - if (i != a.values.begin()) out << ", "; - (*i)->print(out); - } - return out << "}"; -} - -void Array::encode(Buffer& buffer) const{ - buffer.putLong(encodedSize() - 4);//size added only when array is a top-level type - buffer.putOctet(type); - buffer.putLong(count()); - for (ValueVector::const_iterator i = values.begin(); i!=values.end(); ++i) { - (*i)->getData().encode(buffer); - } -} - -void Array::decode(Buffer& buffer){ - values.clear(); - uint32_t size = buffer.getLong();//size added only when array is a top-level type - uint32_t available = buffer.available(); - if (available < size) { - throw IllegalArgumentException(QPID_MSG("Not enough data for array, expected " - << size << " bytes but only " << available << " available")); - } - if (size) { - type = TypeCode(buffer.getOctet()); - uint32_t count = buffer.getLong(); - - FieldValue dummy; - dummy.setType(type); - available = buffer.available(); - if (available < count * dummy.getData().encodedSize()) { - throw IllegalArgumentException(QPID_MSG("Not enough data for array, expected " - << count << " items of " << dummy.getData().encodedSize() - << " bytes each but only " << available << " bytes available")); - } - - for (uint32_t i = 0; i < count; i++) { - ValuePtr value(new FieldValue); - value->setType(type); - value->getData().decode(buffer); - values.push_back(ValuePtr(value)); - } - } -} - - -bool Array::operator==(const Array& x) const { - if (type != x.type) return false; - if (values.size() != x.values.size()) return false; - - for (ValueVector::const_iterator i = values.begin(), j = x.values.begin(); i != values.end(); ++i, ++j) { - if (*(i->get()) != *(j->get())) return false; - } - - return true; -} - -void Array::insert(iterator i, ValuePtr value) { - if (type != value->getType()) { - // FIXME aconway 2008-10-31: put meaningful strings in this message. - throw Exception(QPID_MSG("Wrong type of value in Array, expected " << type - << " but found " << TypeCode(value->getType()))); - } - values.insert(i, value); -} - - -} -} diff --git a/cpp/src/qpid/framing/Blob.cpp b/cpp/src/qpid/framing/Blob.cpp deleted file mode 100644 index 0c8316f3d2..0000000000 --- a/cpp/src/qpid/framing/Blob.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/Blob.h" - - -namespace qpid { -namespace framing { - -void BlobHelper<void>::destroy(void*) {} - -void BlobHelper<void>::copy(void*, const void*) {} - -}} // namespace qpid::framing diff --git a/cpp/src/qpid/framing/Blob.h b/cpp/src/qpid/framing/Blob.h deleted file mode 100644 index 9878d92fe4..0000000000 --- a/cpp/src/qpid/framing/Blob.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - diff --git a/cpp/src/qpid/framing/BodyFactory.h b/cpp/src/qpid/framing/BodyFactory.h deleted file mode 100644 index 6a8d9b1988..0000000000 --- a/cpp/src/qpid/framing/BodyFactory.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_FRAMING_BODYFACTORY_H -#define QPID_FRAMING_BODYFACTORY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace framing { - -/** - * Indirect creation of body types to allow centralized changes to - * memory management strategy. - */ -class BodyFactory { - public: - template <class BodyType> static boost::intrusive_ptr<BodyType> create() { - return new BodyType; - } - - template <class BodyType> static boost::intrusive_ptr<BodyType> copy(const BodyType& body) { - return new BodyType(body); - } -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_BODYFACTORY_H*/ diff --git a/cpp/src/qpid/framing/BodyHandler.cpp b/cpp/src/qpid/framing/BodyHandler.cpp deleted file mode 100644 index db302b1e4c..0000000000 --- a/cpp/src/qpid/framing/BodyHandler.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/BodyHandler.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeartbeatBody.h" -#include <boost/cast.hpp> -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" - -using namespace qpid::framing; -using namespace boost; - -BodyHandler::~BodyHandler() {} - -// TODO aconway 2007-08-13: Replace with visitor. -void BodyHandler::handleBody(AMQBody* body) { - switch(body->type()) - { - case METHOD_BODY: - handleMethod(polymorphic_downcast<AMQMethodBody*>(body)); - break; - case HEADER_BODY: - handleHeader(polymorphic_downcast<AMQHeaderBody*>(body)); - break; - case CONTENT_BODY: - handleContent(polymorphic_downcast<AMQContentBody*>(body)); - break; - case HEARTBEAT_BODY: - handleHeartbeat(polymorphic_downcast<AMQHeartbeatBody*>(body)); - break; - default: - throw FramingErrorException( - QPID_MSG("Invalid frame type " << body->type())); - } -} - diff --git a/cpp/src/qpid/framing/BodyHandler.h b/cpp/src/qpid/framing/BodyHandler.h deleted file mode 100644 index 9ded737195..0000000000 --- a/cpp/src/qpid/framing/BodyHandler.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _BodyHandler_ -#define _BodyHandler_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace framing { -class AMQBody; -class AMQMethodBody; -class AMQHeaderBody; -class AMQContentBody; -class AMQHeartbeatBody; - -// TODO aconway 2007-08-10: rework using Visitor pattern? - -/** - * Interface to handle incoming frame bodies. - * Derived classes provide logic for each frame type. - */ -class BodyHandler { - public: - virtual ~BodyHandler(); - virtual void handleBody(AMQBody* body); - - protected: - virtual void handleMethod(AMQMethodBody*) = 0; - virtual void handleHeader(AMQHeaderBody*) = 0; - virtual void handleContent(AMQContentBody*) = 0; - virtual void handleHeartbeat(AMQHeartbeatBody*) = 0; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/framing/Buffer.cpp b/cpp/src/qpid/framing/Buffer.cpp deleted file mode 100644 index 5a5bc0325e..0000000000 --- a/cpp/src/qpid/framing/Buffer.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/Msg.h" -#include <string.h> -#include <boost/format.hpp> -namespace qpid { - -namespace framing { - -Buffer::Buffer(char* _data, uint32_t _size) - : size(_size), data(_data), position(0) { -} - -void Buffer::record(){ - r_position = position; -} - -void Buffer::restore(bool reRecord){ - uint32_t savedPosition = position; - - position = r_position; - - if (reRecord) - r_position = savedPosition; -} - -void Buffer::reset(){ - position = 0; -} - -/////////////////////////////////////////////////// - -void Buffer::putOctet(uint8_t i){ - data[position++] = i; - assert(position <= size); -} - -void Buffer::putShort(uint16_t i){ - uint16_t b = i; - data[position++] = (uint8_t) (0xFF & (b >> 8)); - data[position++] = (uint8_t) (0xFF & b); - assert(position <= size); -} - -void Buffer::putLong(uint32_t i){ - uint32_t b = i; - data[position++] = (uint8_t) (0xFF & (b >> 24)); - data[position++] = (uint8_t) (0xFF & (b >> 16)); - data[position++] = (uint8_t) (0xFF & (b >> 8)); - data[position++] = (uint8_t) (0xFF & b); - assert(position <= size); -} - -void Buffer::putLongLong(uint64_t i){ - uint32_t hi = i >> 32; - uint32_t lo = i; - putLong(hi); - putLong(lo); -} - -void Buffer::putInt8(int8_t i){ - data[position++] = (uint8_t) i; - assert(position <= size); -} - -void Buffer::putInt16(int16_t i){ - putShort((uint16_t) i); -} - -void Buffer::putInt32(int32_t i){ - putLong((uint32_t) i); -} - -void Buffer::putInt64(int64_t i){ - putLongLong((uint64_t) i); -} - -void Buffer::putFloat(float f){ - union { - uint32_t i; - float f; - } val; - - val.f = f; - putLong (val.i); -} - -void Buffer::putDouble(double f){ - union { - uint64_t i; - double f; - } val; - - val.f = f; - putLongLong (val.i); -} - -void Buffer::putBin128(const uint8_t* b){ - memcpy (data + position, b, 16); - position += 16; -} - -uint8_t Buffer::getOctet(){ - uint8_t octet = static_cast<uint8_t>(data[position++]); - assert(position <= size); - return octet; -} - -uint16_t Buffer::getShort(){ - uint16_t hi = (unsigned char) data[position++]; - hi = hi << 8; - hi |= (unsigned char) data[position++]; - assert(position <= size); - return hi; -} - -uint32_t Buffer::getLong(){ - uint32_t a = (unsigned char) data[position++]; - uint32_t b = (unsigned char) data[position++]; - uint32_t c = (unsigned char) data[position++]; - uint32_t d = (unsigned char) data[position++]; - assert(position <= size); - a = a << 24; - a |= b << 16; - a |= c << 8; - a |= d; - return a; -} - -uint64_t Buffer::getLongLong(){ - uint64_t hi = getLong(); - uint64_t lo = getLong(); - hi = hi << 32; - return hi | lo; -} - -int8_t Buffer::getInt8(){ - int8_t i = static_cast<int8_t>(data[position++]); - assert(position <= size); - return i; -} - -int16_t Buffer::getInt16(){ - return (int16_t) getShort(); -} - -int32_t Buffer::getInt32(){ - return (int32_t) getLong(); -} - -int64_t Buffer::getInt64(){ - return (int64_t) getLongLong(); -} - -float Buffer::getFloat(){ - union { - uint32_t i; - float f; - } val; - val.i = getLong(); - return val.f; -} - -double Buffer::getDouble(){ - union { - uint64_t i; - double f; - } val; - val.i = getLongLong(); - return val.f; -} - -template <> -uint64_t Buffer::getUInt<1>() { - return getOctet(); -} - -template <> -uint64_t Buffer::getUInt<2>() { - return getShort(); -} - -template <> -uint64_t Buffer::getUInt<4>() { - return getLong(); -} - -template <> -uint64_t Buffer::getUInt<8>() { - return getLongLong(); -} - -template <> -void Buffer::putUInt<1>(uint64_t i) { - if (std::numeric_limits<uint8_t>::min() <= i && i <= std::numeric_limits<uint8_t>::max()) { - putOctet(i); - return; - } - throw Exception(QPID_MSG("Could not encode (" << i << ") as uint8_t.")); -} - -template <> -void Buffer::putUInt<2>(uint64_t i) { - if (std::numeric_limits<uint16_t>::min() <= i && i <= std::numeric_limits<uint16_t>::max()) { - putShort(i); - return; - } - throw Exception(QPID_MSG("Could not encode (" << i << ") as uint16_t.")); -} - -template <> -void Buffer::putUInt<4>(uint64_t i) { - if (std::numeric_limits<uint32_t>::min() <= i && i <= std::numeric_limits<uint32_t>::max()) { - putLong(i); - return; - } - throw Exception(QPID_MSG("Could not encode (" << i << ") as uint32_t.")); -} - -template <> -void Buffer::putUInt<8>(uint64_t i) { - putLongLong(i); -} - -void Buffer::putShortString(const string& s){ - size_t slen = s.length(); - if (slen <= std::numeric_limits<uint8_t>::max()) { - uint8_t len = (uint8_t) slen; - checkAvailable(slen + 1); - putOctet(len); - s.copy(data + position, len); - position += len; - return; - } - throw Exception(QPID_MSG("Could not encode string of " << slen << " bytes as uint8_t string.")); -} - -void Buffer::putMediumString(const string& s){ - size_t slen = s.length(); - if (slen <= std::numeric_limits<uint16_t>::max()) { - uint16_t len = (uint16_t) slen; - checkAvailable(slen + 2); - putShort(len); - s.copy(data + position, len); - position += len; - return; - } - throw Exception(QPID_MSG("Could not encode string of " << slen << " bytes as uint16_t string.")); -} - -void Buffer::putLongString(const string& s){ - uint32_t len = s.length(); - checkAvailable(len + 4); - putLong(len); - s.copy(data + position, len); - position += len; -} - -void Buffer::getShortString(string& s){ - uint8_t len = getOctet(); - checkAvailable(len); - s.assign(data + position, len); - position += len; -} - -void Buffer::getMediumString(string& s){ - uint16_t len = getShort(); - checkAvailable(len); - s.assign(data + position, len); - position += len; -} - -void Buffer::getLongString(string& s){ - uint32_t len = getLong(); - checkAvailable(len); - s.assign(data + position, len); - position += len; -} - -void Buffer::getBin128(uint8_t* b){ - memcpy (b, data + position, 16); - position += 16; -} - -void Buffer::putRawData(const string& s){ - uint32_t len = s.length(); - checkAvailable(len); - s.copy(data + position, len); - position += len; -} - -void Buffer::getRawData(string& s, uint32_t len){ - checkAvailable(len); - s.assign(data + position, len); - position += len; -} - -void Buffer::putRawData(const uint8_t* s, size_t len){ - checkAvailable(len); - memcpy(data + position, s, len); - position += len; -} - -void Buffer::getRawData(uint8_t* s, size_t len){ - checkAvailable(len); - memcpy(s, data + position, len); - position += len; -} - -void Buffer::dump(std::ostream& out) const { - for (uint32_t i = position; i < size; i++) - { - if (i != position) - out << " "; - out << boost::format("%02x") % ((unsigned) (uint8_t) data[i]); - } -} - -std::ostream& operator<<(std::ostream& out, const Buffer& b){ - out << "Buffer["; - b.dump(out); - return out << "]"; -} - -}} diff --git a/cpp/src/qpid/framing/ChannelHandler.h b/cpp/src/qpid/framing/ChannelHandler.h deleted file mode 100644 index ddab204578..0000000000 --- a/cpp/src/qpid/framing/ChannelHandler.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef QPID_FRAMING_CHANNELHANDLER_H -#define QPID_FRAMING_CHANNELHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/AMQFrame.h" - -namespace qpid { -namespace framing { - -/** - * Sets the channel number on outgoing frames. - */ -class ChannelHandler : public FrameHandler -{ - public: - ChannelHandler(uint16_t channelId=0, FrameHandler* next=0) - : FrameHandler(next), channel(channelId) {} - void handle(AMQFrame& frame) { - frame.setChannel(channel); - next->handle(frame); - } - uint16_t get() const { return channel; } - ChannelHandler& set(uint16_t ch) { channel=ch; return *this; } - operator uint16_t() const { return get(); } - ChannelHandler& operator=(uint16_t ch) { return set(ch); } - - private: - uint16_t channel; -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_CHANNELHANDLER_H*/ diff --git a/cpp/src/qpid/framing/Endian.cpp b/cpp/src/qpid/framing/Endian.cpp deleted file mode 100644 index 5acc3c459f..0000000000 --- a/cpp/src/qpid/framing/Endian.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/Endian.h" - -namespace qpid { -namespace framing { - -Endian::Endian() : littleEndian(!testBigEndian()) {} - -bool Endian::testBigEndian() -{ - uint16_t a = 1; - uint16_t b; - uint8_t* p = (uint8_t*) &b; - p[0] = 0xFF & (a >> 8); - p[1] = 0xFF & (a); - return a == b; -} - -uint8_t* Endian::convertIfRequired(uint8_t* const octets, int width) -{ - if (instance.littleEndian) { - for (int i = 0; i < (width/2); i++) { - uint8_t temp = octets[i]; - octets[i] = octets[width - (1 + i)]; - octets[width - (1 + i)] = temp; - } - } - return octets; -} - -const Endian Endian::instance; - -}} // namespace qpid::framing diff --git a/cpp/src/qpid/framing/Endian.h b/cpp/src/qpid/framing/Endian.h deleted file mode 100644 index 077d5a3e9b..0000000000 --- a/cpp/src/qpid/framing/Endian.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef QPID_FRAMING_ENDIAN_H -#define QPID_FRAMING_ENDIAN_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" - -namespace qpid { -namespace framing { - -/** - * Conversion utility for little-endian platforms that need to convert - * to and from network ordered octet sequences - */ -class Endian -{ - public: - static uint8_t* convertIfRequired(uint8_t* const octets, int width); - private: - const bool littleEndian; - Endian(); - static const Endian instance; - static bool testBigEndian(); -}; -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_ENDIAN_H*/ diff --git a/cpp/src/qpid/framing/FieldTable.cpp b/cpp/src/qpid/framing/FieldTable.cpp deleted file mode 100644 index 21eaea0f4d..0000000000 --- a/cpp/src/qpid/framing/FieldTable.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/Endian.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" -#include <assert.h> - -namespace qpid { -namespace framing { - -FieldTable::FieldTable(const FieldTable& ft) -{ - *this = ft; -} - -FieldTable& FieldTable::operator=(const FieldTable& ft) -{ - clear(); - values = ft.values; - return *this; -} - -FieldTable::~FieldTable() {} - -uint32_t FieldTable::encodedSize() const { - uint32_t len(4/*size field*/ + 4/*count field*/); - for(ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) { - // shortstr_len_byte + key size + value size - len += 1 + (i->first).size() + (i->second)->encodedSize(); - } - return len; -} - -int FieldTable::count() const { - return values.size(); -} - -namespace -{ -std::ostream& operator<<(std::ostream& out, const FieldTable::ValueMap::value_type& i) { - return out << i.first << ":" << *i.second; -} -} - -std::ostream& operator<<(std::ostream& out, const FieldTable& t) { - out << "{"; - FieldTable::ValueMap::const_iterator i = t.begin(); - if (i != t.end()) out << *i++; - while (i != t.end()) - { - out << "," << *i++; - } - return out << "}"; -} - -void FieldTable::set(const std::string& name, const ValuePtr& value){ - values[name] = value; -} - -void FieldTable::setString(const std::string& name, const std::string& value){ - values[name] = ValuePtr(new Str16Value(value)); -} - -void FieldTable::setInt(const std::string& name, const int value){ - values[name] = ValuePtr(new IntegerValue(value)); -} - -void FieldTable::setInt64(const std::string& name, const int64_t value){ - values[name] = ValuePtr(new Integer64Value(value)); -} - -void FieldTable::setTimestamp(const std::string& name, const uint64_t value){ - values[name] = ValuePtr(new TimeValue(value)); -} - -void FieldTable::setUInt64(const std::string& name, const uint64_t value){ - values[name] = ValuePtr(new Unsigned64Value(value)); -} - -void FieldTable::setTable(const std::string& name, const FieldTable& value) -{ - values[name] = ValuePtr(new FieldTableValue(value)); -} -void FieldTable::setArray(const std::string& name, const Array& value) -{ - values[name] = ValuePtr(new ArrayValue(value)); -} - -void FieldTable::setFloat(const std::string& name, const float value){ - values[name] = ValuePtr(new FloatValue(value)); -} - -void FieldTable::setDouble(const std::string& name, double value){ - values[name] = ValuePtr(new DoubleValue(value)); -} - -FieldTable::ValuePtr FieldTable::get(const std::string& name) const -{ - ValuePtr value; - ValueMap::const_iterator i = values.find(name); - if ( i!=values.end() ) - value = i->second; - return value; -} - -namespace { - template <class T> T default_value() { return T(); } - template <> int default_value<int>() { return 0; } - //template <> uint64_t default_value<uint64_t>() { return 0; } -} - -template <class T> -T getValue(const FieldTable::ValuePtr value) -{ - if (!value || !value->convertsTo<T>()) - return default_value<T>(); - - return value->get<T>(); -} - -std::string FieldTable::getAsString(const std::string& name) const { - return getValue<std::string>(get(name)); -} - -int FieldTable::getAsInt(const std::string& name) const { - return getValue<int>(get(name)); -} - -uint64_t FieldTable::getAsUInt64(const std::string& name) const { - return static_cast<uint64_t>( getValue<int64_t>(get(name))); -} - -int64_t FieldTable::getAsInt64(const std::string& name) const { - return getValue<int64_t>(get(name)); -} - -bool FieldTable::getTable(const std::string& name, FieldTable& value) const { - return getEncodedValue<FieldTable>(get(name), value); -} - -bool FieldTable::getArray(const std::string& name, Array& value) const { - return getEncodedValue<Array>(get(name), value); -} - -template <class T, int width, uint8_t typecode> -bool getRawFixedWidthValue(FieldTable::ValuePtr vptr, T& value) -{ - if (vptr && vptr->getType() == typecode) { - value = vptr->get<T>(); - return true; - } - return false; -} - -bool FieldTable::getFloat(const std::string& name, float& value) const { - return getRawFixedWidthValue<float, 4, 0x23>(get(name), value); -} - -bool FieldTable::getDouble(const std::string& name, double& value) const { - return getRawFixedWidthValue<double, 8, 0x33>(get(name), value); -} - -//uint64_t FieldTable::getTimestamp(const std::string& name) const { -// return getValue<uint64_t>(name); -//} - -void FieldTable::encode(Buffer& buffer) const { - buffer.putLong(encodedSize() - 4); - buffer.putLong(values.size()); - for (ValueMap::const_iterator i = values.begin(); i!=values.end(); ++i) { - buffer.putShortString(i->first); - i->second->encode(buffer); - } -} - -void FieldTable::decode(Buffer& buffer){ - clear(); - uint32_t len = buffer.getLong(); - if (len) { - uint32_t available = buffer.available(); - if (available < len) - throw IllegalArgumentException(QPID_MSG("Not enough data for field table.")); - uint32_t count = buffer.getLong(); - uint32_t leftover = available - len; - while(buffer.available() > leftover && count--){ - std::string name; - ValuePtr value(new FieldValue); - - buffer.getShortString(name); - value->decode(buffer); - values[name] = ValuePtr(value); - } - } -} - -bool FieldTable::operator==(const FieldTable& x) const { - if (values.size() != x.values.size()) return false; - for (ValueMap::const_iterator i = values.begin(); i != values.end(); ++i) { - ValueMap::const_iterator j = x.values.find(i->first); - if (j == x.values.end()) return false; - if (*(i->second) != *(j->second)) return false; - } - return true; -} - -void FieldTable::erase(const std::string& name) -{ - if (values.find(name) != values.end()) - values.erase(name); -} - -std::pair<FieldTable::ValueMap::iterator, bool> FieldTable::insert(const ValueMap::value_type& value) -{ - return values.insert(value); -} - -FieldTable::ValueMap::iterator FieldTable::insert(ValueMap::iterator position, const ValueMap::value_type& value) -{ - return values.insert(position, value); -} - - -} -} diff --git a/cpp/src/qpid/framing/FieldValue.cpp b/cpp/src/qpid/framing/FieldValue.cpp deleted file mode 100644 index ce5a50117c..0000000000 --- a/cpp/src/qpid/framing/FieldValue.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/Endian.h" -#include "qpid/framing/List.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" - -namespace qpid { -namespace framing { - -uint8_t FieldValue::getType() const -{ - return typeOctet; -} - -void FieldValue::setType(uint8_t type) -{ - typeOctet = type; - if (typeOctet == 0xA8) { - data.reset(new EncodedValue<FieldTable>()); - } else if (typeOctet == 0xA9) { - data.reset(new EncodedValue<List>()); - } else if (typeOctet == 0xAA) { - data.reset(new EncodedValue<Array>()); - } else { - uint8_t lenType = typeOctet >> 4; - switch(lenType){ - case 0: - data.reset(new FixedWidthValue<1>()); - break; - case 1: - data.reset(new FixedWidthValue<2>()); - break; - case 2: - data.reset(new FixedWidthValue<4>()); - break; - case 3: - data.reset(new FixedWidthValue<8>()); - break; - case 4: - data.reset(new FixedWidthValue<16>()); - break; - case 5: - data.reset(new FixedWidthValue<32>()); - break; - case 6: - data.reset(new FixedWidthValue<64>()); - break; - case 7: - data.reset(new FixedWidthValue<128>()); - break; - case 8: - data.reset(new VariableWidthValue<1>()); - break; - case 9: - data.reset(new VariableWidthValue<2>()); - break; - case 0xA: - data.reset(new VariableWidthValue<4>()); - break; - case 0xC: - data.reset(new FixedWidthValue<5>()); - break; - case 0xD: - data.reset(new FixedWidthValue<9>()); - break; - case 0xF: - data.reset(new FixedWidthValue<0>()); - break; - default: - throw IllegalArgumentException(QPID_MSG("Unknown field table value type: " << (int)typeOctet)); - } - } -} - -void FieldValue::decode(Buffer& buffer) -{ - setType(buffer.getOctet()); - data->decode(buffer); -} - -void FieldValue::encode(Buffer& buffer) -{ - buffer.putOctet(typeOctet); - data->encode(buffer); -} - -bool FieldValue::operator==(const FieldValue& v) const -{ - return - typeOctet == v.typeOctet && - *data == *v.data; -} - -Str8Value::Str8Value(const std::string& v) : - FieldValue( - TYPE_CODE_STR8, - new VariableWidthValue<1>( - reinterpret_cast<const uint8_t*>(v.data()), - reinterpret_cast<const uint8_t*>(v.data()+v.size()))) -{ -} - -Str16Value::Str16Value(const std::string& v) : - FieldValue( - 0x95, - new VariableWidthValue<2>( - reinterpret_cast<const uint8_t*>(v.data()), - reinterpret_cast<const uint8_t*>(v.data()+v.size()))) -{} - -Var16Value::Var16Value(const std::string& v, uint8_t code) : - FieldValue( - code, - new VariableWidthValue<2>( - reinterpret_cast<const uint8_t*>(v.data()), - reinterpret_cast<const uint8_t*>(v.data()+v.size()))) -{} -Var32Value::Var32Value(const std::string& v, uint8_t code) : - FieldValue( - code, - new VariableWidthValue<4>( - reinterpret_cast<const uint8_t*>(v.data()), - reinterpret_cast<const uint8_t*>(v.data()+v.size()))) -{} - -Struct32Value::Struct32Value(const std::string& v) : - FieldValue( - 0xAB, - new VariableWidthValue<4>( - reinterpret_cast<const uint8_t*>(v.data()), - reinterpret_cast<const uint8_t*>(v.data()+v.size()))) -{} - -IntegerValue::IntegerValue(int v) : - FieldValue(0x21, new FixedWidthValue<4>(v)) -{} - -FloatValue::FloatValue(float v) : - FieldValue(0x23, new FixedWidthValue<4>(Endian::convertIfRequired(reinterpret_cast<uint8_t*>(&v), 4))) -{} - -DoubleValue::DoubleValue(double v) : - FieldValue(0x33, new FixedWidthValue<8>(Endian::convertIfRequired(reinterpret_cast<uint8_t*>(&v), 8))) -{} - -Integer64Value::Integer64Value(int64_t v) : - FieldValue(0x31, new FixedWidthValue<8>(v)) -{} - -Unsigned64Value::Unsigned64Value(uint64_t v) : - FieldValue(0x32, new FixedWidthValue<8>(v)) -{} - - -TimeValue::TimeValue(uint64_t v) : - FieldValue(0x38, new FixedWidthValue<8>(v)) -{ -} - -FieldTableValue::FieldTableValue(const FieldTable& f) : FieldValue(0xa8, new EncodedValue<FieldTable>(f)) -{ -} - -ListValue::ListValue(const List& l) : FieldValue(0xa9, new EncodedValue<List>(l)) -{ -} - -ArrayValue::ArrayValue(const Array& a) : FieldValue(0xaa, new EncodedValue<Array>(a)) -{ -} - -VoidValue::VoidValue() : FieldValue(0xf0, new FixedWidthValue<0>()) {} - -BoolValue::BoolValue(bool b) : - FieldValue(0x08, new FixedWidthValue<1>(b)) -{} - -Unsigned8Value::Unsigned8Value(uint8_t v) : - FieldValue(0x02, new FixedWidthValue<1>(v)) -{} -Unsigned16Value::Unsigned16Value(uint16_t v) : - FieldValue(0x12, new FixedWidthValue<2>(v)) -{} -Unsigned32Value::Unsigned32Value(uint32_t v) : - FieldValue(0x22, new FixedWidthValue<4>(v)) -{} - -Integer8Value::Integer8Value(int8_t v) : - FieldValue(0x01, new FixedWidthValue<1>(v)) -{} -Integer16Value::Integer16Value(int16_t v) : - FieldValue(0x11, new FixedWidthValue<2>(v)) -{} -UuidValue::UuidValue(const unsigned char* v) : - FieldValue(0x48, new FixedWidthValue<16>(v)) -{} - -void FieldValue::print(std::ostream& out) const { - data->print(out); - out << TypeCode(typeOctet) << '('; - if (data->convertsToString()) out << data->getString(); - else if (data->convertsToInt()) out << data->getInt(); - else data->print(out); - out << ')'; -} - -uint8_t* FieldValue::convertIfRequired(uint8_t* const octets, int width) -{ - return Endian::convertIfRequired(octets, width); -} - -}} diff --git a/cpp/src/qpid/framing/FrameDecoder.cpp b/cpp/src/qpid/framing/FrameDecoder.cpp deleted file mode 100644 index 90cbbd84a1..0000000000 --- a/cpp/src/qpid/framing/FrameDecoder.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/FrameDecoder.h" -#include "qpid/framing/Buffer.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" -#include <algorithm> -#include <string.h> - -namespace qpid { -namespace framing { - -namespace { -/** Append up to n bytes from start of buf to end of bytes. */ -void append(std::vector<char>& bytes, Buffer& buffer, size_t n) { - size_t oldSize = bytes.size(); - if ((n = std::min(n, size_t(buffer.available()))) == 0) - return; - bytes.resize(oldSize+n); - char* p = &bytes[oldSize]; - buffer.getRawData(reinterpret_cast<uint8_t*>(p), n); -} -} - -bool FrameDecoder::decode(Buffer& buffer) { - if (buffer.available() == 0) return false; - if (fragment.empty()) { - if (frame.decode(buffer)) // Decode from buffer - return true; - else // Store fragment - append(fragment, buffer, buffer.available()); - } - else { // Already have a fragment - // Get enough data to decode the frame size. - if (fragment.size() < AMQFrame::DECODE_SIZE_MIN) { - append(fragment, buffer, AMQFrame::DECODE_SIZE_MIN - fragment.size()); - } - if (fragment.size() >= AMQFrame::DECODE_SIZE_MIN) { - uint16_t size = AMQFrame::decodeSize(&fragment[0]); - if (size <= fragment.size()) - throw FramingErrorException(QPID_MSG("Frame size " << size << " is too small.")); - append(fragment, buffer, size-fragment.size()); - Buffer b(&fragment[0], fragment.size()); - if (frame.decode(b)) { - assert(b.available() == 0); - fragment.clear(); - return true; - } - } - } - return false; -} - -void FrameDecoder::setFragment(const char* data, size_t size) { - fragment.resize(size); - ::memcpy(&fragment[0], data, size); -} - -std::pair<const char*, size_t> FrameDecoder::getFragment() const { - return std::pair<const char*, size_t>(&fragment[0], fragment.size()); -} - -}} // namespace qpid::framing diff --git a/cpp/src/qpid/framing/FrameDecoder.h b/cpp/src/qpid/framing/FrameDecoder.h deleted file mode 100644 index 26bed6c447..0000000000 --- a/cpp/src/qpid/framing/FrameDecoder.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_FRAMING_FRAMEDECODER_H -#define QPID_FRAMING_FRAMEDECODER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/AMQFrame.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -/** - * Decode a frame from buffer. If buffer does not contain a complete - * frame, caches the fragment for the next call to decode. - */ -class FrameDecoder -{ - public: - QPID_COMMON_EXTERN bool decode(Buffer& buffer); - const AMQFrame& getFrame() const { return frame; } - AMQFrame& getFrame() { return frame; } - - void setFragment(const char*, size_t); - std::pair<const char*, size_t> getFragment() const; - - private: - std::vector<char> fragment; - AMQFrame frame; - -}; -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_FRAMEDECODER_H*/ diff --git a/cpp/src/qpid/framing/FrameDefaultVisitor.h b/cpp/src/qpid/framing/FrameDefaultVisitor.h deleted file mode 100644 index bd676960bf..0000000000 --- a/cpp/src/qpid/framing/FrameDefaultVisitor.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_FRAMING_FRAMEVISITOR_H -#define QPID_FRAMING_FRAMEVISITOR_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/MethodBodyDefaultVisitor.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeartbeatBody.h" - -namespace qpid { -namespace framing { -/** - * Visitor for all concrete frame body types, which combines - * AMQBodyConstVisitor and MethodBodyDefaultVisitor. - * - * Derived classes can override visit methods to specify actions. - * Derived classes must override defaultVisit(), which is called - * for any non-overridden visit functions. - * - */ -struct FrameDefaultVisitor : public AMQBodyConstVisitor, - protected MethodBodyDefaultVisitor -{ - virtual void defaultVisit(const AMQBody&) = 0; - void defaultVisit(const AMQMethodBody& method) { defaultVisit(static_cast<const AMQBody&>(method)); } - - void visit(const AMQHeaderBody& b) { defaultVisit(b); } - void visit(const AMQContentBody& b) { defaultVisit(b); } - void visit(const AMQHeartbeatBody& b) { defaultVisit(b); } - void visit(const AMQMethodBody& b) { b.accept(static_cast<MethodBodyDefaultVisitor&>(*this)); } - - using AMQBodyConstVisitor::visit; - using MethodBodyDefaultVisitor::visit; -}; - -}} // namespace qpid::framing - - -#endif /*!QPID_FRAMING_FRAMEVISITOR_H*/ diff --git a/cpp/src/qpid/framing/FrameHandler.h b/cpp/src/qpid/framing/FrameHandler.h deleted file mode 100644 index fa1fb535ef..0000000000 --- a/cpp/src/qpid/framing/FrameHandler.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef QPID_FRAMING_FRAMEHANDLER_H -#define QPID_FRAMING_FRAMEHANDLER_H -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/Handler.h" - -namespace qpid { -namespace framing { - -class AMQFrame; -typedef Handler<AMQFrame&> FrameHandler; - - -}} -#endif /*!QPID_FRAMING_FRAMEHANDLER_H*/ diff --git a/cpp/src/qpid/framing/FrameSet.cpp b/cpp/src/qpid/framing/FrameSet.cpp deleted file mode 100644 index 255aaf6e6b..0000000000 --- a/cpp/src/qpid/framing/FrameSet.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/frame_functors.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/TypeFilter.h" - -using namespace qpid::framing; -using namespace boost; - -FrameSet::FrameSet(const SequenceNumber& _id) : id(_id),contentSize(0),recalculateSize(true) { } -FrameSet::FrameSet(const FrameSet& original) : id(original.id), contentSize(0), recalculateSize(true) -{ - for (Frames::const_iterator i = original.begin(); i != original.end(); ++i) { - parts.push_back(AMQFrame(*(i->getBody()))); - parts.back().setFirstSegment(i->isFirstSegment()); - parts.back().setLastSegment(i->isLastSegment()); - parts.back().setFirstFrame(i->isFirstFrame()); - parts.back().setLastFrame(i->isLastFrame()); - } -} - -void FrameSet::append(const AMQFrame& part) -{ - parts.push_back(part); - recalculateSize = true; -} - -bool FrameSet::isComplete() const -{ - return !parts.empty() && parts.back().getEof() && parts.back().getEos(); -} - -bool FrameSet::isContentBearing() const -{ - const AMQMethodBody* method = getMethod(); - return method && method->isContentBearing(); -} - -const AMQMethodBody* FrameSet::getMethod() const -{ - return parts.empty() ? 0 : parts[0].getMethod(); -} - -AMQMethodBody* FrameSet::getMethod() -{ - return parts.empty() ? 0 : parts[0].getMethod(); -} - -const AMQHeaderBody* FrameSet::getHeaders() const -{ - return parts.size() < 2 ? 0 : parts[1].castBody<AMQHeaderBody>(); -} - -AMQHeaderBody* FrameSet::getHeaders() -{ - return parts.size() < 2 ? 0 : parts[1].castBody<AMQHeaderBody>(); -} - -uint64_t FrameSet::getContentSize() const -{ - if (recalculateSize) - { - SumBodySize sum; - map_if(sum, TypeFilter<CONTENT_BODY>()); - contentSize = sum.getSize(); - recalculateSize = false; - } - return contentSize; -} - -void FrameSet::getContent(std::string& out) const { - out.clear(); - out.reserve(getContentSize()); - for(Frames::const_iterator i = parts.begin(); i != parts.end(); i++) { - if (i->getBody()->type() == CONTENT_BODY) - out += i->castBody<AMQContentBody>()->getData(); - } -} - -std::string FrameSet::getContent() const { - std::string out; - getContent(out); - return out; -} diff --git a/cpp/src/qpid/framing/FrameSet.h b/cpp/src/qpid/framing/FrameSet.h deleted file mode 100644 index cae75e5ec8..0000000000 --- a/cpp/src/qpid/framing/FrameSet.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include "qpid/InlineVector.h" -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/CommonImportExport.h" - -#ifndef _FrameSet_ -#define _FrameSet_ - -namespace qpid { -namespace framing { - -/** - * Collects the frames representing a message. - */ -class FrameSet -{ - typedef InlineVector<AMQFrame, 4> Frames; - const SequenceNumber id; - Frames parts; - mutable uint64_t contentSize; - mutable bool recalculateSize; - -public: - typedef boost::shared_ptr<FrameSet> shared_ptr; - - QPID_COMMON_EXTERN FrameSet(const SequenceNumber& id); - QPID_COMMON_EXTERN FrameSet(const FrameSet&); - QPID_COMMON_EXTERN void append(const AMQFrame& part); - QPID_COMMON_EXTERN bool isComplete() const; - - QPID_COMMON_EXTERN uint64_t getContentSize() const; - - QPID_COMMON_EXTERN void getContent(std::string&) const; - QPID_COMMON_EXTERN std::string getContent() const; - - bool isContentBearing() const; - - QPID_COMMON_EXTERN const AMQMethodBody* getMethod() const; - QPID_COMMON_EXTERN AMQMethodBody* getMethod(); - QPID_COMMON_EXTERN const AMQHeaderBody* getHeaders() const; - QPID_COMMON_EXTERN AMQHeaderBody* getHeaders(); - - template <class T> bool isA() const { - const AMQMethodBody* method = getMethod(); - return method && method->isA<T>(); - } - - template <class T> const T* as() const { - const AMQMethodBody* method = getMethod(); - return (method && method->isA<T>()) ? dynamic_cast<const T*>(method) : 0; - } - - template <class T> T* as() { - AMQMethodBody* method = getMethod(); - return (method && method->isA<T>()) ? dynamic_cast<T*>(method) : 0; - } - - template <class T> const T* getHeaderProperties() const { - const AMQHeaderBody* header = getHeaders(); - return header ? header->get<T>() : 0; - } - - Frames::const_iterator begin() const { return parts.begin(); } - Frames::const_iterator end() const { return parts.end(); } - - const SequenceNumber& getId() const { return id; } - - template <class P> void remove(P predicate) { - parts.erase(std::remove_if(parts.begin(), parts.end(), predicate), parts.end()); - } - - template <class F> void map(F& functor) { - std::for_each(parts.begin(), parts.end(), functor); - } - - template <class F> void map(F& functor) const { - std::for_each(parts.begin(), parts.end(), functor); - } - - template <class F, class P> void map_if(F& functor, P predicate) { - for(Frames::iterator i = parts.begin(); i != parts.end(); i++) { - if (predicate(*i)) functor(*i); - } - } - - template <class F, class P> void map_if(F& functor, P predicate) const { - for(Frames::const_iterator i = parts.begin(); i != parts.end(); i++) { - if (predicate(*i)) functor(*i); - } - } -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/framing/Handler.h b/cpp/src/qpid/framing/Handler.h deleted file mode 100644 index fa8db36f49..0000000000 --- a/cpp/src/qpid/framing/Handler.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef QPID_FRAMING_HANDLER_H -#define QPID_FRAMING_HANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <boost/shared_ptr.hpp> -#include <boost/type_traits/remove_reference.hpp> -#include <assert.h> - -namespace qpid { -namespace framing { - -template <class T> -struct Handler { - typedef T HandledType; - typedef void handleFptr(T); - typedef void result_type; // Compatible with std/boost functors. - - Handler(Handler<T>* next_=0) : next(next_) {} - virtual ~Handler() {} - virtual void handle(T) = 0; - - /** Allow functor syntax for calling handle */ - void operator()(T t) { handle(t); } - - - /** Pointer to next handler in a linked list. */ - Handler<T>* next; - - /** Adapt any void(T) functor as a Handler. - * Functor<F>(f) will copy f. - * Functor<F&>(f) will only take a reference to x. - */ - template <class F> class Functor : public Handler<T> { - public: - Functor(F f, Handler<T>* next=0) : Handler<T>(next), functor(f) {} - void handle(T t) { functor(t); } - private: - F functor; - }; - - /** Adapt a member function of X as a Handler. - * Only holds a reference to its target, not a copy. - */ - template <class X, void (X::*F)(T)> - class MemFunRef : public Handler<T> { - public: - MemFunRef(X& x, Handler<T>* next=0) : Handler(next), target(&x) {} - void handle(T t) { (target->*F)(t); } - - /** Allow calling with -> syntax */ - MemFunRef* operator->() { return this; } - - private: - X* target; - }; - - /** Interface for a handler that implements a - * pair of in/out handle operations. - * @see InOutHandler - */ - class InOutHandlerInterface { - public: - virtual ~InOutHandlerInterface() {} - virtual void handleIn(T) = 0; - virtual void handleOut(T) = 0; - }; - - /** Support for implementing an in-out handler pair as a single class. - * Overrides handleIn, handleOut functions in a single class. - */ - struct InOutHandler : protected InOutHandlerInterface { - InOutHandler(Handler<T>* nextIn=0, Handler<T>* nextOut=0) : in(*this, nextIn), out(*this, nextOut) {} - MemFunRef<InOutHandlerInterface, &InOutHandlerInterface::handleIn> in; - MemFunRef<InOutHandlerInterface, &InOutHandlerInterface::handleOut> out; - }; -}; - - - -}} -#endif /*!QPID_FRAMING_HANDLER_H*/ -// diff --git a/cpp/src/qpid/framing/HeaderProperties.h b/cpp/src/qpid/framing/HeaderProperties.h deleted file mode 100644 index 8b1828daec..0000000000 --- a/cpp/src/qpid/framing/HeaderProperties.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" - -#ifndef _HeaderProperties_ -#define _HeaderProperties_ - -namespace qpid { -namespace framing { - - class HeaderProperties - { - - public: - inline virtual ~HeaderProperties(){} - virtual uint8_t classId() const = 0; - virtual uint32_t encodedSize() const = 0; - virtual void encode(Buffer& buffer) const = 0; - virtual void decode(Buffer& buffer, uint32_t size) = 0; - }; -} -} - - -#endif diff --git a/cpp/src/qpid/framing/InitiationHandler.cpp b/cpp/src/qpid/framing/InitiationHandler.cpp deleted file mode 100644 index 7ded505a47..0000000000 --- a/cpp/src/qpid/framing/InitiationHandler.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/InitiationHandler.h" - -qpid::framing::InitiationHandler::~InitiationHandler() {} diff --git a/cpp/src/qpid/framing/InitiationHandler.h b/cpp/src/qpid/framing/InitiationHandler.h deleted file mode 100644 index 5dfcc6b468..0000000000 --- a/cpp/src/qpid/framing/InitiationHandler.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> - -#ifndef _InitiationHandler_ -#define _InitiationHandler_ - -#include "qpid/framing/ProtocolInitiation.h" - -namespace qpid { -namespace framing { - - class InitiationHandler{ - public: - virtual ~InitiationHandler(); - virtual void initiated(const ProtocolInitiation&) = 0; - }; - -} -} - - -#endif diff --git a/cpp/src/qpid/framing/InputHandler.h b/cpp/src/qpid/framing/InputHandler.h deleted file mode 100644 index 3efb23632a..0000000000 --- a/cpp/src/qpid/framing/InputHandler.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _InputHandler_ -#define _InputHandler_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/FrameHandler.h" -#include <boost/noncopyable.hpp> - -namespace qpid { -namespace framing { - -// TODO aconway 2007-08-29: Eliminate, replace with FrameHandler. -class InputHandler : public FrameHandler { - public: - virtual ~InputHandler() {} - virtual void received(AMQFrame&) = 0; - void handle(AMQFrame& f) { received(f); } -}; - -}} - - -#endif diff --git a/cpp/src/qpid/framing/Invoker.h b/cpp/src/qpid/framing/Invoker.h deleted file mode 100644 index 4f1cf7c331..0000000000 --- a/cpp/src/qpid/framing/Invoker.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef QPID_FRAMING_INVOKER_H -#define QPID_FRAMING_INVOKER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/MethodBodyDefaultVisitor.h" -#include "qpid/framing/StructHelper.h" - -#include <boost/optional.hpp> - -namespace qpid { -namespace framing { - -class AMQMethodBody; - -/** - * Base class for invoker visitors. - */ -class Invoker: public MethodBodyDefaultVisitor, protected StructHelper -{ - public: - struct Result { - public: - Result() : handled(false) {} - const std::string& getResult() const { return result; } - bool hasResult() const { return !result.empty(); } - bool wasHandled() const { return handled; } - operator bool() const { return handled; } - - std::string result; - bool handled; - }; - - void defaultVisit(const AMQMethodBody&) {} - Result getResult() const { return result; } - - protected: - Result result; -}; - -/** - * Invoke an invocable object. - * Invocable classes must provide a nested type Invoker. - */ -template <class Invocable> -Invoker::Result invoke(Invocable& target, const AMQMethodBody& body) { - typename Invocable::Invoker invoker(target); - body.accept(invoker); - return invoker.getResult(); -} - -/** - * Invoke an invocable object. - * Invocable classes must provide a nested type Invoker. - */ -template <class Invocable> -Invoker::Result invoke(Invocable& target, const AMQBody& body) { - typename Invocable::Invoker invoker(target); - const AMQMethodBody* method = body.getMethod(); - if (method) - method->accept(invoker); - return invoker.getResult(); -} - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_INVOKER_H*/ diff --git a/cpp/src/qpid/framing/IsInSequenceSet.h b/cpp/src/qpid/framing/IsInSequenceSet.h deleted file mode 100644 index fe10c1b9fa..0000000000 --- a/cpp/src/qpid/framing/IsInSequenceSet.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef QPID_FRAMING_ISINSEQUENCESET_H -#define QPID_FRAMING_ISINSEQUENCESET_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/SequenceSet.h" - -namespace qpid { -namespace framing { -/** - * Functor to test whether values are in a sequence set. This is a - * stateful functor that requires the values to be supplied in order - * and takes advantage of that ordering to avoid multiple scans. - */ -class IsInSequenceSet -{ - public: - IsInSequenceSet(const SequenceSet& s) : set(s), i(set.rangesBegin()) {} - - bool operator()(const SequenceNumber& n) { - while (i != set.rangesEnd() && i->end() <= n) ++i; - return i != set.rangesEnd() && i->begin() <= n; - } - - private: - const SequenceSet& set; - SequenceSet::RangeIterator i; -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_ISINSEQUENCESET_H*/ diff --git a/cpp/src/qpid/framing/List.cpp b/cpp/src/qpid/framing/List.cpp deleted file mode 100644 index 963ebc206b..0000000000 --- a/cpp/src/qpid/framing/List.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/List.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" - -namespace qpid { -namespace framing { - -uint32_t List::encodedSize() const -{ - uint32_t len(4/*size*/ + 4/*count*/); - for(Values::const_iterator i = values.begin(); i != values.end(); ++i) { - len += (*i)->encodedSize(); - } - return len; -} - -void List::encode(Buffer& buffer) const -{ - buffer.putLong(encodedSize() - 4); - buffer.putLong(size()); - for (Values::const_iterator i = values.begin(); i!=values.end(); ++i) { - (*i)->encode(buffer); - } -} - -void List::decode(Buffer& buffer) -{ - values.clear(); - uint32_t size = buffer.getLong(); - uint32_t available = buffer.available(); - if (available < size) { - throw IllegalArgumentException(QPID_MSG("Not enough data for list, expected " - << size << " bytes but only " << available << " available")); - } - if (size) { - uint32_t count = buffer.getLong(); - for (uint32_t i = 0; i < count; i++) { - ValuePtr value(new FieldValue); - value->decode(buffer); - values.push_back(value); - } - } -} - - -bool List::operator==(const List& other) const { - return values.size() == other.values.size() && - std::equal(values.begin(), values.end(), other.values.begin()); -} - -std::ostream& operator<<(std::ostream& out, const List& l) -{ - out << "{"; - for(List::Values::const_iterator i = l.values.begin(); i != l.values.end(); ++i) { - if (i != l.values.begin()) out << ", "; - (*i)->print(out); - } - return out << "}"; -} - -}} // namespace qpid::framing diff --git a/cpp/src/qpid/framing/MethodBodyFactory.h b/cpp/src/qpid/framing/MethodBodyFactory.h deleted file mode 100644 index 88bc444795..0000000000 --- a/cpp/src/qpid/framing/MethodBodyFactory.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QPID_FRAMING_METHODBODYFACTORY_H -#define QPID_FRAMING_METHODBODYFACTORY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQBody.h" -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace framing { - -class AMQMethodBody; - -/** - * Functions to create instances of AMQMethodBody sub-classes. - * Note: MethodBodyFactory.cpp file is generated by rubygen. - */ -class MethodBodyFactory -{ - public: - static boost::intrusive_ptr<AMQMethodBody> create(ClassId c, MethodId m); -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_METHODBODYFACTORY_H*/ diff --git a/cpp/src/qpid/framing/MethodContent.h b/cpp/src/qpid/framing/MethodContent.h deleted file mode 100644 index b290a0c140..0000000000 --- a/cpp/src/qpid/framing/MethodContent.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _MethodContent_ -#define _MethodContent_ - -#include <string> -#include "qpid/framing/AMQHeaderBody.h" - -namespace qpid { -namespace framing { - -class MethodContent -{ -public: - virtual ~MethodContent() {} - //TODO: rethink this interface - virtual AMQHeaderBody getHeader() const = 0; - virtual const std::string& getData() const = 0; -}; - -}} -#endif diff --git a/cpp/src/qpid/framing/ModelMethod.h b/cpp/src/qpid/framing/ModelMethod.h deleted file mode 100644 index d99bd06cfa..0000000000 --- a/cpp/src/qpid/framing/ModelMethod.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _ModelMethod_ -#define _ModelMethod_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/Header.h" - -namespace qpid { -namespace framing { - - -class ModelMethod : public AMQMethodBody -{ - mutable Header header; -public: - virtual ~ModelMethod() {} - virtual void encodeHeader(Buffer& buffer) const { header.encode(buffer); } - virtual void decodeHeader(Buffer& buffer, uint32_t size=0) { header.decode(buffer, size); } - virtual uint32_t headerSize() const { return header.encodedSize(); } - virtual bool isSync() const { return header.getSync(); } - virtual void setSync(bool on) const { header.setSync(on); } - Header& getHeader() { return header; } - const Header& getHeader() const { return header; } -}; - - -}} // namespace qpid::framing - - -#endif diff --git a/cpp/src/qpid/framing/OutputHandler.h b/cpp/src/qpid/framing/OutputHandler.h deleted file mode 100644 index 88c95589da..0000000000 --- a/cpp/src/qpid/framing/OutputHandler.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _OutputHandler_ -#define _OutputHandler_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <boost/noncopyable.hpp> -#include "qpid/framing/FrameHandler.h" - -namespace qpid { -namespace framing { - -// TODO aconway 2007-08-29: Replace with FrameHandler. -class OutputHandler : public FrameHandler { - public: - virtual ~OutputHandler() {} - virtual void send(AMQFrame&) = 0; - void handle(AMQFrame& f) { send(f); } -}; - - -}} - - -#endif diff --git a/cpp/src/qpid/framing/ProtocolInitiation.cpp b/cpp/src/qpid/framing/ProtocolInitiation.cpp deleted file mode 100644 index e617015d64..0000000000 --- a/cpp/src/qpid/framing/ProtocolInitiation.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/ProtocolInitiation.h" - -namespace qpid { -namespace framing { - -ProtocolInitiation::ProtocolInitiation(){} - -ProtocolInitiation::ProtocolInitiation(uint8_t _major, uint8_t _minor) : version(_major, _minor) {} - -ProtocolInitiation::ProtocolInitiation(ProtocolVersion p) : version(p) {} - -ProtocolInitiation::~ProtocolInitiation(){} - -void ProtocolInitiation::encode(Buffer& buffer) const { - buffer.putOctet('A'); - buffer.putOctet('M'); - buffer.putOctet('Q'); - buffer.putOctet('P'); - buffer.putOctet(1);//class - buffer.putOctet(1);//instance - buffer.putOctet(version.getMajor()); - buffer.putOctet(version.getMinor()); -} - -bool ProtocolInitiation::decode(Buffer& buffer){ - if(buffer.available() >= 8){ - buffer.getOctet();//A - buffer.getOctet();//M - buffer.getOctet();//Q - buffer.getOctet();//P - buffer.getOctet();//class - buffer.getOctet();//instance - version.setMajor(buffer.getOctet()); - version.setMinor(buffer.getOctet()); - return true; - }else{ - return false; - } -} - - -std::ostream& operator<<(std::ostream& o, const framing::ProtocolInitiation& pi) { - return o << int(pi.getMajor()) << "-" << int(pi.getMinor()); -} - -}} // namespace qpid::framing diff --git a/cpp/src/qpid/framing/ProtocolInitiation.h b/cpp/src/qpid/framing/ProtocolInitiation.h deleted file mode 100644 index c519bc2442..0000000000 --- a/cpp/src/qpid/framing/ProtocolInitiation.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/AMQDataBlock.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/CommonImportExport.h" - -#ifndef _ProtocolInitiation_ -#define _ProtocolInitiation_ - -namespace qpid { -namespace framing { - -class ProtocolInitiation : public AMQDataBlock -{ -private: - ProtocolVersion version; - -public: - QPID_COMMON_EXTERN ProtocolInitiation(); - QPID_COMMON_EXTERN ProtocolInitiation(uint8_t major, uint8_t minor); - QPID_COMMON_EXTERN ProtocolInitiation(ProtocolVersion p); - QPID_COMMON_EXTERN virtual ~ProtocolInitiation(); - QPID_COMMON_EXTERN virtual void encode(Buffer& buffer) const; - QPID_COMMON_EXTERN virtual bool decode(Buffer& buffer); - inline virtual uint32_t encodedSize() const { return 8; } - inline uint8_t getMajor() const { return version.getMajor(); } - inline uint8_t getMinor() const { return version.getMinor(); } - inline ProtocolVersion getVersion() const { return version; } - bool operator==(ProtocolVersion v) const { return v == getVersion(); } -}; - -QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream& o, const framing::ProtocolInitiation& pi); - - -} -} - - -#endif diff --git a/cpp/src/qpid/framing/ProtocolVersion.cpp b/cpp/src/qpid/framing/ProtocolVersion.cpp deleted file mode 100644 index c63cddb4cc..0000000000 --- a/cpp/src/qpid/framing/ProtocolVersion.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/ProtocolVersion.h" -#include <sstream> - -using namespace qpid::framing; - -const std::string ProtocolVersion::toString() const -{ - std::stringstream ss; - ss << major_ << "-" << minor_; - return ss.str(); -} - -ProtocolVersion& ProtocolVersion::operator=(ProtocolVersion p) -{ - major_ = p.major_; - minor_ = p.minor_; - return *this; -} - -bool ProtocolVersion::operator==(ProtocolVersion p) const -{ - return major_ == p.major_ && minor_ == p.minor_; -} - diff --git a/cpp/src/qpid/framing/Proxy.cpp b/cpp/src/qpid/framing/Proxy.cpp deleted file mode 100644 index 452fb13b01..0000000000 --- a/cpp/src/qpid/framing/Proxy.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/framing/Proxy.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace framing { - -Proxy::Proxy(FrameHandler& h) : out(&h), sync(false) {} - -Proxy::~Proxy() {} - -void Proxy::send(const AMQBody& b) { - if (sync) { - const AMQMethodBody* m = dynamic_cast<const AMQMethodBody*>(&b); - if (m) m->setSync(sync); - } - AMQFrame f(b); - out->handle(f); -} - -ProtocolVersion Proxy::getVersion() const { - return ProtocolVersion(); -} - -FrameHandler& Proxy::getHandler() { return *out; } - -void Proxy::setHandler(FrameHandler& f) { out=&f; } - -Proxy::ScopedSync::ScopedSync(Proxy& p) : proxy(p) { proxy.sync = true; } -Proxy::ScopedSync::~ScopedSync() { proxy.sync = false; } - -}} // namespace qpid::framing diff --git a/cpp/src/qpid/framing/Proxy.h b/cpp/src/qpid/framing/Proxy.h deleted file mode 100644 index 0884e9cbd2..0000000000 --- a/cpp/src/qpid/framing/Proxy.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _framing_Proxy_h -#define _framing_Proxy_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/ProtocolVersion.h" - -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class AMQBody; - -/** - * Base class for proxies. - */ -class Proxy -{ - public: - class ScopedSync - { - Proxy& proxy; - public: - QPID_COMMON_EXTERN ScopedSync(Proxy& p); - QPID_COMMON_EXTERN ~ScopedSync(); - }; - - QPID_COMMON_EXTERN Proxy(FrameHandler& h); - QPID_COMMON_EXTERN virtual ~Proxy(); - - QPID_COMMON_EXTERN void send(const AMQBody&); - - QPID_COMMON_EXTERN ProtocolVersion getVersion() const; - - QPID_COMMON_EXTERN FrameHandler& getHandler(); - QPID_COMMON_EXTERN void setHandler(FrameHandler&); - private: - FrameHandler* out; - bool sync; -}; - -}} // namespace qpid::framing - - - -#endif /*!_framing_Proxy_h*/ diff --git a/cpp/src/qpid/framing/ResizableBuffer.h b/cpp/src/qpid/framing/ResizableBuffer.h deleted file mode 100644 index 0abc5ba7f4..0000000000 --- a/cpp/src/qpid/framing/ResizableBuffer.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_FRAMING_RESIZABLEBUFFER_H -#define QPID_FRAMING_RESIZABLEBUFFER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/Buffer.h" -#include <vector> - -namespace qpid { -namespace framing { - -/** - * A buffer that maintains its own storage and can be resized, - * keeping any data already written to the buffer. - */ -class ResizableBuffer : public Buffer -{ - public: - ResizableBuffer(size_t initialSize) : store(initialSize) { - static_cast<Buffer&>(*this) = Buffer(&store[0], store.size()); - } - - void resize(size_t newSize) { - size_t oldPos = getPosition(); - store.resize(newSize); - static_cast<Buffer&>(*this) = Buffer(&store[0], store.size()); - setPosition(oldPos); - } - - /** Make sure at least n bytes are available */ - void makeAvailable(size_t n) { - if (n > available()) - resize(getSize() + n - available()); - } - - private: - std::vector<char> store; -}; -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_RESIZABLEBUFFER_H*/ diff --git a/cpp/src/qpid/framing/SendContent.cpp b/cpp/src/qpid/framing/SendContent.cpp deleted file mode 100644 index 04b60396da..0000000000 --- a/cpp/src/qpid/framing/SendContent.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/SendContent.h" - -qpid::framing::SendContent::SendContent(FrameHandler& h, uint16_t mfs, uint efc) : handler(h), - maxFrameSize(mfs), - expectedFrameCount(efc), frameCount(0) {} - -void qpid::framing::SendContent::operator()(const AMQFrame& f) -{ - bool first = frameCount == 0; - bool last = ++frameCount == expectedFrameCount; - - uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead(); - const AMQContentBody* body(f.castBody<AMQContentBody>()); - if (body->encodedSize() > maxContentSize) { - uint32_t offset = 0; - for (int chunk = body->encodedSize() / maxContentSize; chunk > 0; chunk--) { - sendFragment(*body, offset, maxContentSize, first && offset == 0, last && offset + maxContentSize == body->encodedSize()); - offset += maxContentSize; - } - uint32_t remainder = body->encodedSize() % maxContentSize; - if (remainder) { - sendFragment(*body, offset, remainder, first && offset == 0, last); - } - } else { - AMQFrame copy(f); - setFlags(copy, first, last); - handler.handle(copy); - } -} - -void qpid::framing::SendContent::sendFragment(const AMQContentBody& body, uint32_t offset, uint16_t size, bool first, bool last) const -{ - AMQFrame fragment((AMQContentBody(body.getData().substr(offset, size)))); - setFlags(fragment, first, last); - handler.handle(fragment); -} - -void qpid::framing::SendContent::setFlags(AMQFrame& f, bool first, bool last) const -{ - f.setBof(false); - f.setBos(first); - f.setEof(true);//content is always the last segment - f.setEos(last); -} - diff --git a/cpp/src/qpid/framing/SendContent.h b/cpp/src/qpid/framing/SendContent.h deleted file mode 100644 index 1c464b9c8b..0000000000 --- a/cpp/src/qpid/framing/SendContent.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/CommonImportExport.h" - -#ifndef _SendContent_ -#define _SendContent_ - -namespace qpid { -namespace framing { - -/** - * Functor that sends frame to handler, refragmenting if - * necessary. Currently only works on content frames but this could be - * changed once we support multi-frame segments in general. - */ -class SendContent -{ - FrameHandler& handler; - const uint16_t maxFrameSize; - uint expectedFrameCount; - uint frameCount; - - void sendFragment(const AMQContentBody& body, uint32_t offset, uint16_t size, bool first, bool last) const; - void setFlags(AMQFrame& f, bool first, bool last) const; -public: - QPID_COMMON_EXTERN SendContent(FrameHandler& _handler, uint16_t _maxFrameSize, uint frameCount); - QPID_COMMON_EXTERN void operator()(const AMQFrame& f); -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/framing/SequenceNumber.cpp b/cpp/src/qpid/framing/SequenceNumber.cpp deleted file mode 100644 index 41cb236629..0000000000 --- a/cpp/src/qpid/framing/SequenceNumber.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/Buffer.h" -#include <ostream> - -using qpid::framing::SequenceNumber; -using qpid::framing::Buffer; - -void SequenceNumber::encode(Buffer& buffer) const -{ - buffer.putLong(value); -} - -void SequenceNumber::decode(Buffer& buffer) -{ - value = buffer.getLong(); -} - -uint32_t SequenceNumber::encodedSize() const { - return 4; -} - -namespace qpid { -namespace framing { - -std::ostream& operator<<(std::ostream& o, const SequenceNumber& n) { - return o << n.getValue(); -} - -}} diff --git a/cpp/src/qpid/framing/SequenceNumberSet.cpp b/cpp/src/qpid/framing/SequenceNumberSet.cpp deleted file mode 100644 index e9d78f3c17..0000000000 --- a/cpp/src/qpid/framing/SequenceNumberSet.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/SequenceNumberSet.h" - -using namespace qpid::framing; - -void SequenceNumberSet::encode(Buffer& buffer) const -{ - buffer.putShort(size() * 4); - for (const_iterator i = begin(); i != end(); i++) { - buffer.putLong(i->getValue()); - } -} - -void SequenceNumberSet::decode(Buffer& buffer) -{ - clear(); - uint16_t count = (buffer.getShort() / 4); - for (uint16_t i = 0; i < count; i++) { - push_back(SequenceNumber(buffer.getLong())); - } -} - -uint32_t SequenceNumberSet::encodedSize() const -{ - return 2 /*count*/ + (size() * 4); -} - -SequenceNumberSet SequenceNumberSet::condense() const -{ - SequenceNumberSet result; - const_iterator last = end(); - const_iterator start = end(); - for (const_iterator i = begin(); i != end(); i++) { - if (start == end()) { - start = i; - } else if (*i - *last > 1) { - result.push_back(*start); - result.push_back(*last); - start = i; - } - last = i; - } - if (start != end()) { - result.push_back(*start); - result.push_back(*last); - } - return result; -} - -void SequenceNumberSet::addRange(const SequenceNumber& start, const SequenceNumber& end) -{ - push_back(start); - push_back(end); -} - -namespace qpid{ -namespace framing{ - -std::ostream& operator<<(std::ostream& out, const SequenceNumberSet& set) { - out << "{"; - for (SequenceNumberSet::const_iterator i = set.begin(); i != set.end(); i++) { - if (i != set.begin()) out << ", "; - out << (i->getValue()); - } - out << "}"; - return out; -} - -} -} diff --git a/cpp/src/qpid/framing/SequenceNumberSet.h b/cpp/src/qpid/framing/SequenceNumberSet.h deleted file mode 100644 index c8356c8163..0000000000 --- a/cpp/src/qpid/framing/SequenceNumberSet.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _framing_SequenceNumberSet_h -#define _framing_SequenceNumberSet_h - -#include <ostream> -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/InlineVector.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -class SequenceNumberSet : public InlineVector<SequenceNumber, 2> -{ - typedef InlineVector<SequenceNumber, 2> Base; -public: - typedef Base::const_iterator const_iterator; - typedef Base::iterator iterator; - - void encode(Buffer& buffer) const; - void decode(Buffer& buffer); - uint32_t encodedSize() const; - QPID_COMMON_EXTERN SequenceNumberSet condense() const; - QPID_COMMON_EXTERN void addRange(const SequenceNumber& start, const SequenceNumber& end); - - template <class T> - void processRanges(T& t) const - { - if (size() % 2) { //must be even number - throw InvalidArgumentException("SequenceNumberSet contains odd number of elements"); - } - - for (SequenceNumberSet::const_iterator i = begin(); i != end(); i++) { - SequenceNumber first = *(i); - SequenceNumber last = *(++i); - t(first, last); - } - } - - friend QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const SequenceNumberSet&); -}; - - -}} // namespace qpid::framing - - -#endif diff --git a/cpp/src/qpid/framing/SequenceSet.cpp b/cpp/src/qpid/framing/SequenceSet.cpp deleted file mode 100644 index 72fcd8a9e2..0000000000 --- a/cpp/src/qpid/framing/SequenceSet.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" - -using namespace qpid::framing; -using std::max; -using std::min; - -namespace qpid { -namespace framing { - -namespace { -//each range contains 2 numbers, 4 bytes each -uint16_t RANGE_SIZE = 2 * 4; -} - -void SequenceSet::encode(Buffer& buffer) const -{ - buffer.putShort(rangesSize() * RANGE_SIZE); - for (RangeIterator i = rangesBegin(); i != rangesEnd(); i++) { - buffer.putLong(i->first().getValue()); - buffer.putLong(i->last().getValue()); - } -} - -void SequenceSet::decode(Buffer& buffer) -{ - clear(); - uint16_t size = buffer.getShort(); - uint16_t count = size / RANGE_SIZE;//number of ranges - if (size % RANGE_SIZE) - throw IllegalArgumentException(QPID_MSG("Invalid size for sequence set: " << size)); - - for (uint16_t i = 0; i < count; i++) { - add(SequenceNumber(buffer.getLong()), SequenceNumber(buffer.getLong())); - } -} - -uint32_t SequenceSet::encodedSize() const { - return 2 /*size field*/ + (rangesSize() * RANGE_SIZE); -} - -bool SequenceSet::contains(const SequenceNumber& s) const { - return RangeSet<SequenceNumber>::contains(s); -} - -void SequenceSet::add(const SequenceNumber& s) { *this += s; } - -void SequenceSet::add(const SequenceNumber& start, const SequenceNumber& finish) { - *this += Range<SequenceNumber>::makeClosed(std::min(start,finish), std::max(start, finish)); -} - -void SequenceSet::add(const SequenceSet& set) { *this += set; } - -void SequenceSet::remove(const SequenceSet& set) { *this -= set; } - -void SequenceSet::remove(const SequenceNumber& start, const SequenceNumber& finish) { - *this -= Range<SequenceNumber>::makeClosed(std::min(start,finish), std::max(start, finish)); -} - -void SequenceSet::remove(const SequenceNumber& s) { *this -= s; } - - -struct RangePrinter { - std::ostream& out; - RangePrinter(std::ostream& o) : out(o) {} - void operator()(SequenceNumber i, SequenceNumber j) const { - out << "[" << i.getValue() << "," << j.getValue() << "] "; - } -}; - -std::ostream& operator<<(std::ostream& o, const SequenceSet& s) { - RangePrinter print(o); - o << "{ "; - s.for_each(print); - return o << "}"; -} - -}} // namespace qpid::framing - diff --git a/cpp/src/qpid/framing/TemplateVisitor.h b/cpp/src/qpid/framing/TemplateVisitor.h deleted file mode 100644 index d6d59603f7..0000000000 --- a/cpp/src/qpid/framing/TemplateVisitor.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef QPID_FRAMING_TEMPLATEVISITOR_H -#define QPID_FRAMING_TEMPLATEVISITOR_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <boost/mpl/fold.hpp> -#include <boost/utility/value_init.hpp> - -namespace qpid { -namespace framing { - -/** - * Metafunction to generate a visitor class derived from Base, with a - * visit for each type in TypeList calling functor F. TypeList may be - * any boost::mpl type collection e.g. mpl::list. - * - * Generated class is: TemplateVisitor<Base, F, TypeList>::type - * - * @see make_visitor - */ -template <class VisitTemplate, class TypeList, class F> -class TemplateVisitor -{ - struct Base : public VisitorBase { - F action; - Base(F f) : action(f) {} - using VisitorBase::visit; - }; - - template <class B, class T> struct Visit : public B { - Visit(F action) : B(action) {} - using B::visit; - void visit(const T& body) { action(body); } - }; - - typedef typename boost::mpl::fold< - TypeList, Base, Visit<boost::mpl::placeholders::_1, - boost::mpl::placeholders::_2> - >::type type; -}; - -/** - * Construct a TemplateVisitor to perform the given action, - * for example: - * @code - */ -template <class VisitorBase, class TypeList, class F> -TemplateVisitor<VisitorBase,TypeList,F>::type make_visitor(F action) { - return TemplateVisitor<VisitorBase,TypeList,F>::type(action); -}; - -/** - * For method body classes in TypeList, invoke the corresponding function - * on Target and return true. For other body types return false. - */ -template <class TypeList, class Target> -bool invoke(const AMQBody& body, Target& target) { - typename InvokeVisitor<TypeList, Target>::type v(target); - body.accept(v); - return v.target; -} - -}} // namespace qpid::framing - - -#endif /*!QPID_FRAMING_INVOKEVISITOR_H*/ - -}} // namespace qpid::framing - - - -#endif /*!QPID_FRAMING_TEMPLATEVISITOR_H*/ diff --git a/cpp/src/qpid/framing/TransferContent.cpp b/cpp/src/qpid/framing/TransferContent.cpp deleted file mode 100644 index 837d7d346a..0000000000 --- a/cpp/src/qpid/framing/TransferContent.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/TransferContent.h" - -namespace qpid { -namespace framing { - -TransferContent::TransferContent(const std::string& data, const std::string& key) { - setData(data); - if (!key.empty()) getDeliveryProperties().setRoutingKey(key); -} - - -AMQHeaderBody TransferContent::getHeader() const -{ - return header; -} - -const std::string& TransferContent::getData() const { - return data; -} - -std::string& TransferContent::getData() { - return data; -} - -void TransferContent::setData(const std::string& _data) -{ - data = _data; - header.get<MessageProperties>(true)->setContentLength(data.size()); -} - -void TransferContent::appendData(const std::string& _data) -{ - data += _data; - header.get<MessageProperties>(true)->setContentLength(data.size()); -} - -MessageProperties& TransferContent::getMessageProperties() -{ - return *header.get<MessageProperties>(true); -} - -DeliveryProperties& TransferContent::getDeliveryProperties() -{ - return *header.get<DeliveryProperties>(true); -} - -void TransferContent::populate(const FrameSet& frameset) -{ - const AMQHeaderBody* h = frameset.getHeaders(); - if (h) { - header = *h; - } - frameset.getContent(data); -} - -const MessageProperties& TransferContent::getMessageProperties() const -{ - const MessageProperties* props = header.get<MessageProperties>(); - if (!props) throw Exception("No message properties."); - return *props; -} - -const DeliveryProperties& TransferContent::getDeliveryProperties() const -{ - const DeliveryProperties* props = header.get<DeliveryProperties>(); - if (!props) throw Exception("No message properties."); - return *props; -} - -bool TransferContent::hasMessageProperties() const -{ - return header.get<MessageProperties>(); -} - -bool TransferContent::hasDeliveryProperties() const -{ - return header.get<DeliveryProperties>(); -} - - -}} diff --git a/cpp/src/qpid/framing/TransferContent.h b/cpp/src/qpid/framing/TransferContent.h deleted file mode 100644 index 9a698a1823..0000000000 --- a/cpp/src/qpid/framing/TransferContent.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TransferContent_ -#define _TransferContent_ - -#include "qpid/framing/FrameSet.h" -#include "qpid/framing/MethodContent.h" -#include "qpid/Exception.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace framing { - -/** Message content */ -class QPID_COMMON_CLASS_EXTERN TransferContent : public MethodContent -{ - AMQHeaderBody header; - std::string data; -public: - QPID_COMMON_EXTERN TransferContent(const std::string& data = std::string(), const std::string& key=std::string()); - - ///@internal - QPID_COMMON_EXTERN AMQHeaderBody getHeader() const; - - QPID_COMMON_EXTERN void setData(const std::string&); - QPID_COMMON_EXTERN const std::string& getData() const; - QPID_COMMON_EXTERN std::string& getData(); - - QPID_COMMON_EXTERN void appendData(const std::string&); - - QPID_COMMON_EXTERN bool hasMessageProperties() const; - QPID_COMMON_EXTERN MessageProperties& getMessageProperties(); - QPID_COMMON_EXTERN const MessageProperties& getMessageProperties() const; - - QPID_COMMON_EXTERN bool hasDeliveryProperties() const; - QPID_COMMON_EXTERN DeliveryProperties& getDeliveryProperties(); - QPID_COMMON_EXTERN const DeliveryProperties& getDeliveryProperties() const; - - ///@internal - QPID_COMMON_EXTERN void populate(const FrameSet& frameset); -}; - -}} -#endif diff --git a/cpp/src/qpid/framing/TypeFilter.h b/cpp/src/qpid/framing/TypeFilter.h deleted file mode 100644 index d1c42de583..0000000000 --- a/cpp/src/qpid/framing/TypeFilter.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef QPID_FRAMING_TYPEFILTER_H -#define QPID_FRAMING_TYPEFILTER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FrameHandler.h" - -namespace qpid { -namespace framing { - -/** - * Predicate that selects frames by type - */ -template <uint8_t Type> -struct TypeFilter { - bool operator()(const AMQFrame& f) const { - return f.getBody()->type() == Type; - } -}; - -template <uint8_t T1, uint8_t T2> -struct TypeFilter2 { - bool operator()(const AMQFrame& f) const { - return f.getBody()->type() == T1 || f.getBody()->type() == T2; - } -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_TYPEFILTER_H*/ diff --git a/cpp/src/qpid/framing/Uuid.cpp b/cpp/src/qpid/framing/Uuid.cpp deleted file mode 100644 index 945c0a4d24..0000000000 --- a/cpp/src/qpid/framing/Uuid.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/framing/Uuid.h" - -#include "qpid/sys/uuid.h" -#include "qpid/Exception.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/Msg.h" - -namespace qpid { -namespace framing { - -using namespace std; - -static const size_t UNPARSED_SIZE=36; - -Uuid::Uuid(bool unique) { - if (unique) { - generate(); - } else { - clear(); - } -} - -Uuid::Uuid(const uint8_t* data) { - assign(data); -} - -void Uuid::assign(const uint8_t* data) { - // This const cast is for Solaris which has a - // uuid_copy that takes a non const 2nd argument - uuid_copy(c_array(), const_cast<uint8_t*>(data)); -} - -void Uuid::generate() { - uuid_generate(c_array()); -} - -void Uuid::clear() { - uuid_clear(c_array()); -} - -// Force int 0/!0 to false/true; avoids compile warnings. -bool Uuid::isNull() const { - return !!uuid_is_null(data()); -} - -void Uuid::encode(Buffer& buf) const { - buf.putRawData(data(), size()); -} - -void Uuid::decode(Buffer& buf) { - if (buf.available() < size()) - throw IllegalArgumentException(QPID_MSG("Not enough data for UUID.")); - buf.getRawData(c_array(), size()); -} - -ostream& operator<<(ostream& out, Uuid uuid) { - char unparsed[UNPARSED_SIZE + 1]; - uuid_unparse(uuid.data(), unparsed); - return out << unparsed; -} - -istream& operator>>(istream& in, Uuid& uuid) { - char unparsed[UNPARSED_SIZE + 1] = {0}; - in.get(unparsed, sizeof(unparsed)); - if (!in.fail()) { - if (uuid_parse(unparsed, uuid.c_array()) != 0) - in.setstate(ios::failbit); - } - return in; -} - -std::string Uuid::str() const { - std::ostringstream os; - os << *this; - return os.str(); -} - -}} // namespace qpid::framing diff --git a/cpp/src/qpid/framing/Visitor.h b/cpp/src/qpid/framing/Visitor.h deleted file mode 100644 index 759ee65914..0000000000 --- a/cpp/src/qpid/framing/Visitor.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef QPID_FRAMING_VISITOR_H -#define QPID_FRAMING_VISITOR_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/mpl/vector.hpp> -#include <boost/type_traits/remove_reference.hpp> -#include <boost/preprocessor/seq/for_each.hpp> - -namespace qpid { -namespace framing { - -/** @file Generic visitor pattern. */ - -/** visit() interface for type T (optional return type R, default is void.) - * To create a visitor for a set of types T1, T2 ... do this: - * struct MyVisitor : public Visit<T1>, public Visit<T2> ... {}; - *@param T Type to visit. This must be forward declared, and need not be defined. - */ -template <class T, class R=void> struct Visit { - typedef R ReturnType; - typedef T VisitType; - - virtual ~Visit() {} - virtual R visit(T&) = 0; -}; - - -#define QPID_VISITOR_DECL(_1,_2,T) class T; - -#define QPID_VISITOR_BASE(_1,_2,T) , public ::qpid::framing::Visit<T> - -/** Convenience macro to generate a visitor interface. - * QPID_VISITOR(MyVisitor,(A)(B)(C)); is equivalent to: - * @code - * class A; class B; class C; - * class MyVisitor : public Visit<A> , public Visit<B> , public Visit<C> {}; - * @endcode - * @param visitor name of the generated visitor class. - * @param bases a sequence of visitable types in the form (T1)(T2)... - * Any parenthesized notations are due to quirks of the preprocesser. - */ -#define QPID_VISITOR(visitor,types) \ - BOOST_PP_SEQ_FOR_EACH(QPID_VISITOR_DECL, _, types) \ - class visitor : public ::qpid::framing::Visit<BOOST_PP_SEQ_HEAD(types)> \ - BOOST_PP_SEQ_FOR_EACH(QPID_VISITOR_BASE, _, BOOST_PP_SEQ_TAIL(types)) \ - {} - -/** The root class for the hierarchy of objects visitable by Visitor V. - * Defines virtual accept(). - */ -template <class V, class R=void> -struct VisitableRoot { - typedef V VisitorType; - typedef R ReturnType; - virtual ~VisitableRoot() {} - virtual R accept(V& v) = 0; -}; - -/** The base class for concrete visitable classes. - * Implements accept(). - * @param T type of visitable class (CRTP). - * @param Base base class to inherit from. - */ -template <class T, class Base> -struct Visitable : public Base { - void accept(typename Base::VisitorType& v) { - static_cast<Visit<T>& >(v).visit(static_cast<T&>(*this)); - } -}; - -}} // namespace qpid::framing - -#endif /*!QPID_FRAMING_VISITOR_H*/ diff --git a/cpp/src/qpid/framing/amqp_framing.h b/cpp/src/qpid/framing/amqp_framing.h deleted file mode 100644 index 3a8b39afb5..0000000000 --- a/cpp/src/qpid/framing/amqp_framing.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/BodyHandler.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeartbeatBody.h" -#include "qpid/framing/InputHandler.h" -#include "qpid/framing/OutputHandler.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/ProtocolVersion.h" diff --git a/cpp/src/qpid/framing/frame_functors.h b/cpp/src/qpid/framing/frame_functors.h deleted file mode 100644 index d2064d6a57..0000000000 --- a/cpp/src/qpid/framing/frame_functors.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include <ostream> -#include <iostream> -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/Buffer.h" - -#ifndef _frame_functors_ -#define _frame_functors_ - -namespace qpid { -namespace framing { - -class SumFrameSize -{ - uint64_t size; -public: - SumFrameSize() : size(0) {} - void operator()(const AMQFrame& f) { size += f.encodedSize(); } - uint64_t getSize() { return size; } -}; - -class SumBodySize -{ - uint64_t size; -public: - SumBodySize() : size(0) {} - void operator()(const AMQFrame& f) { size += f.getBody()->encodedSize(); } - uint64_t getSize() { return size; } -}; - -class Count -{ - uint count; -public: - Count() : count(0) {} - void operator()(const AMQFrame&) { count++; } - uint getCount() { return count; } -}; - -class EncodeFrame -{ - Buffer& buffer; -public: - EncodeFrame(Buffer& b) : buffer(b) {} - void operator()(const AMQFrame& f) { f.encode(buffer); } -}; - -class EncodeBody -{ - Buffer& buffer; -public: - EncodeBody(Buffer& b) : buffer(b) {} - void operator()(const AMQFrame& f) { f.getBody()->encode(buffer); } -}; - -/** - * Sends to the specified handler a copy of the frame it is applied to. - */ -class Relay -{ - FrameHandler& handler; - -public: - Relay(FrameHandler& h) : handler(h) {} - - void operator()(const AMQFrame& f) - { - AMQFrame copy(f); - handler.handle(copy); - } -}; - -class Print -{ - std::ostream& out; -public: - Print(std::ostream& o) : out(o) {} - - void operator()(const AMQFrame& f) - { - out << f << std::endl; - } -}; - -class MarkLastSegment -{ -public: - void operator()(AMQFrame& f) const { f.setEof(true); } -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/framing/variant.h b/cpp/src/qpid/framing/variant.h deleted file mode 100644 index 8e13063385..0000000000 --- a/cpp/src/qpid/framing/variant.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef QPID_FRAMING_VARIANT_H -#define QPID_FRAMING_VARIANT_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/**@file Tools for using boost::variant. */ - - -#include <boost/variant.hpp> - -namespace qpid { -namespace framing { -class Buffer; - -/** boost::static_visitor that throws an exception if variant contains a blank. - * Subclasses need to have a using() declaration, which can be generated - * with QPID_USING_NOBLANK(R) - */ -template <class R=void> -struct NoBlankVisitor : public boost::static_visitor<R> { - R foundBlank() const { - assert(0); - throw Exception(QPID_MSG("Invalid variant value.")); - } - R operator()(const boost::blank&) const { return foundBlank(); } - R operator()(boost::blank&) const { return foundBlank(); } -}; - - -}} // qpid::framing - - -/** Generate a using statement, needed in visitors inheriting NoBlankVisitor - * @param R return type. - */ -#define QPID_USING_NOBLANK(R) using ::qpid::framing::NoBlankVisitor<R>::operator() - -namespace qpid { -namespace framing { - -/** Convert the variant value to type R. */ -template <class R> struct ConvertVisitor : public NoBlankVisitor<R> { - QPID_USING_NOBLANK(R); - template <class T> R operator()(T& t) const { return t; } -}; - -/** Convert the address of variant value to type R. */ -template <class R> struct AddressVisitor : public NoBlankVisitor<R> { - QPID_USING_NOBLANK(R); - template <class T> R operator()(T& t) const { return &t; } -}; - -/** Apply a visitor to the nested variant.*/ -template<class V> -struct ApplyVisitor : public NoBlankVisitor<typename V::result_type> { - QPID_USING_NOBLANK(typename V::result_type); - const V& visitor; - ApplyVisitor(const V& v) : visitor(v) {} - template <class T> typename V::result_type operator()(T& t) const { - return boost::apply_visitor(visitor, t); - } -}; - -/** Convenience function to construct and apply an ApplyVisitor */ -template <class Visitor, class Visitable> -typename Visitor::result_type applyApplyVisitor(const Visitor& visitor, Visitable& visitable) { - return boost::apply_visitor(ApplyVisitor<Visitor>(visitor), visitable); -} - -}} // namespace qpid::framing - - -#endif /*!QPID_FRAMING_VARIANT_H*/ diff --git a/cpp/src/qpid/log/Helpers.h b/cpp/src/qpid/log/Helpers.h deleted file mode 100644 index 82ef8244be..0000000000 --- a/cpp/src/qpid/log/Helpers.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef QPID_LOG_HELPERS_H -#define QPID_LOG_HELPERS_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/range.hpp> - -#include <ostream> - -namespace qpid { -namespace log { - -/** @file Helper classes for logging complex types */ - -/// @internal -template <class Range> -struct ListFormatter { - typedef typename boost::range_const_iterator<Range>::type Iterator; - boost::iterator_range<Iterator> range; - const char* separator; - - ListFormatter(const Range& r, const char* s=", ") : range(r), separator(s) {} -}; - -/// @internal -template <class Range> -std::ostream& operator<<(std::ostream& out, const ListFormatter<Range>& sl) { - typename ListFormatter<Range>::Iterator i = sl.range.begin(); - if (i != sl.range.end()) out << *(i++); - while (i != sl.range.end()) out << sl.separator << *(i++); - return out; -} - -/** Return a formatting object with operator << - * to stream range as a separated list. - *@param range: a range - all standard containers are ranges, - * as is a pair of iterators. - *@param separator: printed between elements, default ", " - */ -template <class Range> -ListFormatter<Range> formatList(const Range& range, const char* separator=", ") { - return ListFormatter<Range>(range, separator); -} - -/** Return a formatting object with operator << - * to stream the range defined by iterators [begin, end) - * as a separated list. - *@param begin, end: Beginning and end of range. - *@param separator: printed between elements, default ", " - */ -template <class U, class V> -ListFormatter<std::pair<U,V> > formatList(U begin, V end, const char* separator=", ") { - return formatList(std::make_pair(begin,end), separator); -} - - -}} // namespace qpid::log - - - -#endif /*!QPID_LOG_HELPERS_H*/ diff --git a/cpp/src/qpid/log/Logger.cpp b/cpp/src/qpid/log/Logger.cpp deleted file mode 100644 index 1600822142..0000000000 --- a/cpp/src/qpid/log/Logger.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/SinkOptions.h" -#include "qpid/memory.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Time.h" -#include "qpid/DisableExceptionLogging.h" -#include <boost/pool/detail/singleton.hpp> -#include <boost/bind.hpp> -#include <boost/function.hpp> -#include <algorithm> -#include <sstream> -#include <iomanip> -#include <stdexcept> -#include <time.h> - - -namespace qpid { -namespace log { - -using namespace std; - -typedef sys::Mutex::ScopedLock ScopedLock; - -inline void Logger::enable_unlocked(Statement* s) { - s->enabled=selector.isEnabled(s->level, s->function); -} - -Logger& Logger::instance() { - return boost::details::pool::singleton_default<Logger>::instance(); -} - -Logger::Logger() : flags(0) { - // Disable automatic logging in Exception constructors to avoid - // re-entrant use of logger singleton if there is an error in - // option parsing. - DisableExceptionLogging del; - - // Initialize myself from env variables so all programs - // (e.g. tests) can use logging even if they don't parse - // command line args. - Options opts(""); - opts.parse(0, 0); - configure(opts); -} - -Logger::~Logger() {} - -void Logger::select(const Selector& s) { - ScopedLock l(lock); - selector=s; - std::for_each(statements.begin(), statements.end(), - boost::bind(&Logger::enable_unlocked, this, _1)); -} - -Logger::Output::Output() {} -Logger::Output::~Output() {} - -void Logger::log(const Statement& s, const std::string& msg) { - // Format the message outside the lock. - std::ostringstream os; - if (!prefix.empty()) - os << prefix << ": "; - if (flags&TIME) { - if (flags&HIRES) - qpid::sys::outputHiresNow(os); - else - qpid::sys::outputFormattedNow(os); - } - if (flags&LEVEL) - os << LevelTraits::name(s.level) << " "; - if (flags&THREAD) - os << "[0x" << hex << qpid::sys::Thread::logId() << "] "; - if (flags&FILE) - os << s.file << ":"; - if (flags&LINE) - os << dec << s.line << ":"; - if (flags&FUNCTION) - os << s.function << ":"; - if (flags & (FILE|LINE|FUNCTION)) - os << " "; - os << msg << endl; - std::string formatted=os.str(); - { - ScopedLock l(lock); - std::for_each(outputs.begin(), outputs.end(), - boost::bind(&Output::log, _1, s, formatted)); - } -} - -void Logger::output(std::auto_ptr<Output> out) { - ScopedLock l(lock); - outputs.push_back(out.release()); -} - -void Logger::clear() { - select(Selector()); // locked - format(0); // locked - ScopedLock l(lock); - outputs.clear(); -} - -void Logger::format(int formatFlags) { - ScopedLock l(lock); - flags=formatFlags; -} - -static int bitIf(bool test, int bit) { - return test ? bit : 0; -} - -int Logger::format(const Options& opts) { - int flags= - bitIf(opts.level, LEVEL) | - bitIf(opts.time, TIME) | - bitIf(opts.source, (FILE|LINE)) | - bitIf(opts.function, FUNCTION) | - bitIf(opts.thread, THREAD) | - bitIf(opts.hiresTs, HIRES); - format(flags); - return flags; -} - -void Logger::add(Statement& s) { - ScopedLock l(lock); - enable_unlocked(&s); - statements.insert(&s); -} - -void Logger::configure(const Options& opts) { - options = opts; - clear(); - Options o(opts); - if (o.trace) - o.selectors.push_back("trace+"); - format(o); - select(Selector(o)); - setPrefix(opts.prefix); - options.sinkOptions->setup(this); -} - -void Logger::reconfigure(const std::vector<std::string>& selectors) { - options.selectors = selectors; - select(Selector(options)); -} - -void Logger::setPrefix(const std::string& p) { prefix = p; } - -}} // namespace qpid::log diff --git a/cpp/src/qpid/log/Options.cpp b/cpp/src/qpid/log/Options.cpp deleted file mode 100644 index 0001d00bdf..0000000000 --- a/cpp/src/qpid/log/Options.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/Options.h" -#include "qpid/log/SinkOptions.h" -#include "qpid/log/Statement.h" -#include "qpid/Options.h" -#include <map> -#include <string> -#include <algorithm> - -namespace qpid { -namespace log { - -using namespace std; - -Options::Options(const std::string& argv0_, const std::string& name_) : - qpid::Options(name_), - argv0(argv0_), - name(name_), - time(true), - level(true), - thread(false), - source(false), - function(false), - hiresTs(false), - trace(false), - sinkOptions (SinkOptions::create(argv0_)) -{ - selectors.push_back("notice+"); - - ostringstream levels; - levels << LevelTraits::name(Level(0)); - for (int i = 1; i < LevelTraits::COUNT; ++i) - levels << " " << LevelTraits::name(Level(i)); - - addOptions() - ("trace,t", optValue(trace), "Enables all logging" ) - ("log-enable", optValue(selectors, "RULE"), - ("Enables logging for selected levels and components. " - "RULE is in the form 'LEVEL[+][:PATTERN]' " - "Levels are one of: \n\t "+levels.str()+"\n" - "For example:\n" - "\t'--log-enable warning+' " - "logs all warning, error and critical messages.\n" - "\t'--log-enable debug:framing' " - "logs debug messages from the framing namespace. " - "This option can be used multiple times").c_str()) - ("log-time", optValue(time, "yes|no"), "Include time in log messages") - ("log-level", optValue(level,"yes|no"), "Include severity level in log messages") - ("log-source", optValue(source,"yes|no"), "Include source file:line in log messages") - ("log-thread", optValue(thread,"yes|no"), "Include thread ID in log messages") - ("log-function", optValue(function,"yes|no"), "Include function signature in log messages") - ("log-hires-timestamp", optValue(hiresTs,"yes|no"), "Use unformatted hi-res timestamp in log messages") - ("log-prefix", optValue(prefix,"STRING"), "Prefix to append to all log messages") - ; - add(*sinkOptions); -} - -Options::Options(const Options &o) : - qpid::Options(o.name), - argv0(o.argv0), - name(o.name), - selectors(o.selectors), - time(o.time), - level(o.level), - thread(o.thread), - source(o.source), - function(o.function), - hiresTs(o.hiresTs), - trace(o.trace), - prefix(o.prefix), - sinkOptions (SinkOptions::create(o.argv0)) -{ - *sinkOptions = *o.sinkOptions; -} - -Options& Options::operator=(const Options& x) { - if (this != &x) { - argv0 = x.argv0; - name = x.name; - selectors = x.selectors; - time = x.time; - level= x.level; - thread = x.thread; - source = x.source; - function = x.function; - hiresTs = x.hiresTs; - trace = x.trace; - prefix = x.prefix; - *sinkOptions = *x.sinkOptions; - } - return *this; -} - -}} // namespace qpid::log diff --git a/cpp/src/qpid/log/OstreamOutput.cpp b/cpp/src/qpid/log/OstreamOutput.cpp deleted file mode 100644 index 9b6ec1f8aa..0000000000 --- a/cpp/src/qpid/log/OstreamOutput.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/OstreamOutput.h" -#include <stdexcept> - -using namespace std; - -namespace qpid { -namespace log { - -OstreamOutput::OstreamOutput(std::ostream& o) : out(&o) {} - -OstreamOutput::OstreamOutput(const std::string& file) - : out(new ofstream(file.c_str(), ios_base::out | ios_base::app)), - mine(out) -{ - if (!out->good()) - throw std::runtime_error("Can't open log file: "+file); -} - -void OstreamOutput::log(const Statement&, const std::string& m) { - *out << m << flush; -} - -}} // namespace qpid::log diff --git a/cpp/src/qpid/log/OstreamOutput.h b/cpp/src/qpid/log/OstreamOutput.h deleted file mode 100644 index 12fd4ce425..0000000000 --- a/cpp/src/qpid/log/OstreamOutput.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef QPID_LOG_OSTREAMOUTPUT_H -#define QPID_LOG_OSTREAMOUTPUT_H - -/* - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/Logger.h" -#include <boost/scoped_ptr.hpp> -#include <fstream> -#include <ostream> - -namespace qpid { -namespace log { - -/** - * OstreamOutput is a reusable logging sink that directs logging to a C++ - * ostream. - */ -class OstreamOutput : public qpid::log::Logger::Output { -public: - QPID_COMMON_EXTERN OstreamOutput(std::ostream& o); - QPID_COMMON_EXTERN OstreamOutput(const std::string& file); - - virtual void log(const Statement&, const std::string& m); - -private: - std::ostream* out; - boost::scoped_ptr<std::ostream> mine; -}; - -}} // namespace qpid::log - -#endif /*!QPID_LOG_OSTREAMOUTPUT_H*/ diff --git a/cpp/src/qpid/log/Selector.cpp b/cpp/src/qpid/log/Selector.cpp deleted file mode 100644 index a4bc580470..0000000000 --- a/cpp/src/qpid/log/Selector.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/Selector.h" -#include "qpid/log/Options.h" -#include <boost/bind.hpp> -#include <algorithm> -#include <string.h> - -namespace qpid { -namespace log { - -using namespace std; - -void Selector::enable(const string& enableStr) { - string level, pattern; - size_t c=enableStr.find(':'); - if (c==string::npos) { - level=enableStr; - } - else { - level=enableStr.substr(0,c); - pattern=enableStr.substr(c+1); - } - if (!level.empty() && level[level.size()-1]=='+') { - for (int i = LevelTraits::level(level.substr(0,level.size()-1)); - i < LevelTraits::COUNT; - ++i) - enable(Level(i), pattern); - } - else { - enable(LevelTraits::level(level), pattern); - } -} - -Selector::Selector(const Options& opt){ - for_each(opt.selectors.begin(), opt.selectors.end(), - boost::bind(&Selector::enable, this, _1)); -} - -bool Selector::isEnabled(Level level, const char* function) { - const char* functionEnd = function+::strlen(function); - for (std::vector<std::string>::iterator i=substrings[level].begin(); - i != substrings[level].end(); - ++i) - { - if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd) - return true; - } - return false; -} - -}} // namespace qpid::log diff --git a/cpp/src/qpid/log/Statement.cpp b/cpp/src/qpid/log/Statement.cpp deleted file mode 100644 index 6a32b50096..0000000000 --- a/cpp/src/qpid/log/Statement.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/Statement.h" -#include "qpid/log/Logger.h" -#include <boost/bind.hpp> -#include <stdexcept> -#include <algorithm> -#include <ctype.h> - -namespace qpid { -namespace log { - -namespace { -using namespace std; - -struct NonPrint { bool operator()(unsigned char c) { return !isprint(c) && !isspace(c); } }; - -const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - -std::string quote(const std::string& str) { - NonPrint nonPrint; - size_t n = std::count_if(str.begin(), str.end(), nonPrint); - if (n==0) return str; - std::string ret; - ret.reserve(str.size()+2*n); // Avoid extra allocations. - for (string::const_iterator i = str.begin(); i != str.end(); ++i) { - if (nonPrint(*i)) { - ret.push_back('\\'); - ret.push_back('x'); - ret.push_back(hex[((*i) >> 4)&0xf]); - ret.push_back(hex[(*i) & 0xf]); - } - else ret.push_back(*i); - } - return ret; -} - -} - -void Statement::log(const std::string& message) { - Logger::instance().log(*this, quote(message)); -} - -Statement::Initializer::Initializer(Statement& s) : statement(s) { - Logger::instance().add(s); -} - -namespace { -const char* names[LevelTraits::COUNT] = { - "trace", "debug", "info", "notice", "warning", "error", "critical" -}; - -} // namespace - -Level LevelTraits::level(const char* name) { - for (int i =0; i < LevelTraits::COUNT; ++i) { - if (strcmp(names[i], name)==0) - return Level(i); - } - throw std::runtime_error(std::string("Invalid log level name: ")+name); -} - -const char* LevelTraits::name(Level l) { - return names[l]; -} - -}} // namespace qpid::log diff --git a/cpp/src/qpid/log/posix/SinkOptions.cpp b/cpp/src/qpid/log/posix/SinkOptions.cpp deleted file mode 100644 index 292e9147f6..0000000000 --- a/cpp/src/qpid/log/posix/SinkOptions.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/posix/SinkOptions.h" -#include "qpid/log/SinkOptions.h" -#include "qpid/log/Logger.h" -#include "qpid/log/OstreamOutput.h" -#include "qpid/memory.h" -#include "qpid/Exception.h" -#include <iostream> -#include <map> -#include <string> -#include <syslog.h> - -using std::string; -using qpid::Exception; - -namespace { - -// SyslogFacilities maps from syslog values to the text equivalents. -class SyslogFacilities { -public: - typedef std::map<string, int> ByName; - typedef std::map<int, string> ByValue; - - SyslogFacilities() { - struct NameValue { const char* name; int value; }; - NameValue nameValue[] = { - { "AUTH", LOG_AUTH }, -#ifdef HAVE_LOG_AUTHPRIV - { "AUTHPRIV", LOG_AUTHPRIV }, -#endif - { "CRON", LOG_CRON }, - { "DAEMON", LOG_DAEMON }, -#ifdef HAVE_LOG_FTP - { "FTP", LOG_FTP }, -#endif - { "KERN", LOG_KERN }, - { "LOCAL0", LOG_LOCAL0 }, - { "LOCAL1", LOG_LOCAL1 }, - { "LOCAL2", LOG_LOCAL2 }, - { "LOCAL3", LOG_LOCAL3 }, - { "LOCAL4", LOG_LOCAL4 }, - { "LOCAL5", LOG_LOCAL5 }, - { "LOCAL6", LOG_LOCAL6 }, - { "LOCAL7", LOG_LOCAL7 }, - { "LPR", LOG_LPR }, - { "MAIL", LOG_MAIL }, - { "NEWS", LOG_NEWS }, - { "SYSLOG", LOG_SYSLOG }, - { "USER", LOG_USER }, - { "UUCP", LOG_UUCP } - }; - for (size_t i = 0; i < sizeof(nameValue)/sizeof(nameValue[0]); ++i) { - byName.insert(ByName::value_type(nameValue[i].name, nameValue[i].value)); - // Recognise with and without LOG_ prefix e.g.: AUTH and LOG_AUTH - byName.insert(ByName::value_type(string("LOG_")+nameValue[i].name, nameValue[i].value)); - byValue.insert(ByValue::value_type(nameValue[i].value, string("LOG_")+nameValue[i].name)); - } - } - - int value(const string& name) const { - string key(name); - std::transform(key.begin(), key.end(), key.begin(), ::toupper); - ByName::const_iterator i = byName.find(key); - if (i == byName.end()) - throw Exception("Not a valid syslog facility: " + name); - return i->second; - } - - string name(int value) const { - ByValue::const_iterator i = byValue.find(value); - if (i == byValue.end()) - throw Exception("Not a valid syslog value: " + value); - return i->second; - } - - private: - ByName byName; - ByValue byValue; -}; - -// 'priorities' maps qpid log levels to syslog priorities. They are in -// order of qpid log levels and must map to: -// "trace", "debug", "info", "notice", "warning", "error", "critical" -static int priorities[qpid::log::LevelTraits::COUNT] = { - LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_NOTICE, - LOG_WARNING, LOG_ERR, LOG_CRIT -}; - -std::string basename(const std::string path) { - size_t i = path.find_last_of('/'); - return path.substr((i == std::string::npos) ? 0 : i+1); -} - -} // namespace - -namespace qpid { -namespace log { -namespace posix { - -std::ostream& operator<<(std::ostream& o, const SyslogFacility& f) { - return o << SyslogFacilities().name(f.value); -} - -std::istream& operator>>(std::istream& i, SyslogFacility& f) { - std::string name; - i >> name; - f.value = SyslogFacilities().value(name); - return i; -} - -class SyslogOutput : public qpid::log::Logger::Output { -public: - SyslogOutput(const std::string& logName, const SyslogFacility& logFacility) - : name(logName), facility(logFacility.value) - { - ::openlog(name.c_str(), LOG_PID, facility); - } - - virtual ~SyslogOutput() { - ::closelog(); - } - - virtual void log(const Statement& s, const std::string& m) - { - syslog(priorities[s.level], "%s", m.c_str()); - } - -private: - std::string name; - int facility; -}; - -SinkOptions::SinkOptions(const std::string& argv0) - : qpid::log::SinkOptions(), - logToStderr(true), - logToStdout(false), - logToSyslog(false), - syslogName(basename(argv0)), - syslogFacility(LOG_DAEMON) { - - addOptions() - ("log-to-stderr", optValue(logToStderr, "yes|no"), "Send logging output to stderr") - ("log-to-stdout", optValue(logToStdout, "yes|no"), "Send logging output to stdout") - ("log-to-file", optValue(logFile, "FILE"), "Send log output to FILE.") - ("log-to-syslog", optValue(logToSyslog, "yes|no"), "Send logging output to syslog;\n\tcustomize using --syslog-name and --syslog-facility") - ("syslog-name", optValue(syslogName, "NAME"), "Name to use in syslog messages") - ("syslog-facility", optValue(syslogFacility,"LOG_XXX"), "Facility to use in syslog messages") - ; - -} - -qpid::log::SinkOptions& SinkOptions::operator=(const qpid::log::SinkOptions& rhs) { - const SinkOptions *prhs = dynamic_cast<const SinkOptions*>(&rhs); - if (this != prhs) { - logToStderr = prhs->logToStderr; - logToStdout = prhs->logToStdout; - logToSyslog = prhs->logToSyslog; - logFile = prhs->logFile; - syslogName = prhs->syslogName; - syslogFacility.value = prhs->syslogFacility.value; - } - return *this; -} - -void SinkOptions::detached(void) { - if (logToStderr && !logToStdout && !logToSyslog) { - logToStderr = false; - logToSyslog = true; - } -} - -// The Logger acting on these options calls setup() to request any -// Sinks be set up and fed back to the logger. -void SinkOptions::setup(qpid::log::Logger *logger) { - if (logToStderr) - logger->output(make_auto_ptr<qpid::log::Logger::Output> - (new qpid::log::OstreamOutput(std::clog))); - if (logToStdout) - logger->output(make_auto_ptr<qpid::log::Logger::Output> - (new qpid::log::OstreamOutput(std::cout))); - - if (logFile.length() > 0) - logger->output(make_auto_ptr<qpid::log::Logger::Output> - (new qpid::log::OstreamOutput(logFile))); - - if (logToSyslog) - logger->output(make_auto_ptr<qpid::log::Logger::Output> - (new SyslogOutput(syslogName, syslogFacility))); - -} - -} // namespace qpid::log::posix - -SinkOptions* SinkOptions::create(const std::string& argv0) { - return new qpid::log::posix::SinkOptions (argv0); -} - -}} // namespace qpid::log diff --git a/cpp/src/qpid/log/posix/SinkOptions.h b/cpp/src/qpid/log/posix/SinkOptions.h deleted file mode 100644 index d929c29025..0000000000 --- a/cpp/src/qpid/log/posix/SinkOptions.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_LOG_POSIX_SINKOPTIONS_H -#define QPID_LOG_POSIX_SINKOPTIONS_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/SinkOptions.h" -#include <string> - -namespace qpid { -namespace log { -namespace posix { - -/** - * Provides a type that can be passed to << and >> operators to convert - * syslog facility values to/from strings. - */ -struct SyslogFacility { - int value; - SyslogFacility(int i=0) : value(i) {} -}; - -struct SinkOptions : public qpid::log::SinkOptions { - SinkOptions(const std::string& argv0); - virtual ~SinkOptions() {} - - virtual qpid::log::SinkOptions& operator=(const qpid::log::SinkOptions& rhs); - - // This allows the caller to indicate that there's no normal outputs - // available. For example, when running as a daemon. In these cases, the - // platform's "syslog"-type output should replace the default stderr - // unless some other sink has been selected. - virtual void detached(void); - - // The Logger acting on these options calls setup() to request any - // Sinks be set up and fed back to the logger. - virtual void setup(qpid::log::Logger *logger); - - bool logToStderr; - bool logToStdout; - bool logToSyslog; - std::string logFile; - std::string syslogName; - SyslogFacility syslogFacility; -}; - -}}} // namespace qpid::log::posix - -#endif /*!QPID_LOG_POSIX_SINKOPTIONS_H*/ diff --git a/cpp/src/qpid/log/windows/SinkOptions.cpp b/cpp/src/qpid/log/windows/SinkOptions.cpp deleted file mode 100644 index 0c74bea64e..0000000000 --- a/cpp/src/qpid/log/windows/SinkOptions.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/windows/SinkOptions.h" -#include "qpid/log/SinkOptions.h" -#include "qpid/log/Logger.h" -#include "qpid/log/OstreamOutput.h" -#include "qpid/memory.h" -#include "qpid/Exception.h" -#include <iostream> -#include <map> -#include <string> - -#include <windows.h> - -using qpid::Exception; - -namespace qpid { -namespace log { -namespace windows { - -namespace { - -// 'eventTypes' maps qpid log levels to Windows event types. They are in -// order of qpid log levels and must map to: -// "trace", "debug", "info", "notice", "warning", "error", "critical" -static int eventTypes[qpid::log::LevelTraits::COUNT] = { - EVENTLOG_INFORMATION_TYPE, /* trace */ - EVENTLOG_INFORMATION_TYPE, /* debug */ - EVENTLOG_INFORMATION_TYPE, /* info */ - EVENTLOG_INFORMATION_TYPE, /* notice */ - EVENTLOG_WARNING_TYPE, /* warning */ - EVENTLOG_ERROR_TYPE, /* error */ - EVENTLOG_ERROR_TYPE /* critical */ -}; - -} // namespace - -class EventLogOutput : public qpid::log::Logger::Output { -public: - EventLogOutput(const std::string& /*sourceName*/) : logHandle(0) - { - logHandle = OpenEventLog(0, "Application"); - } - - virtual ~EventLogOutput() { - if (logHandle) - CloseEventLog(logHandle); - } - - virtual void log(const Statement& s, const std::string& m) - { - if (logHandle) { - const char *msg = m.c_str(); - ReportEvent(logHandle, - eventTypes[s.level], - 0, /* category unused */ - 0, /* event id */ - 0, /* user security id */ - 1, /* number of strings */ - 0, /* no event-specific data */ - &msg, - 0); - } - } - -private: - HANDLE logHandle; -}; - -SinkOptions::SinkOptions(const std::string& /*argv0*/) - : qpid::log::SinkOptions(), - logToStderr(true), - logToStdout(false), - logToEventLog(false), - eventSource("Application") -{ - addOptions() - ("log-to-stderr", optValue(logToStderr, "yes|no"), "Send logging output to stderr") - ("log-to-stdout", optValue(logToStdout, "yes|no"), "Send logging output to stdout") - ("log-to-file", optValue(logFile, "FILE"), "Send log output to FILE.") - ("log-to-eventlog", optValue(logToEventLog, "yes|no"), "Send logging output to event log;\n\tcustomize using --syslog-name and --syslog-facility") - ("eventlog-source-name", optValue(eventSource, "Application"), "Event source to log to") - ; - -} - -qpid::log::SinkOptions& SinkOptions::operator=(const qpid::log::SinkOptions& rhs) { - const SinkOptions *prhs = dynamic_cast<const SinkOptions*>(&rhs); - if (this != prhs) { - logToStderr = prhs->logToStderr; - logToStdout = prhs->logToStdout; - logToEventLog = prhs->logToEventLog; - eventSource = prhs->eventSource; - logFile = prhs->logFile; - } - return *this; -} - -void SinkOptions::detached(void) { - if (logToStderr && !logToStdout && !logToEventLog) { - logToStderr = false; - logToEventLog = true; - } -} - -// The Logger acting on these options calls setup() to request any -// Sinks be set up and fed back to the logger. -void SinkOptions::setup(qpid::log::Logger *logger) { - if (logToStderr) - logger->output(make_auto_ptr<qpid::log::Logger::Output> - (new qpid::log::OstreamOutput(std::clog))); - if (logToStdout) - logger->output(make_auto_ptr<qpid::log::Logger::Output> - (new qpid::log::OstreamOutput(std::cout))); - - if (logFile.length() > 0) - logger->output(make_auto_ptr<qpid::log::Logger::Output> - (new qpid::log::OstreamOutput(logFile))); - - if (logToEventLog) - logger->output(make_auto_ptr<qpid::log::Logger::Output> - (new EventLogOutput(eventSource))); - -} - -} // namespace windows - -SinkOptions* SinkOptions::create(const std::string& argv0) { - return new qpid::log::windows::SinkOptions (argv0); -} - -}} // namespace qpid::log diff --git a/cpp/src/qpid/log/windows/SinkOptions.h b/cpp/src/qpid/log/windows/SinkOptions.h deleted file mode 100644 index f270c504a2..0000000000 --- a/cpp/src/qpid/log/windows/SinkOptions.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_LOG_WINDOWS_SINKOPTIONS_H -#define QPID_LOG_WINDOWS_SINKOPTIONS_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/log/SinkOptions.h" -#include <string> - -namespace qpid { -namespace log { -namespace windows { - -struct QPID_COMMON_CLASS_EXTERN SinkOptions : public qpid::log::SinkOptions { - QPID_COMMON_EXTERN SinkOptions(const std::string& argv0); - virtual ~SinkOptions() {} - - QPID_COMMON_EXTERN virtual qpid::log::SinkOptions& operator=(const qpid::log::SinkOptions& rhs); - - // This allows the caller to indicate that there's no normal outputs - // available. For example, when running as a service. In these cases, the - // platform's "syslog"-type output should replace the default stderr - // unless some other sink has been selected. - QPID_COMMON_EXTERN virtual void detached(void); - - // The Logger acting on these options calls setup() to request any - // Sinks be set up and fed back to the logger. - QPID_COMMON_EXTERN virtual void setup(qpid::log::Logger *logger); - - bool logToStderr; - bool logToStdout; - bool logToEventLog; - std::string eventSource; - std::string logFile; -}; - -}}} // namespace qpid::log::windows - -#endif /*!QPID_LOG_WINDOWS_SINKOPTIONS_H*/ diff --git a/cpp/src/qpid/management/Buffer.cpp b/cpp/src/qpid/management/Buffer.cpp deleted file mode 100644 index 7556b2a243..0000000000 --- a/cpp/src/qpid/management/Buffer.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/management/Buffer.h" -#include "qpid/framing/Buffer.h" -#include "qpid/amqp_0_10/Codecs.h" - -using namespace std; - -namespace qpid { -namespace management { - -Buffer::Buffer(char* data, uint32_t size) : impl(new framing::Buffer(data, size)) {} -Buffer::~Buffer() { delete impl; } -void Buffer::record() { impl->record(); } -void Buffer::restore(bool reRecord) { impl->restore(reRecord); } -void Buffer::reset() { impl->reset(); } -uint32_t Buffer::available() { return impl->available(); } -uint32_t Buffer::getSize() { return impl->getSize(); } -uint32_t Buffer::getPosition() { return impl->getPosition(); } -char* Buffer::getPointer() { return impl->getPointer(); } -void Buffer::putOctet(uint8_t i) { impl->putOctet(i); } -void Buffer::putShort(uint16_t i) { impl->putShort(i); } -void Buffer::putLong(uint32_t i) { impl->putLong(i); } -void Buffer::putLongLong(uint64_t i) { impl->putLongLong(i); } -void Buffer::putInt8(int8_t i) { impl->putInt8(i); } -void Buffer::putInt16(int16_t i) { impl->putInt16(i); } -void Buffer::putInt32(int32_t i) { impl->putInt32(i); } -void Buffer::putInt64(int64_t i) { impl->putInt64(i); } -void Buffer::putFloat(float i) { impl->putFloat(i); } -void Buffer::putDouble(double i) { impl->putDouble(i); } -void Buffer::putBin128(const uint8_t* i) { impl->putBin128(i); } -uint8_t Buffer::getOctet() { return impl->getOctet(); } -uint16_t Buffer::getShort() { return impl->getShort(); } -uint32_t Buffer::getLong() { return impl->getLong(); } -uint64_t Buffer::getLongLong() { return impl->getLongLong(); } -int8_t Buffer:: getInt8() { return impl-> getInt8(); } -int16_t Buffer::getInt16() { return impl->getInt16(); } -int32_t Buffer::getInt32() { return impl->getInt32(); } -int64_t Buffer::getInt64() { return impl->getInt64(); } -float Buffer::getFloat() { return impl->getFloat(); } -double Buffer::getDouble() { return impl->getDouble(); } -void Buffer::putShortString(const string& i) { impl->putShortString(i); } -void Buffer::putMediumString(const string& i) { impl->putMediumString(i); } -void Buffer::putLongString(const string& i) { impl->putLongString(i); } -void Buffer::getShortString(string& i) { impl->getShortString(i); } -void Buffer::getMediumString(string& i) { impl->getMediumString(i); } -void Buffer::getLongString(string& i) { impl->getLongString(i); } -void Buffer::getBin128(uint8_t* i) { impl->getBin128(i); } -void Buffer::putRawData(const string& i) { impl->putRawData(i); } -void Buffer::getRawData(string& s, uint32_t size) { impl->getRawData(s, size); } -void Buffer::putRawData(const uint8_t* data, size_t size) { impl->putRawData(data, size); } -void Buffer::getRawData(uint8_t* data, size_t size) { impl->getRawData(data, size); } - -void Buffer::putMap(const types::Variant::Map& i) -{ - string encoded; - amqp_0_10::MapCodec::encode(i, encoded); - impl->putRawData(encoded); -} - -void Buffer::putList(const types::Variant::List& i) -{ - string encoded; - amqp_0_10::ListCodec::encode(i, encoded); - impl->putRawData(encoded); -} - -void Buffer::getMap(types::Variant::Map& map) -{ - string encoded; - uint32_t saved = impl->getPosition(); - uint32_t length = impl->getLong(); - impl->setPosition(saved); - impl->getRawData(encoded, length + sizeof(uint32_t)); - amqp_0_10::MapCodec::decode(encoded, map); -} - -void Buffer::getList(types::Variant::List& list) -{ - string encoded; - uint32_t saved = impl->getPosition(); - uint32_t length = impl->getLong(); - impl->setPosition(saved); - impl->getRawData(encoded, length + sizeof(uint32_t)); - amqp_0_10::ListCodec::decode(encoded, list); -} - -}} diff --git a/cpp/src/qpid/management/ConnectionSettings.cpp b/cpp/src/qpid/management/ConnectionSettings.cpp deleted file mode 100644 index 1421a26867..0000000000 --- a/cpp/src/qpid/management/ConnectionSettings.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/management/ConnectionSettings.h" -#include "qpid/Version.h" - -qpid::management::ConnectionSettings::ConnectionSettings() : - protocol("tcp"), - host("localhost"), - port(5672), - locale("en_US"), - heartbeat(0), - maxChannels(32767), - maxFrameSize(65535), - bounds(2), - tcpNoDelay(false), - service(qpid::saslName), - minSsf(0), - maxSsf(256) -{} - -qpid::management::ConnectionSettings::~ConnectionSettings() {} - diff --git a/cpp/src/qpid/management/Manageable.cpp b/cpp/src/qpid/management/Manageable.cpp deleted file mode 100644 index 651215ffb5..0000000000 --- a/cpp/src/qpid/management/Manageable.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/management/Manageable.h" - -using namespace qpid::management; -using std::string; - -string Manageable::StatusText (status_t status, string text) -{ - if ((status & STATUS_USER) == STATUS_USER) - return text; - - switch (status) - { - case STATUS_OK : return "OK"; - case STATUS_UNKNOWN_OBJECT : return "UnknownObject"; - case STATUS_UNKNOWN_METHOD : return "UnknownMethod"; - case STATUS_NOT_IMPLEMENTED : return "NotImplemented"; - case STATUS_PARAMETER_INVALID : return "InvalidParameter"; - case STATUS_FEATURE_NOT_IMPLEMENTED : return "FeatureNotImplemented"; - case STATUS_FORBIDDEN : return "Forbidden"; - } - - return "??"; -} - -Manageable::status_t Manageable::ManagementMethod (uint32_t, Args&, std::string&) -{ - return STATUS_UNKNOWN_METHOD; -} - -bool Manageable::AuthorizeMethod(uint32_t, Args&, const std::string&) -{ - return true; -} - diff --git a/cpp/src/qpid/management/ManagementAgent.cpp b/cpp/src/qpid/management/ManagementAgent.cpp deleted file mode 100644 index 8a12a57fa6..0000000000 --- a/cpp/src/qpid/management/ManagementAgent.cpp +++ /dev/null @@ -1,3121 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -// NOTE on use of log levels: The criteria for using trace vs. debug -// is to use trace for log messages that are generated for each -// unbatched stats/props notification and debug for everything else. - -#include "qpid/management/ManagementAgent.h" -#include "qpid/management/ManagementObject.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/log/Statement.h" -#include <qpid/broker/Message.h> -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/AclModule.h" -#include "qpid/types/Variant.h" -#include "qpid/types/Uuid.h" -#include "qpid/framing/List.h" -#include "qpid/amqp_0_10/Codecs.h" -#include <list> -#include <iostream> -#include <fstream> -#include <sstream> -#include <typeinfo> - -using boost::intrusive_ptr; -using qpid::framing::Uuid; -using qpid::types::Variant; -using qpid::amqp_0_10::MapCodec; -using qpid::amqp_0_10::ListCodec; -using qpid::sys::Mutex; -using namespace qpid::framing; -using namespace qpid::management; -using namespace qpid::broker; -using namespace qpid; -using namespace std; -namespace _qmf = qmf::org::apache::qpid::broker; - - -namespace { - const string defaultVendorName("vendor"); - const string defaultProductName("product"); - - // Create a valid binding key substring by - // replacing all '.' chars with '_' - const string keyifyNameStr(const string& name) - { - string n2 = name; - - size_t pos = n2.find('.'); - while (pos != n2.npos) { - n2.replace(pos, 1, "_"); - pos = n2.find('.', pos); - } - return n2; - } - -struct ScopedManagementContext -{ - ScopedManagementContext(const qpid::broker::ConnectionState* context) - { - setManagementExecutionContext(context); - } - ~ScopedManagementContext() - { - setManagementExecutionContext(0); - } -}; -} - - -static Variant::Map mapEncodeSchemaId(const string& pname, - const string& cname, - const string& type, - const uint8_t *md5Sum) -{ - Variant::Map map_; - - map_["_package_name"] = pname; - map_["_class_name"] = cname; - map_["_type"] = type; - map_["_hash"] = qpid::types::Uuid(md5Sum); - return map_; -} - - -ManagementAgent::RemoteAgent::~RemoteAgent () -{ - QPID_LOG(debug, "Remote Agent removed bank=[" << brokerBank << "." << agentBank << "]"); - if (mgmtObject != 0) { - mgmtObject->resourceDestroy(); - agent.deleteObjectNowLH(mgmtObject->getObjectId()); - } -} - -ManagementAgent::ManagementAgent (const bool qmfV1, const bool qmfV2) : - threadPoolSize(1), interval(10), broker(0), timer(0), - startTime(sys::now()), - suppressed(false), disallowAllV1Methods(false), - vendorNameKey(defaultVendorName), productNameKey(defaultProductName), - qmf1Support(qmfV1), qmf2Support(qmfV2), maxReplyObjs(100), - msgBuffer(MA_BUFFER_SIZE) -{ - nextObjectId = 1; - brokerBank = 1; - bootSequence = 1; - nextRemoteBank = 10; - nextRequestSequence = 1; - clientWasAdded = false; - attrMap["_vendor"] = defaultVendorName; - attrMap["_product"] = defaultProductName; -} - -ManagementAgent::~ManagementAgent () -{ - { - sys::Mutex::ScopedLock lock (userLock); - - // Reset the shared pointers to exchanges. If this is not done now, the exchanges - // will stick around until dExchange and mExchange are implicitly destroyed (long - // after this destructor completes). Those exchanges hold references to management - // objects that will be invalid. - dExchange.reset(); - mExchange.reset(); - v2Topic.reset(); - v2Direct.reset(); - - moveNewObjectsLH(); - for (ManagementObjectMap::iterator iter = managementObjects.begin (); - iter != managementObjects.end (); - iter++) { - ManagementObject* object = iter->second; - delete object; - } - managementObjects.clear(); - } -} - -void ManagementAgent::configure(const string& _dataDir, uint16_t _interval, - qpid::broker::Broker* _broker, int _threads) -{ - dataDir = _dataDir; - interval = _interval; - broker = _broker; - threadPoolSize = _threads; - ManagementObject::maxThreads = threadPoolSize; - - // Get from file or generate and save to file. - if (dataDir.empty()) - { - uuid.generate(); - QPID_LOG (info, "ManagementAgent has no data directory, generated new broker ID: " - << uuid); - } - else - { - string filename(dataDir + "/.mbrokerdata"); - ifstream inFile(filename.c_str ()); - - if (inFile.good()) - { - inFile >> uuid; - inFile >> bootSequence; - inFile >> nextRemoteBank; - inFile.close(); - if (uuid.isNull()) { - uuid.generate(); - QPID_LOG (info, "No stored broker ID found - ManagementAgent generated broker ID: " << uuid); - } else - QPID_LOG (info, "ManagementAgent restored broker ID: " << uuid); - - // if sequence goes beyond a 12-bit field, skip zero and wrap to 1. - bootSequence++; - if (bootSequence & 0xF000) - bootSequence = 1; - writeData(); - } - else - { - uuid.generate(); - QPID_LOG (info, "ManagementAgent generated broker ID: " << uuid); - writeData(); - } - - QPID_LOG (debug, "ManagementAgent boot sequence: " << bootSequence); - } -} - -void ManagementAgent::pluginsInitialized() { - // Do this here so cluster plugin has the chance to set up the timer. - timer = &broker->getClusterTimer(); - timer->add(new Periodic(*this, interval)); -} - - -void ManagementAgent::setName(const string& vendor, const string& product, const string& instance) -{ - if (vendor.find(':') != vendor.npos) { - throw Exception("vendor string cannot contain a ':' character."); - } - if (product.find(':') != product.npos) { - throw Exception("product string cannot contain a ':' character."); - } - attrMap["_vendor"] = vendor; - attrMap["_product"] = product; - string inst; - if (instance.empty()) { - if (uuid.isNull()) - { - throw Exception("ManagementAgent::configure() must be called if default name is used."); - } - inst = uuid.str(); - } else - inst = instance; - - name_address = vendor + ":" + product + ":" + inst; - attrMap["_instance"] = inst; - attrMap["_name"] = name_address; - - vendorNameKey = keyifyNameStr(vendor); - productNameKey = keyifyNameStr(product); - instanceNameKey = keyifyNameStr(inst); -} - - -void ManagementAgent::getName(string& vendor, string& product, string& instance) -{ - vendor = std::string(attrMap["_vendor"]); - product = std::string(attrMap["_product"]); - instance = std::string(attrMap["_instance"]); -} - - -const std::string& ManagementAgent::getAddress() -{ - return name_address; -} - - -void ManagementAgent::writeData () -{ - string filename (dataDir + "/.mbrokerdata"); - ofstream outFile (filename.c_str ()); - - if (outFile.good()) - { - outFile << uuid << " " << bootSequence << " " << nextRemoteBank << endl; - outFile.close(); - } -} - -void ManagementAgent::setExchange(qpid::broker::Exchange::shared_ptr _mexchange, - qpid::broker::Exchange::shared_ptr _dexchange) -{ - mExchange = _mexchange; - dExchange = _dexchange; -} - -void ManagementAgent::setExchangeV2(qpid::broker::Exchange::shared_ptr _texchange, - qpid::broker::Exchange::shared_ptr _dexchange) -{ - v2Topic = _texchange; - v2Direct = _dexchange; -} - -void ManagementAgent::registerClass (const string& packageName, - const string& className, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall) -{ - sys::Mutex::ScopedLock lock(userLock); - PackageMap::iterator pIter = findOrAddPackageLH(packageName); - addClassLH(ManagementItem::CLASS_KIND_TABLE, pIter, className, md5Sum, schemaCall); -} - -void ManagementAgent::registerEvent (const string& packageName, - const string& eventName, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall) -{ - sys::Mutex::ScopedLock lock(userLock); - PackageMap::iterator pIter = findOrAddPackageLH(packageName); - addClassLH(ManagementItem::CLASS_KIND_EVENT, pIter, eventName, md5Sum, schemaCall); -} - -// Deprecated: V1 objects -ObjectId ManagementAgent::addObject(ManagementObject* object, uint64_t persistId, bool persistent) -{ - uint16_t sequence; - uint64_t objectNum; - - sequence = persistent ? 0 : bootSequence; - objectNum = persistId ? persistId : nextObjectId++; - - ObjectId objId(0 /*flags*/, sequence, brokerBank, objectNum); - objId.setV2Key(*object); // let object generate the v2 key - - object->setObjectId(objId); - - { - sys::Mutex::ScopedLock lock(addLock); - newManagementObjects.push_back(object); - } - QPID_LOG(debug, "Management object (V1) added: " << objId.getV2Key()); - return objId; -} - - - -ObjectId ManagementAgent::addObject(ManagementObject* object, - const string& key, - bool persistent) -{ - uint16_t sequence; - - sequence = persistent ? 0 : bootSequence; - - ObjectId objId(0 /*flags*/, sequence, brokerBank); - if (key.empty()) { - objId.setV2Key(*object); // let object generate the key - } else { - objId.setV2Key(key); - } - - object->setObjectId(objId); - { - sys::Mutex::ScopedLock lock(addLock); - newManagementObjects.push_back(object); - } - QPID_LOG(debug, "Management object added: " << objId.getV2Key()); - return objId; -} - -void ManagementAgent::raiseEvent(const ManagementEvent& event, severity_t severity) -{ - static const std::string severityStr[] = { - "emerg", "alert", "crit", "error", "warn", - "note", "info", "debug" - }; - sys::Mutex::ScopedLock lock (userLock); - uint8_t sev = (severity == SEV_DEFAULT) ? event.getSeverity() : (uint8_t) severity; - - if (qmf1Support) { - Buffer outBuffer(eventBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - encodeHeader(outBuffer, 'e'); - outBuffer.putShortString(event.getPackageName()); - outBuffer.putShortString(event.getEventName()); - outBuffer.putBin128(event.getMd5Sum()); - outBuffer.putLongLong(uint64_t(sys::Duration(sys::EPOCH, sys::now()))); - outBuffer.putOctet(sev); - string sBuf; - event.encode(sBuf); - outBuffer.putRawData(sBuf); - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, mExchange, - "console.event.1.0." + event.getPackageName() + "." + event.getEventName()); - QPID_LOG(debug, "SEND raiseEvent (v1) class=" << event.getPackageName() << "." << event.getEventName()); - } - - if (qmf2Support) { - Variant::Map map_; - Variant::Map schemaId; - Variant::Map values; - Variant::Map headers; - - map_["_schema_id"] = mapEncodeSchemaId(event.getPackageName(), - event.getEventName(), - "_event", - event.getMd5Sum()); - event.mapEncode(values); - map_["_values"] = values; - map_["_timestamp"] = uint64_t(sys::Duration(sys::EPOCH, sys::now())); - map_["_severity"] = sev; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_event"; - headers["qmf.agent"] = name_address; - - stringstream key; - key << "agent.ind.event." << keyifyNameStr(event.getPackageName()) - << "." << keyifyNameStr(event.getEventName()) - << "." << severityStr[sev] - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - key << "." << instanceNameKey; - - - string content; - Variant::List list_; - list_.push_back(map_); - ListCodec::encode(list_, content); - sendBufferLH(content, "", headers, "amqp/list", v2Topic, key.str()); - QPID_LOG(debug, "SEND raiseEvent (v2) class=" << event.getPackageName() << "." << event.getEventName()); - } -} - -ManagementAgent::Periodic::Periodic (ManagementAgent& _agent, uint32_t _seconds) - : TimerTask (sys::Duration((_seconds ? _seconds : 1) * sys::TIME_SEC), - "ManagementAgent::periodicProcessing"), - agent(_agent) {} - -ManagementAgent::Periodic::~Periodic () {} - -void ManagementAgent::Periodic::fire () -{ - agent.timer->add (new Periodic (agent, agent.interval)); - agent.periodicProcessing (); -} - -void ManagementAgent::clientAdded (const string& routingKey) -{ - sys::Mutex::ScopedLock lock(userLock); - - // - // If this routing key is not relevant to object updates, exit. - // - if ((routingKey.compare(0, 1, "#") != 0) && - (routingKey.compare(0, 9, "console.#") != 0) && - (routingKey.compare(0, 12, "console.obj.") != 0)) - return; - - // - // Mark local objects for full-update. - // - clientWasAdded = true; - - // - // If the routing key is relevant for local objects only, don't involve - // any of the remote agents. - // - if (routingKey.compare(0, 39, "console.obj.*.*.org.apache.qpid.broker.") == 0) - return; - - std::list<std::string> rkeys; - - for (RemoteAgentMap::iterator aIter = remoteAgents.begin(); - aIter != remoteAgents.end(); - aIter++) { - rkeys.push_back(aIter->second->routingKey); - } - - while (rkeys.size()) { - char localBuffer[16]; - Buffer outBuffer(localBuffer, 16); - uint32_t outLen; - - encodeHeader(outBuffer, 'x'); - outLen = outBuffer.getPosition(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, dExchange, rkeys.front()); - QPID_LOG(debug, "SEND ConsoleAddedIndication to=" << rkeys.front()); - rkeys.pop_front(); - } -} - -void ManagementAgent::clusterUpdate() { - // Called on all cluster memebers when a new member joins a cluster. - // Set clientWasAdded so that on the next periodicProcessing we will do - // a full update on all cluster members. - sys::Mutex::ScopedLock l(userLock); - moveNewObjectsLH(); // keep lists consistent with updater/updatee. - moveDeletedObjectsLH(); - clientWasAdded = true; - debugSnapshot("Cluster member joined"); -} - -void ManagementAgent::encodeHeader (Buffer& buf, uint8_t opcode, uint32_t seq) -{ - buf.putOctet ('A'); - buf.putOctet ('M'); - buf.putOctet ('2'); - buf.putOctet (opcode); - buf.putLong (seq); -} - -bool ManagementAgent::checkHeader (Buffer& buf, uint8_t *opcode, uint32_t *seq) -{ - uint8_t h1 = buf.getOctet(); - uint8_t h2 = buf.getOctet(); - uint8_t h3 = buf.getOctet(); - - *opcode = buf.getOctet(); - *seq = buf.getLong(); - - return h1 == 'A' && h2 == 'M' && h3 == '2'; -} - -// NOTE WELL: assumes userLock is held by caller (LH) -// NOTE EVEN WELLER: drops this lock when delivering the message!!! -void ManagementAgent::sendBufferLH(Buffer& buf, - uint32_t length, - qpid::broker::Exchange::shared_ptr exchange, - const string& routingKey) -{ - if (suppressed) { - QPID_LOG(debug, "Suppressing management message to " << routingKey); - return; - } - if (exchange.get() == 0) return; - - intrusive_ptr<Message> msg(new Message()); - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange->getName (), 0, 0))); - AMQFrame header((AMQHeaderBody())); - AMQFrame content((AMQContentBody())); - - content.castBody<AMQContentBody>()->decode(buf, length); - - method.setEof(false); - header.setBof(false); - header.setEof(false); - content.setBof(false); - - msg->getFrames().append(method); - msg->getFrames().append(header); - - MessageProperties* props = - msg->getFrames().getHeaders()->get<MessageProperties>(true); - props->setContentLength(length); - - DeliveryProperties* dp = - msg->getFrames().getHeaders()->get<DeliveryProperties>(true); - dp->setRoutingKey(routingKey); - - msg->getFrames().append(content); - msg->setIsManagementMessage(true); - - { - sys::Mutex::ScopedUnlock u(userLock); - - DeliverableMessage deliverable (msg); - try { - exchange->route(deliverable, routingKey, 0); - } catch(exception&) {} - } - buf.reset(); -} - - -void ManagementAgent::sendBufferLH(Buffer& buf, - uint32_t length, - const string& exchange, - const string& routingKey) -{ - qpid::broker::Exchange::shared_ptr ex(broker->getExchanges().get(exchange)); - if (ex.get() != 0) - sendBufferLH(buf, length, ex, routingKey); -} - - -// NOTE WELL: assumes userLock is held by caller (LH) -// NOTE EVEN WELLER: drops this lock when delivering the message!!! -void ManagementAgent::sendBufferLH(const string& data, - const string& cid, - const Variant::Map& headers, - const string& content_type, - qpid::broker::Exchange::shared_ptr exchange, - const string& routingKey, - uint64_t ttl_msec) -{ - Variant::Map::const_iterator i; - - if (suppressed) { - QPID_LOG(debug, "Suppressing management message to " << routingKey); - return; - } - if (exchange.get() == 0) return; - - intrusive_ptr<Message> msg(new Message()); - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange->getName (), 0, 0))); - AMQFrame header((AMQHeaderBody())); - AMQFrame content((AMQContentBody(data))); - - method.setEof(false); - header.setBof(false); - header.setEof(false); - content.setBof(false); - - msg->getFrames().append(method); - msg->getFrames().append(header); - - MessageProperties* props = - msg->getFrames().getHeaders()->get<MessageProperties>(true); - props->setContentLength(data.length()); - if (!cid.empty()) { - props->setCorrelationId(cid); - } - props->setContentType(content_type); - props->setAppId("qmf2"); - - for (i = headers.begin(); i != headers.end(); ++i) { - msg->getOrInsertHeaders().setString(i->first, i->second.asString()); - } - - DeliveryProperties* dp = - msg->getFrames().getHeaders()->get<DeliveryProperties>(true); - dp->setRoutingKey(routingKey); - if (ttl_msec) { - dp->setTtl(ttl_msec); - msg->setTimestamp(broker->getExpiryPolicy()); - } - msg->getFrames().append(content); - msg->setIsManagementMessage(true); - - { - sys::Mutex::ScopedUnlock u(userLock); - - DeliverableMessage deliverable (msg); - try { - exchange->route(deliverable, routingKey, 0); - } catch(exception&) {} - } -} - - -void ManagementAgent::sendBufferLH(const string& data, - const string& cid, - const Variant::Map& headers, - const string& content_type, - const string& exchange, - const string& routingKey, - uint64_t ttl_msec) -{ - qpid::broker::Exchange::shared_ptr ex(broker->getExchanges().get(exchange)); - if (ex.get() != 0) - sendBufferLH(data, cid, headers, content_type, ex, routingKey, ttl_msec); -} - - -/** Objects that have been added since the last periodic poll are temporarily - * saved in the newManagementObjects list. This allows objects to be - * added without needing to block on the userLock (addLock is used instead). - * These new objects need to be integrated into the object database - * (managementObjects) *before* they can be properly managed. This routine - * performs the integration. - * - * Note well: objects on the newManagementObjects list may have been - * marked as "deleted", and, possibly re-added. This would result in - * duplicate object ids. To avoid clashes, don't put deleted objects - * into the active object database. - */ -void ManagementAgent::moveNewObjectsLH() -{ - sys::Mutex::ScopedLock lock (addLock); - while (!newManagementObjects.empty()) { - ManagementObject *object = newManagementObjects.back(); - newManagementObjects.pop_back(); - - if (object->isDeleted()) { - DeletedObject::shared_ptr dptr(new DeletedObject(object, qmf1Support, qmf2Support)); - pendingDeletedObjs[dptr->getKey()].push_back(dptr); - delete object; - } else { // add to active object list, check for duplicates. - ObjectId oid = object->getObjectId(); - ManagementObjectMap::iterator destIter = managementObjects.find(oid); - if (destIter != managementObjects.end()) { - // duplicate found. It is OK if the old object has been marked - // deleted... - ManagementObject *oldObj = destIter->second; - if (oldObj->isDeleted()) { - DeletedObject::shared_ptr dptr(new DeletedObject(oldObj, qmf1Support, qmf2Support)); - pendingDeletedObjs[dptr->getKey()].push_back(dptr); - delete oldObj; - } else { - // Duplicate non-deleted objects? This is a user error - oids must be unique. - // for now, leak the old object (safer than deleting - may still be referenced) - // and complain loudly... - QPID_LOG(error, "Detected two management objects with the same identifier: " << oid); - } - } - managementObjects[oid] = object; - } - } -} - -void ManagementAgent::periodicProcessing (void) -{ -#define BUFSIZE 65536 -#define HEADROOM 4096 - debugSnapshot("Management agent periodic processing"); - sys::Mutex::ScopedLock lock (userLock); - uint32_t contentSize; - string routingKey; - string sBuf; - - uint64_t uptime = sys::Duration(startTime, sys::now()); - static_cast<_qmf::Broker*>(broker->GetManagementObject())->set_uptime(uptime); - - moveNewObjectsLH(); - - // - // Clear the been-here flag on all objects in the map. - // - for (ManagementObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - iter++) { - ManagementObject* object = iter->second; - object->setFlags(0); - if (clientWasAdded) { - object->setForcePublish(true); - } - } - - clientWasAdded = false; - - // first send the pending deletes before sending updates. This prevents a - // "false delete" scenario: if an object was deleted then re-added during - // the last poll cycle, it will have a delete entry and an active entry. - // if we sent the active update first, _then_ the delete update, clients - // would incorrectly think the object was deleted. See QPID-2997 - // - bool objectsDeleted = moveDeletedObjectsLH(); - if (!pendingDeletedObjs.empty()) { - // use a temporary copy of the pending deletes so dropping the lock when - // the buffer is sent is safe. - PendingDeletedObjsMap tmp(pendingDeletedObjs); - pendingDeletedObjs.clear(); - - for (PendingDeletedObjsMap::iterator mIter = tmp.begin(); mIter != tmp.end(); mIter++) { - std::string packageName; - std::string className; - msgBuffer.reset(); - uint32_t v1Objs = 0; - uint32_t v2Objs = 0; - Variant::List list_; - - size_t pos = mIter->first.find(":"); - packageName = mIter->first.substr(0, pos); - className = mIter->first.substr(pos+1); - - for (DeletedObjectList::iterator lIter = mIter->second.begin(); - lIter != mIter->second.end(); lIter++) { - msgBuffer.makeAvailable(HEADROOM); // Make sure there's buffer space. - std::string oid = (*lIter)->objectId; - if (!(*lIter)->encodedV1Config.empty()) { - encodeHeader(msgBuffer, 'c'); - msgBuffer.putRawData((*lIter)->encodedV1Config); - QPID_LOG(trace, "Deleting V1 properties " << oid - << " len=" << (*lIter)->encodedV1Config.size()); - v1Objs++; - } - if (!(*lIter)->encodedV1Inst.empty()) { - encodeHeader(msgBuffer, 'i'); - msgBuffer.putRawData((*lIter)->encodedV1Inst); - QPID_LOG(trace, "Deleting V1 statistics " << oid - << " len=" << (*lIter)->encodedV1Inst.size()); - v1Objs++; - } - if (v1Objs >= maxReplyObjs) { - v1Objs = 0; - contentSize = msgBuffer.getSize(); - stringstream key; - key << "console.obj.1.0." << packageName << "." << className; - msgBuffer.reset(); - sendBufferLH(msgBuffer, contentSize, mExchange, key.str()); // UNLOCKS USERLOCK - QPID_LOG(debug, "SEND V1 Multicast ContentInd V1 (delete) to=" - << key.str() << " len=" << contentSize); - } - - if (!(*lIter)->encodedV2.empty()) { - QPID_LOG(trace, "Deleting V2 " << "map=" << (*lIter)->encodedV2); - list_.push_back((*lIter)->encodedV2); - if (++v2Objs >= maxReplyObjs) { - v2Objs = 0; - - string content; - ListCodec::encode(list_, content); - list_.clear(); - if (content.length()) { - stringstream key; - Variant::Map headers; - key << "agent.ind.data." << keyifyNameStr(packageName) - << "." << keyifyNameStr(className) - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - key << "." << instanceNameKey; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = name_address; - - sendBufferLH(content, "", headers, "amqp/list", v2Topic, key.str()); // UNLOCKS USERLOCK - QPID_LOG(debug, "SEND Multicast ContentInd V2 (delete) to=" << key.str() << " len=" << content.length()); - } - } - } - } // end current list - - // send any remaining objects... - - if (v1Objs) { - contentSize = BUFSIZE - msgBuffer.available(); - stringstream key; - key << "console.obj.1.0." << packageName << "." << className; - msgBuffer.reset(); - sendBufferLH(msgBuffer, contentSize, mExchange, key.str()); // UNLOCKS USERLOCK - QPID_LOG(debug, "SEND V1 Multicast ContentInd V1 (delete) to=" << key.str() << " len=" << contentSize); - } - - if (!list_.empty()) { - string content; - ListCodec::encode(list_, content); - list_.clear(); - if (content.length()) { - stringstream key; - Variant::Map headers; - key << "agent.ind.data." << keyifyNameStr(packageName) - << "." << keyifyNameStr(className) - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - key << "." << instanceNameKey; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = name_address; - - sendBufferLH(content, "", headers, "amqp/list", v2Topic, key.str()); // UNLOCKS USERLOCK - QPID_LOG(debug, "SEND Multicast ContentInd V2 (delete) to=" << key.str() << " len=" << content.length()); - } - } - } // end map - } - - // - // Process the entire object map. Remember: we drop the userLock each time we call - // sendBuffer(). This allows the managementObjects map to be altered during the - // sendBuffer() call, so always restart the search after a sendBuffer() call - // - while (1) { - msgBuffer.reset(); - Variant::List list_; - uint32_t pcount; - uint32_t scount; - uint32_t v1Objs, v2Objs; - ManagementObjectMap::iterator baseIter; - std::string packageName; - std::string className; - - for (baseIter = managementObjects.begin(); - baseIter != managementObjects.end(); - baseIter++) { - ManagementObject* baseObject = baseIter->second; - // - // Skip until we find a base object requiring processing... - // - if (baseObject->getFlags() == 0) { - packageName = baseObject->getPackageName(); - className = baseObject->getClassName(); - break; - } - } - - if (baseIter == managementObjects.end()) - break; // done - all objects processed - - pcount = scount = 0; - v1Objs = 0; - v2Objs = 0; - list_.clear(); - msgBuffer.reset(); - - for (ManagementObjectMap::iterator iter = baseIter; - iter != managementObjects.end(); - iter++) { - msgBuffer.makeAvailable(HEADROOM); // Make sure there's buffer space - ManagementObject* baseObject = baseIter->second; - ManagementObject* object = iter->second; - bool send_stats, send_props; - if (baseObject->isSameClass(*object) && object->getFlags() == 0) { - object->setFlags(1); - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - // skip any objects marked deleted since our first pass. Deal with them - // on the next periodic cycle... - if (object->isDeleted()) { - continue; - } - - send_props = (object->getConfigChanged() || object->getForcePublish()); - send_stats = (object->hasInst() && (object->getInstChanged() || object->getForcePublish())); - - if (send_props && qmf1Support) { - size_t pos = msgBuffer.getPosition(); - encodeHeader(msgBuffer, 'c'); - sBuf.clear(); - object->writeProperties(sBuf); - msgBuffer.putRawData(sBuf); - QPID_LOG(trace, "Changed V1 properties " - << object->getObjectId().getV2Key() - << " len=" << msgBuffer.getPosition()-pos); - ++v1Objs; - } - - if (send_stats && qmf1Support) { - size_t pos = msgBuffer.getPosition(); - encodeHeader(msgBuffer, 'i'); - sBuf.clear(); - object->writeStatistics(sBuf); - msgBuffer.putRawData(sBuf); - QPID_LOG(trace, "Changed V1 statistics " - << object->getObjectId().getV2Key() - << " len=" << msgBuffer.getPosition()-pos); - ++v1Objs; - } - - if ((send_stats || send_props) && qmf2Support) { - Variant::Map map_; - Variant::Map values; - Variant::Map oid; - - object->getObjectId().mapEncode(oid); - map_["_object_id"] = oid; - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - "_data", - object->getMd5Sum()); - object->writeTimestamps(map_); - object->mapEncodeValues(values, send_props, send_stats); - map_["_values"] = values; - list_.push_back(map_); - v2Objs++; - QPID_LOG(trace, "Changed V2" - << (send_stats? " statistics":"") - << (send_props? " properties":"") - << " map=" << map_); - } - - if (send_props) pcount++; - if (send_stats) scount++; - - object->setForcePublish(false); - - if ((qmf1Support && (v1Objs >= maxReplyObjs)) || - (qmf2Support && (v2Objs >= maxReplyObjs))) - break; // have enough objects, send an indication... - } - } - - if (pcount || scount) { - if (qmf1Support) { - contentSize = BUFSIZE - msgBuffer.available(); - if (contentSize > 0) { - stringstream key; - key << "console.obj.1.0." << packageName << "." << className; - msgBuffer.reset(); - sendBufferLH(msgBuffer, contentSize, mExchange, key.str()); // UNLOCKS USERLOCK - QPID_LOG(debug, "SEND V1 Multicast ContentInd to=" << key.str() - << " props=" << pcount - << " stats=" << scount - << " len=" << contentSize); - } - } - - if (qmf2Support) { - string content; - ListCodec::encode(list_, content); - if (content.length()) { - stringstream key; - Variant::Map headers; - key << "agent.ind.data." << keyifyNameStr(packageName) - << "." << keyifyNameStr(className) - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - key << "." << instanceNameKey; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = name_address; - - sendBufferLH(content, "", headers, "amqp/list", v2Topic, key.str()); // UNLOCKS USERLOCK - QPID_LOG(debug, "SEND Multicast ContentInd to=" << key.str() - << " props=" << pcount - << " stats=" << scount - << " len=" << content.length()); - } - } - } - } // end processing updates for all objects - - if (objectsDeleted) deleteOrphanedAgentsLH(); - - // heartbeat generation - - if (qmf1Support) { -#define BUFSIZE 65536 - uint32_t contentSize; - char msgChars[BUFSIZE]; - Buffer msgBuffer(msgChars, BUFSIZE); - encodeHeader(msgBuffer, 'h'); - msgBuffer.putLongLong(uint64_t(sys::Duration(sys::EPOCH, sys::now()))); - - contentSize = BUFSIZE - msgBuffer.available (); - msgBuffer.reset (); - routingKey = "console.heartbeat.1.0"; - sendBufferLH(msgBuffer, contentSize, mExchange, routingKey); - QPID_LOG(debug, "SEND HeartbeatInd to=" << routingKey); - } - - if (qmf2Support) { - std::stringstream addr_key; - - addr_key << "agent.ind.heartbeat." << vendorNameKey << "." << productNameKey; - if (!instanceNameKey.empty()) - addr_key << "." << instanceNameKey; - - Variant::Map map; - Variant::Map headers; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_agent_heartbeat_indication"; - headers["qmf.agent"] = name_address; - - map["_values"] = attrMap; - map["_values"].asMap()["_timestamp"] = uint64_t(sys::Duration(sys::EPOCH, sys::now())); - map["_values"].asMap()["_heartbeat_interval"] = interval; - map["_values"].asMap()["_epoch"] = bootSequence; - - string content; - MapCodec::encode(map, content); - - // Set TTL (in msecs) on outgoing heartbeat indications based on the interval - // time to prevent stale heartbeats from getting to the consoles. - sendBufferLH(content, "", headers, "amqp/map", v2Topic, addr_key.str(), interval * 2 * 1000); - - QPID_LOG(debug, "SENT AgentHeartbeat name=" << name_address); - } -} - -void ManagementAgent::deleteObjectNowLH(const ObjectId& oid) -{ - ManagementObjectMap::iterator iter = managementObjects.find(oid); - if (iter == managementObjects.end()) - return; - ManagementObject* object = iter->second; - if (!object->isDeleted()) - return; - - // since sendBufferLH drops the userLock, don't call it until we - // are done manipulating the object. -#define DNOW_BUFSIZE 2048 - char msgChars[DNOW_BUFSIZE]; - Buffer msgBuffer(msgChars, DNOW_BUFSIZE); - Variant::List list_; - stringstream v1key, v2key; - - if (qmf1Support) { - string sBuf; - - v1key << "console.obj.1.0." << object->getPackageName() << "." << object->getClassName(); - encodeHeader(msgBuffer, 'c'); - object->writeProperties(sBuf); - msgBuffer.putRawData(sBuf); - } - - if (qmf2Support) { - Variant::Map map_; - Variant::Map values; - - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - "_data", - object->getMd5Sum()); - object->writeTimestamps(map_); - object->mapEncodeValues(values, true, false); - map_["_values"] = values; - list_.push_back(map_); - v2key << "agent.ind.data." << keyifyNameStr(object->getPackageName()) - << "." << keyifyNameStr(object->getClassName()) - << "." << vendorNameKey - << "." << productNameKey; - if (!instanceNameKey.empty()) - v2key << "." << instanceNameKey; - } - - object = 0; - managementObjects.erase(oid); - - // object deleted, ok to drop lock now. - - if (qmf1Support) { - uint32_t contentSize = msgBuffer.getPosition(); - msgBuffer.reset(); - sendBufferLH(msgBuffer, contentSize, mExchange, v1key.str()); - QPID_LOG(debug, "SEND Immediate(delete) ContentInd to=" << v1key.str()); - } - - if (qmf2Support) { - Variant::Map headers; - headers["method"] = "indication"; - headers["qmf.opcode"] = "_data_indication"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = name_address; - - string content; - ListCodec::encode(list_, content); - sendBufferLH(content, "", headers, "amqp/list", v2Topic, v2key.str()); - QPID_LOG(debug, "SEND Immediate(delete) ContentInd to=" << v2key.str()); - } -} - -void ManagementAgent::sendCommandCompleteLH(const string& replyToKey, uint32_t sequence, - uint32_t code, const string& text) -{ - Buffer outBuffer (outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - encodeHeader (outBuffer, 'z', sequence); - outBuffer.putLong (code); - outBuffer.putShortString (text); - outLen = MA_BUFFER_SIZE - outBuffer.available (); - outBuffer.reset (); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND CommandCompleteInd code=" << code << " text=" << text << " to=" << - replyToKey << " seq=" << sequence); -} - -void ManagementAgent::sendExceptionLH(const string& rte, const string& rtk, const string& cid, - const string& text, uint32_t code, bool viaLocal) -{ - static const string addr_exchange("qmf.default.direct"); - - Variant::Map map; - Variant::Map headers; - Variant::Map values; - string content; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_exception"; - headers["qmf.agent"] = viaLocal ? "broker" : name_address; - - values["error_code"] = code; - values["error_text"] = text; - map["_values"] = values; - - MapCodec::encode(map, content); - sendBufferLH(content, cid, headers, "amqp/map", rte, rtk); - - QPID_LOG(debug, "SENT Exception code=" << code <<" text=" << text); -} - -bool ManagementAgent::dispatchCommand (Deliverable& deliverable, - const string& routingKey, - const FieldTable* /*args*/, - const bool topic, - int qmfVersion) -{ - sys::Mutex::ScopedLock lock (userLock); - Message& msg = ((DeliverableMessage&) deliverable).getMessage (); - - if (topic && qmfVersion == 1) { - - // qmf1 is bound only to the topic management exchange. - // Parse the routing key. This management broker should act as though it - // is bound to the exchange to match the following keys: - // - // agent.1.0.# - // broker - // schema.# - - if (routingKey == "broker") { - dispatchAgentCommandLH(msg); - return false; - } - - if (routingKey.length() > 6) { - - if (routingKey.compare(0, 9, "agent.1.0") == 0) { - dispatchAgentCommandLH(msg); - return false; - } - - if (routingKey.compare(0, 8, "agent.1.") == 0) { - return authorizeAgentMessageLH(msg); - } - - if (routingKey.compare(0, 7, "schema.") == 0) { - dispatchAgentCommandLH(msg); - return true; - } - } - } - - if (qmfVersion == 2) { - - if (topic) { - // Intercept messages bound to: - // "console.ind.locate.# - process these messages, and also allow them to be forwarded. - if (routingKey == "console.request.agent_locate") { - dispatchAgentCommandLH(msg); - return true; - } - - } else { // direct exchange - - // Intercept messages bound to: - // "broker" - generic alias for the local broker - // "<name_address>" - the broker agent's proper name - // and do not forward them futher - if (routingKey == "broker" || routingKey == name_address) { - dispatchAgentCommandLH(msg, routingKey == "broker"); - return false; - } - } - } - - return true; -} - -void ManagementAgent::handleMethodRequestLH(Buffer& inBuffer, const string& replyToKey, uint32_t sequence, const ConnectionToken* connToken) -{ - moveNewObjectsLH(); - - string methodName; - string packageName; - string className; - uint8_t hash[16]; - Buffer outBuffer (outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - AclModule* acl = broker->getAcl(); - string inArgs; - - string sBuf; - inBuffer.getRawData(sBuf, 16); - ObjectId objId; - objId.decode(sBuf); - inBuffer.getShortString(packageName); - inBuffer.getShortString(className); - inBuffer.getBin128(hash); - inBuffer.getShortString(methodName); - inBuffer.getRawData(inArgs, inBuffer.available()); - - QPID_LOG(debug, "RECV MethodRequest (v1) class=" << packageName << ":" << className << "(" << Uuid(hash) << ") method=" << - methodName << " replyTo=" << replyToKey); - - encodeHeader(outBuffer, 'm', sequence); - - if (disallowAllV1Methods) { - outBuffer.putLong(Manageable::STATUS_FORBIDDEN); - outBuffer.putMediumString("QMFv1 methods forbidden on this broker, use QMFv2"); - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND MethodResponse status=FORBIDDEN reason='All QMFv1 Methods Forbidden' seq=" << sequence); - return; - } - - DisallowedMethods::const_iterator i = disallowed.find(make_pair(className, methodName)); - if (i != disallowed.end()) { - outBuffer.putLong(Manageable::STATUS_FORBIDDEN); - outBuffer.putMediumString(i->second); - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND MethodResponse status=FORBIDDEN text=" << i->second << " seq=" << sequence); - return; - } - - string userId = ((const qpid::broker::ConnectionState*) connToken)->getUserId(); - if (acl != 0) { - map<acl::Property, string> params; - params[acl::PROP_SCHEMAPACKAGE] = packageName; - params[acl::PROP_SCHEMACLASS] = className; - - if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_METHOD, methodName, ¶ms)) { - outBuffer.putLong(Manageable::STATUS_FORBIDDEN); - outBuffer.putMediumString(Manageable::StatusText(Manageable::STATUS_FORBIDDEN)); - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND MethodResponse status=FORBIDDEN" << " seq=" << sequence); - return; - } - } - - ManagementObjectMap::iterator iter = numericFind(objId); - if (iter == managementObjects.end() || iter->second->isDeleted()) { - outBuffer.putLong (Manageable::STATUS_UNKNOWN_OBJECT); - outBuffer.putMediumString(Manageable::StatusText (Manageable::STATUS_UNKNOWN_OBJECT)); - } else { - if ((iter->second->getPackageName() != packageName) || - (iter->second->getClassName() != className)) { - outBuffer.putLong (Manageable::STATUS_PARAMETER_INVALID); - outBuffer.putMediumString(Manageable::StatusText (Manageable::STATUS_PARAMETER_INVALID)); - } - else - try { - outBuffer.record(); - sys::Mutex::ScopedUnlock u(userLock); - string outBuf; - iter->second->doMethod(methodName, inArgs, outBuf, userId); - outBuffer.putRawData(outBuf); - } catch(exception& e) { - outBuffer.restore(); - outBuffer.putLong(Manageable::STATUS_EXCEPTION); - outBuffer.putMediumString(e.what()); - } - } - - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND MethodResponse (v1) to=" << replyToKey << " seq=" << sequence); -} - - -void ManagementAgent::handleMethodRequestLH (const string& body, const string& rte, const string& rtk, - const string& cid, const ConnectionToken* connToken, bool viaLocal) -{ - moveNewObjectsLH(); - - string methodName; - Variant::Map inMap; - MapCodec::decode(body, inMap); - Variant::Map::const_iterator oid, mid; - string content; - string error; - uint32_t errorCode(0); - - Variant::Map outMap; - Variant::Map headers; - - headers["method"] = "response"; - headers["qmf.opcode"] = "_method_response"; - headers["qmf.agent"] = viaLocal ? "broker" : name_address; - - if ((oid = inMap.find("_object_id")) == inMap.end() || - (mid = inMap.find("_method_name")) == inMap.end()) { - sendExceptionLH(rte, rtk, cid, Manageable::StatusText(Manageable::STATUS_PARAMETER_INVALID), - Manageable::STATUS_PARAMETER_INVALID, viaLocal); - return; - } - - ObjectId objId; - Variant::Map inArgs; - Variant::Map callMap; - - try { - // coversions will throw if input is invalid. - objId = ObjectId(oid->second.asMap()); - methodName = mid->second.getString(); - - mid = inMap.find("_arguments"); - if (mid != inMap.end()) { - inArgs = (mid->second).asMap(); - } - } catch(exception& e) { - sendExceptionLH(rte, rtk, cid, e.what(), Manageable::STATUS_EXCEPTION, viaLocal); - return; - } - - ManagementObjectMap::iterator iter = managementObjects.find(objId); - - if (iter == managementObjects.end() || iter->second->isDeleted()) { - stringstream estr; - estr << "No object found with ID=" << objId; - sendExceptionLH(rte, rtk, cid, estr.str(), 1, viaLocal); - return; - } - - // validate - AclModule* acl = broker->getAcl(); - DisallowedMethods::const_iterator i; - - i = disallowed.find(make_pair(iter->second->getClassName(), methodName)); - if (i != disallowed.end()) { - sendExceptionLH(rte, rtk, cid, i->second, Manageable::STATUS_FORBIDDEN, viaLocal); - return; - } - - string userId = ((const qpid::broker::ConnectionState*) connToken)->getUserId(); - if (acl != 0) { - map<acl::Property, string> params; - params[acl::PROP_SCHEMAPACKAGE] = iter->second->getPackageName(); - params[acl::PROP_SCHEMACLASS] = iter->second->getClassName(); - - if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_METHOD, methodName, ¶ms)) { - sendExceptionLH(rte, rtk, cid, Manageable::StatusText(Manageable::STATUS_FORBIDDEN), - Manageable::STATUS_FORBIDDEN, viaLocal); - return; - } - } - - // invoke the method - - QPID_LOG(debug, "RECV MethodRequest (v2) class=" << iter->second->getPackageName() - << ":" << iter->second->getClassName() << " method=" << - methodName << " replyTo=" << rte << "/" << rtk << " objId=" << objId << " inArgs=" << inArgs); - - try { - sys::Mutex::ScopedUnlock u(userLock); - iter->second->doMethod(methodName, inArgs, callMap, userId); - errorCode = callMap["_status_code"].asUint32(); - if (errorCode == 0) { - outMap["_arguments"] = Variant::Map(); - for (Variant::Map::const_iterator iter = callMap.begin(); - iter != callMap.end(); iter++) - if (iter->first != "_status_code" && iter->first != "_status_text") - outMap["_arguments"].asMap()[iter->first] = iter->second; - } else - error = callMap["_status_text"].asString(); - } catch(exception& e) { - sendExceptionLH(rte, rtk, cid, e.what(), Manageable::STATUS_EXCEPTION, viaLocal); - return; - } - - if (errorCode != 0) { - sendExceptionLH(rte, rtk, cid, error, errorCode, viaLocal); - return; - } - - MapCodec::encode(outMap, content); - sendBufferLH(content, cid, headers, "amqp/map", rte, rtk); - QPID_LOG(debug, "SEND MethodResponse (v2) to=" << rte << "/" << rtk << " seq=" << cid << " map=" << outMap); -} - - -void ManagementAgent::handleBrokerRequestLH (Buffer&, const string& replyToKey, uint32_t sequence) -{ - Buffer outBuffer (outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - QPID_LOG(debug, "RECV BrokerRequest replyTo=" << replyToKey); - - encodeHeader (outBuffer, 'b', sequence); - uuid.encode (outBuffer); - - outLen = MA_BUFFER_SIZE - outBuffer.available (); - outBuffer.reset (); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND BrokerResponse to=" << replyToKey); -} - -void ManagementAgent::handlePackageQueryLH (Buffer&, const string& replyToKey, uint32_t sequence) -{ - QPID_LOG(debug, "RECV PackageQuery replyTo=" << replyToKey); - Buffer outBuffer (outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - for (PackageMap::iterator pIter = packages.begin (); - pIter != packages.end (); - pIter++) - { - encodeHeader (outBuffer, 'p', sequence); - encodePackageIndication (outBuffer, pIter); - } - - outLen = MA_BUFFER_SIZE - outBuffer.available (); - if (outLen) { - outBuffer.reset (); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND PackageInd to=" << replyToKey << " seq=" << sequence); - } - - sendCommandCompleteLH(replyToKey, sequence); -} - -void ManagementAgent::handlePackageIndLH (Buffer& inBuffer, const string& replyToKey, uint32_t sequence) -{ - string packageName; - - inBuffer.getShortString(packageName); - - QPID_LOG(debug, "RECV PackageInd package=" << packageName << " replyTo=" << replyToKey << " seq=" << sequence); - - findOrAddPackageLH(packageName); -} - -void ManagementAgent::handleClassQueryLH(Buffer& inBuffer, const string& replyToKey, uint32_t sequence) -{ - string packageName; - - inBuffer.getShortString(packageName); - - QPID_LOG(debug, "RECV ClassQuery package=" << packageName << " replyTo=" << replyToKey << " seq=" << sequence); - - PackageMap::iterator pIter = packages.find(packageName); - if (pIter != packages.end()) - { - typedef std::pair<SchemaClassKey, uint8_t> _ckeyType; - std::list<_ckeyType> classes; - ClassMap &cMap = pIter->second; - for (ClassMap::iterator cIter = cMap.begin(); - cIter != cMap.end(); - cIter++) { - if (cIter->second.hasSchema()) { - classes.push_back(make_pair(cIter->first, cIter->second.kind)); - } - } - - while (classes.size()) { - Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - encodeHeader(outBuffer, 'q', sequence); - encodeClassIndication(outBuffer, packageName, classes.front().first, classes.front().second); - - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND ClassInd class=" << packageName << ":" << classes.front().first.name << - "(" << Uuid(classes.front().first.hash) << ") to=" << replyToKey << " seq=" << sequence); - classes.pop_front(); - } - - } - sendCommandCompleteLH(replyToKey, sequence); -} - -void ManagementAgent::handleClassIndLH (Buffer& inBuffer, const string& replyToKey, uint32_t) -{ - string packageName; - SchemaClassKey key; - - uint8_t kind = inBuffer.getOctet(); - inBuffer.getShortString(packageName); - inBuffer.getShortString(key.name); - inBuffer.getBin128(key.hash); - - QPID_LOG(debug, "RECV ClassInd class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << - "), replyTo=" << replyToKey); - - PackageMap::iterator pIter = findOrAddPackageLH(packageName); - ClassMap::iterator cIter = pIter->second.find(key); - if (cIter == pIter->second.end() || !cIter->second.hasSchema()) { - Buffer outBuffer (outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - uint32_t sequence = nextRequestSequence++; - - // Schema Request - encodeHeader (outBuffer, 'S', sequence); - outBuffer.putShortString(packageName); - key.encode(outBuffer); - outLen = MA_BUFFER_SIZE - outBuffer.available (); - outBuffer.reset (); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND SchemaRequest class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << - "), to=" << replyToKey << " seq=" << sequence); - - if (cIter != pIter->second.end()) - pIter->second.erase(key); - - pIter->second.insert(pair<SchemaClassKey, SchemaClass>(key, SchemaClass(kind, sequence))); - } -} - -void ManagementAgent::SchemaClass::appendSchema(Buffer& buf) -{ - // If the management package is attached locally (embedded in the broker or - // linked in via plug-in), call the schema handler directly. If the package - // is from a remote management agent, send the stored schema information. - - if (writeSchemaCall != 0) { - string schema; - writeSchemaCall(schema); - buf.putRawData(schema); - } else - buf.putRawData(reinterpret_cast<uint8_t*>(&data[0]), data.size()); -} - -void ManagementAgent::handleSchemaRequestLH(Buffer& inBuffer, const string& rte, const string& rtk, uint32_t sequence) -{ - string packageName; - SchemaClassKey key; - - inBuffer.getShortString (packageName); - key.decode(inBuffer); - - QPID_LOG(debug, "RECV SchemaRequest class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << - "), replyTo=" << rte << "/" << rtk << " seq=" << sequence); - - PackageMap::iterator pIter = packages.find(packageName); - if (pIter != packages.end()) { - ClassMap& cMap = pIter->second; - ClassMap::iterator cIter = cMap.find(key); - if (cIter != cMap.end()) { - Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - SchemaClass& classInfo = cIter->second; - - if (classInfo.hasSchema()) { - encodeHeader(outBuffer, 's', sequence); - classInfo.appendSchema(outBuffer); - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, rte, rtk); - QPID_LOG(debug, "SEND SchemaResponse to=" << rte << "/" << rtk << " seq=" << sequence); - } - else - sendCommandCompleteLH(rtk, sequence, 1, "Schema not available"); - } - else - sendCommandCompleteLH(rtk, sequence, 1, "Class key not found"); - } - else - sendCommandCompleteLH(rtk, sequence, 1, "Package not found"); -} - -void ManagementAgent::handleSchemaResponseLH(Buffer& inBuffer, const string& /*replyToKey*/, uint32_t sequence) -{ - string packageName; - SchemaClassKey key; - - inBuffer.record(); - inBuffer.getOctet(); - inBuffer.getShortString(packageName); - key.decode(inBuffer); - inBuffer.restore(); - - QPID_LOG(debug, "RECV SchemaResponse class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << ")" << " seq=" << sequence); - - PackageMap::iterator pIter = packages.find(packageName); - if (pIter != packages.end()) { - ClassMap& cMap = pIter->second; - ClassMap::iterator cIter = cMap.find(key); - if (cIter != cMap.end() && cIter->second.pendingSequence == sequence) { - size_t length = validateSchema(inBuffer, cIter->second.kind); - if (length == 0) { - QPID_LOG(warning, "Management Agent received invalid schema response: " << packageName << "." << key.name); - cMap.erase(key); - } else { - cIter->second.data.resize(length); - inBuffer.getRawData(reinterpret_cast<uint8_t*>(&cIter->second.data[0]), length); - - // Publish a class-indication message - Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - encodeHeader(outBuffer, 'q'); - encodeClassIndication(outBuffer, pIter->first, cIter->first, cIter->second.kind); - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, mExchange, "schema.class"); - QPID_LOG(debug, "SEND ClassInd class=" << packageName << ":" << key.name << "(" << Uuid(key.hash) << ")" << - " to=schema.class"); - } - } - } -} - -bool ManagementAgent::bankInUse (uint32_t bank) -{ - for (RemoteAgentMap::iterator aIter = remoteAgents.begin(); - aIter != remoteAgents.end(); - aIter++) - if (aIter->second->agentBank == bank) - return true; - return false; -} - -uint32_t ManagementAgent::allocateNewBank () -{ - while (bankInUse (nextRemoteBank)) - nextRemoteBank++; - - uint32_t allocated = nextRemoteBank++; - writeData (); - return allocated; -} - -uint32_t ManagementAgent::assignBankLH (uint32_t requestedBank) -{ - if (requestedBank == 0 || bankInUse (requestedBank)) - return allocateNewBank (); - return requestedBank; -} - -void ManagementAgent::deleteOrphanedAgentsLH() -{ - list<ObjectId> deleteList; - - for (RemoteAgentMap::const_iterator aIter = remoteAgents.begin(); aIter != remoteAgents.end(); aIter++) { - bool found = false; - - for (ManagementObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - iter++) { - if (iter->first == aIter->first && !iter->second->isDeleted()) { - found = true; - break; - } - } - - if (!found) - deleteList.push_back(aIter->first); - } - - for (list<ObjectId>::const_iterator dIter = deleteList.begin(); dIter != deleteList.end(); dIter++) - remoteAgents.erase(*dIter); -} - -void ManagementAgent::handleAttachRequestLH (Buffer& inBuffer, const string& replyToKey, uint32_t sequence, const ConnectionToken* connToken) -{ - string label; - uint32_t requestedBrokerBank, requestedAgentBank; - uint32_t assignedBank; - ObjectId connectionRef = ((const ConnectionState*) connToken)->GetManagementObject()->getObjectId(); - Uuid systemId; - - moveNewObjectsLH(); - deleteOrphanedAgentsLH(); - RemoteAgentMap::iterator aIter = remoteAgents.find(connectionRef); - if (aIter != remoteAgents.end()) { - // There already exists an agent on this session. Reject the request. - sendCommandCompleteLH(replyToKey, sequence, 1, "Connection already has remote agent"); - return; - } - - inBuffer.getShortString(label); - systemId.decode(inBuffer); - requestedBrokerBank = inBuffer.getLong(); - requestedAgentBank = inBuffer.getLong(); - - QPID_LOG(debug, "RECV (Agent)AttachRequest label=" << label << " reqBrokerBank=" << requestedBrokerBank << - " reqAgentBank=" << requestedAgentBank << " replyTo=" << replyToKey << " seq=" << sequence); - - assignedBank = assignBankLH(requestedAgentBank); - - boost::shared_ptr<RemoteAgent> agent(new RemoteAgent(*this)); - agent->brokerBank = brokerBank; - agent->agentBank = assignedBank; - agent->routingKey = replyToKey; - agent->connectionRef = connectionRef; - agent->mgmtObject = new _qmf::Agent (this, agent.get()); - agent->mgmtObject->set_connectionRef(agent->connectionRef); - agent->mgmtObject->set_label (label); - agent->mgmtObject->set_registeredTo (broker->GetManagementObject()->getObjectId()); - agent->mgmtObject->set_systemId ((const unsigned char*)systemId.data()); - agent->mgmtObject->set_brokerBank (brokerBank); - agent->mgmtObject->set_agentBank (assignedBank); - addObject (agent->mgmtObject, 0); - remoteAgents[connectionRef] = agent; - - QPID_LOG(debug, "Remote Agent registered bank=[" << brokerBank << "." << assignedBank << "] replyTo=" << replyToKey); - - // Send an Attach Response - Buffer outBuffer (outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - encodeHeader (outBuffer, 'a', sequence); - outBuffer.putLong (brokerBank); - outBuffer.putLong (assignedBank); - outLen = MA_BUFFER_SIZE - outBuffer.available (); - outBuffer.reset (); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND AttachResponse brokerBank=" << brokerBank << " agentBank=" << assignedBank << - " to=" << replyToKey << " seq=" << sequence); -} - -void ManagementAgent::handleGetQueryLH(Buffer& inBuffer, const string& replyToKey, uint32_t sequence) -{ - FieldTable ft; - FieldTable::ValuePtr value; - - moveNewObjectsLH(); - - ft.decode(inBuffer); - - QPID_LOG(debug, "RECV GetQuery (v1) query=" << ft << " seq=" << sequence); - - value = ft.get("_class"); - if (value.get() == 0 || !value->convertsTo<string>()) { - value = ft.get("_objectid"); - if (value.get() == 0 || !value->convertsTo<string>()) - return; - - ObjectId selector(value->get<string>()); - ManagementObjectMap::iterator iter = numericFind(selector); - if (iter != managementObjects.end()) { - ManagementObject* object = iter->second; - Buffer outBuffer (outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - if (!object->isDeleted()) { - string sBuf; - encodeHeader(outBuffer, 'g', sequence); - object->writeProperties(sBuf); - outBuffer.putRawData(sBuf); - sBuf.clear(); - object->writeStatistics(sBuf, true); - outBuffer.putRawData(sBuf); - outLen = MA_BUFFER_SIZE - outBuffer.available (); - outBuffer.reset (); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND GetResponse (v1) to=" << replyToKey << " seq=" << sequence); - } - } - sendCommandCompleteLH(replyToKey, sequence); - return; - } - - string className (value->get<string>()); - std::list<ObjectId>matches; - - // build up a set of all objects to be dumped - for (ManagementObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - iter++) { - ManagementObject* object = iter->second; - if (object->getClassName () == className) { - matches.push_back(object->getObjectId()); - } - } - - // send them (as sendBufferLH drops the userLock) - Buffer outBuffer (outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - while (matches.size()) { - ObjectId objId = matches.front(); - ManagementObjectMap::iterator oIter = managementObjects.find( objId ); - if (oIter != managementObjects.end()) { - ManagementObject* object = oIter->second; - - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - if (!object->isDeleted()) { - string sProps, sStats; - object->writeProperties(sProps); - object->writeStatistics(sStats, true); - - size_t len = 8 + sProps.length() + sStats.length(); // 8 == size of header in bytes. - if (len > MA_BUFFER_SIZE) { - QPID_LOG(error, "Object " << objId << " too large for output buffer - discarded!"); - } else { - if (outBuffer.available() < len) { // not enough room in current buffer, send it. - outLen = MA_BUFFER_SIZE - outBuffer.available (); - outBuffer.reset (); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); // drops lock - QPID_LOG(debug, "SEND GetResponse (v1) to=" << replyToKey << " seq=" << sequence); - continue; // lock dropped, need to re-find _SAME_ objid as it may have been deleted. - } - encodeHeader(outBuffer, 'g', sequence); - outBuffer.putRawData(sProps); - outBuffer.putRawData(sStats); - } - } - } - matches.pop_front(); - } - - outLen = MA_BUFFER_SIZE - outBuffer.available (); - if (outLen) { - outBuffer.reset (); - sendBufferLH(outBuffer, outLen, dExchange, replyToKey); - QPID_LOG(debug, "SEND GetResponse (v1) to=" << replyToKey << " seq=" << sequence); - } - - sendCommandCompleteLH(replyToKey, sequence); -} - - -void ManagementAgent::handleGetQueryLH(const string& body, const string& rte, const string& rtk, const string& cid, bool viaLocal) -{ - moveNewObjectsLH(); - - Variant::Map inMap; - Variant::Map::const_iterator i; - Variant::Map headers; - - MapCodec::decode(body, inMap); - QPID_LOG(debug, "RECV GetQuery (v2): map=" << inMap << " seq=" << cid); - - headers["method"] = "response"; - headers["qmf.opcode"] = "_query_response"; - headers["qmf.content"] = "_data"; - headers["qmf.agent"] = viaLocal ? "broker" : name_address; - - /* - * Unpack the _what element of the query. Currently we only support OBJECT queries. - */ - i = inMap.find("_what"); - if (i == inMap.end()) { - sendExceptionLH(rte, rtk, cid, "_what element missing in Query"); - return; - } - - if (i->second.getType() != qpid::types::VAR_STRING) { - sendExceptionLH(rte, rtk, cid, "_what element is not a string"); - return; - } - - if (i->second.asString() != "OBJECT") { - sendExceptionLH(rte, rtk, cid, "Query for _what => '" + i->second.asString() + "' not supported"); - return; - } - - string className; - string packageName; - - /* - * Handle the _schema_id element, if supplied. - */ - i = inMap.find("_schema_id"); - if (i != inMap.end() && i->second.getType() == qpid::types::VAR_MAP) { - const Variant::Map& schemaIdMap(i->second.asMap()); - - Variant::Map::const_iterator s_iter = schemaIdMap.find("_class_name"); - if (s_iter != schemaIdMap.end() && s_iter->second.getType() == qpid::types::VAR_STRING) - className = s_iter->second.asString(); - - s_iter = schemaIdMap.find("_package_name"); - if (s_iter != schemaIdMap.end() && s_iter->second.getType() == qpid::types::VAR_STRING) - packageName = s_iter->second.asString(); - } - - - /* - * Unpack the _object_id element of the query if it is present. If it is present, find that one - * object and return it. If it is not present, send a class-based result. - */ - i = inMap.find("_object_id"); - if (i != inMap.end() && i->second.getType() == qpid::types::VAR_MAP) { - Variant::List list_; - ObjectId objId(i->second.asMap()); - - ManagementObjectMap::iterator iter = managementObjects.find(objId); - if (iter != managementObjects.end()) { - ManagementObject* object = iter->second; - - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - if (!object->isDeleted()) { - Variant::Map map_; - Variant::Map values; - Variant::Map oidMap; - - object->mapEncodeValues(values, true, true); // write both stats and properties - objId.mapEncode(oidMap); - map_["_values"] = values; - map_["_object_id"] = oidMap; - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - "_data", - object->getMd5Sum()); - list_.push_back(map_); - } - - string content; - - ListCodec::encode(list_, content); - sendBufferLH(content, cid, headers, "amqp/list", rte, rtk); - QPID_LOG(debug, "SENT QueryResponse (query by object_id) to=" << rte << "/" << rtk); - return; - } - } else { - // send class-based result. - Variant::List _list; - Variant::List _subList; - unsigned int objCount = 0; - - for (ManagementObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - iter++) { - ManagementObject* object = iter->second; - if (object->getClassName() == className && - (packageName.empty() || object->getPackageName() == packageName)) { - - - if (!object->isDeleted()) { - Variant::Map map_; - Variant::Map values; - Variant::Map oidMap; - - if (object->getConfigChanged() || object->getInstChanged()) - object->setUpdateTime(); - - object->writeTimestamps(map_); - object->mapEncodeValues(values, true, true); // write both stats and properties - iter->first.mapEncode(oidMap); - - map_["_values"] = values; - map_["_object_id"] = oidMap; - map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(), - object->getClassName(), - "_data", - object->getMd5Sum()); - _subList.push_back(map_); - if (++objCount >= maxReplyObjs) { - objCount = 0; - _list.push_back(_subList); - _subList.clear(); - } - } - } - } - - if (_subList.size()) - _list.push_back(_subList); - - headers["partial"] = Variant(); - string content; - while (_list.size() > 1) { - ListCodec::encode(_list.front().asList(), content); - sendBufferLH(content, cid, headers, "amqp/list", rte, rtk); - _list.pop_front(); - QPID_LOG(debug, "SENT QueryResponse (partial, query by schema_id) to=" << rte << "/" << rtk << " len=" << content.length()); - } - headers.erase("partial"); - ListCodec::encode(_list.size() ? _list.front().asList() : Variant::List(), content); - sendBufferLH(content, cid, headers, "amqp/list", rte, rtk); - QPID_LOG(debug, "SENT QueryResponse (query by schema_id) to=" << rte << "/" << rtk << " len=" << content.length()); - return; - } - - // Unrecognized query - Send empty message to indicate CommandComplete - string content; - ListCodec::encode(Variant::List(), content); - sendBufferLH(content, cid, headers, "amqp/list", rte, rtk); - QPID_LOG(debug, "SENT QueryResponse (empty) to=" << rte << "/" << rtk); -} - - -void ManagementAgent::handleLocateRequestLH(const string&, const string& rte, const string& rtk, const string& cid) -{ - QPID_LOG(debug, "RCVD AgentLocateRequest"); - - Variant::Map map; - Variant::Map headers; - - headers["method"] = "indication"; - headers["qmf.opcode"] = "_agent_locate_response"; - headers["qmf.agent"] = name_address; - - map["_values"] = attrMap; - map["_values"].asMap()["_timestamp"] = uint64_t(sys::Duration(sys::EPOCH, sys::now())); - map["_values"].asMap()["_heartbeat_interval"] = interval; - map["_values"].asMap()["_epoch"] = bootSequence; - - string content; - MapCodec::encode(map, content); - sendBufferLH(content, cid, headers, "amqp/map", rte, rtk); - clientWasAdded = true; - - QPID_LOG(debug, "SENT AgentLocateResponse replyTo=" << rte << "/" << rtk); -} - - -bool ManagementAgent::authorizeAgentMessageLH(Message& msg) -{ - Buffer inBuffer (inputBuffer, MA_BUFFER_SIZE); - uint32_t sequence = 0; - bool methodReq = false; - bool mapMsg = false; - string packageName; - string className; - string methodName; - string cid; - - // - // If the message is larger than our working buffer size, we can't determine if it's - // authorized or not. In this case, return true (authorized) if there is no ACL in place, - // otherwise return false; - // - if (msg.encodedSize() > MA_BUFFER_SIZE) - return broker->getAcl() == 0; - - msg.encodeContent(inBuffer); - uint32_t bufferLen = inBuffer.getPosition(); - inBuffer.reset(); - - const framing::MessageProperties* p = - msg.getFrames().getHeaders()->get<framing::MessageProperties>(); - - const framing::FieldTable *headers = msg.getApplicationHeaders(); - - if (headers && msg.getAppId() == "qmf2") - { - mapMsg = true; - - if (p && p->hasCorrelationId()) { - cid = p->getCorrelationId(); - } - - if (headers->getAsString("qmf.opcode") == "_method_request") - { - methodReq = true; - - // extract object id and method name - - string body; - inBuffer.getRawData(body, bufferLen); - Variant::Map inMap; - MapCodec::decode(body, inMap); - Variant::Map::const_iterator oid, mid; - - ObjectId objId; - - if ((oid = inMap.find("_object_id")) == inMap.end() || - (mid = inMap.find("_method_name")) == inMap.end()) { - QPID_LOG(warning, - "Missing fields in QMF authorize req received."); - return false; - } - - try { - // coversions will throw if input is invalid. - objId = ObjectId(oid->second.asMap()); - methodName = mid->second.getString(); - } catch(exception& /*e*/) { - QPID_LOG(warning, - "Badly formatted QMF authorize req received."); - return false; - } - - // look up schema for object to get package and class name - - ManagementObjectMap::iterator iter = managementObjects.find(objId); - - if (iter == managementObjects.end() || iter->second->isDeleted()) { - QPID_LOG(debug, "ManagementAgent::authorizeAgentMessageLH: stale object id " << - objId); - return false; - } - - packageName = iter->second->getPackageName(); - className = iter->second->getClassName(); - } - } else { // old style binary message format - - uint8_t opcode; - - if (!checkHeader(inBuffer, &opcode, &sequence)) - return false; - - if (opcode == 'M') { - methodReq = true; - - // extract method name & schema package and class name - - uint8_t hash[16]; - inBuffer.getLongLong(); // skip over object id - inBuffer.getLongLong(); - inBuffer.getShortString(packageName); - inBuffer.getShortString(className); - inBuffer.getBin128(hash); - inBuffer.getShortString(methodName); - - } - } - - if (methodReq) { - // TODO: check method call against ACL list. - map<acl::Property, string> params; - AclModule* acl = broker->getAcl(); - if (acl == 0) - return true; - - string userId = ((const qpid::broker::ConnectionState*) msg.getPublisher())->getUserId(); - params[acl::PROP_SCHEMAPACKAGE] = packageName; - params[acl::PROP_SCHEMACLASS] = className; - - if (acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_METHOD, methodName, ¶ms)) - return true; - - // authorization failed, send reply if replyTo present - - const framing::MessageProperties* p = - msg.getFrames().getHeaders()->get<framing::MessageProperties>(); - if (p && p->hasReplyTo()) { - const framing::ReplyTo& rt = p->getReplyTo(); - string rte = rt.getExchange(); - string rtk = rt.getRoutingKey(); - string cid; - if (p && p->hasCorrelationId()) - cid = p->getCorrelationId(); - - if (mapMsg) { - sendExceptionLH(rte, rtk, cid, Manageable::StatusText(Manageable::STATUS_FORBIDDEN), - Manageable::STATUS_FORBIDDEN, false); - } else { - - Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - encodeHeader(outBuffer, 'm', sequence); - outBuffer.putLong(Manageable::STATUS_FORBIDDEN); - outBuffer.putMediumString(Manageable::StatusText(Manageable::STATUS_FORBIDDEN)); - outLen = MA_BUFFER_SIZE - outBuffer.available(); - outBuffer.reset(); - sendBufferLH(outBuffer, outLen, rte, rtk); - } - - QPID_LOG(debug, "SEND MethodResponse status=FORBIDDEN" << " seq=" << sequence); - } - - return false; - } - - return true; -} - -void ManagementAgent::dispatchAgentCommandLH(Message& msg, bool viaLocal) -{ - string rte; - string rtk; - const framing::MessageProperties* p = - msg.getFrames().getHeaders()->get<framing::MessageProperties>(); - if (p && p->hasReplyTo()) { - const framing::ReplyTo& rt = p->getReplyTo(); - rte = rt.getExchange(); - rtk = rt.getRoutingKey(); - } - else - return; - - Buffer inBuffer(inputBuffer, MA_BUFFER_SIZE); - uint8_t opcode; - - if (msg.encodedSize() > MA_BUFFER_SIZE) { - QPID_LOG(debug, "ManagementAgent::dispatchAgentCommandLH: Message too large: " << - msg.encodedSize()); - return; - } - - msg.encodeContent(inBuffer); - uint32_t bufferLen = inBuffer.getPosition(); - inBuffer.reset(); - - ScopedManagementContext context((const qpid::broker::ConnectionState*) msg.getPublisher()); - const framing::FieldTable *headers = msg.getApplicationHeaders(); - if (headers && msg.getAppId() == "qmf2") - { - string opcode = headers->getAsString("qmf.opcode"); - string contentType = headers->getAsString("qmf.content"); - string body; - string cid; - inBuffer.getRawData(body, bufferLen); - - if (p && p->hasCorrelationId()) { - cid = p->getCorrelationId(); - } - - if (opcode == "_method_request") - return handleMethodRequestLH(body, rte, rtk, cid, msg.getPublisher(), viaLocal); - else if (opcode == "_query_request") - return handleGetQueryLH(body, rte, rtk, cid, viaLocal); - else if (opcode == "_agent_locate_request") - return handleLocateRequestLH(body, rte, rtk, cid); - - QPID_LOG(warning, "Support for QMF Opcode [" << opcode << "] TBD!!!"); - return; - } - - // old preV2 binary messages - - while (inBuffer.getPosition() < bufferLen) { - uint32_t sequence; - if (!checkHeader(inBuffer, &opcode, &sequence)) - return; - - if (opcode == 'B') handleBrokerRequestLH (inBuffer, rtk, sequence); - else if (opcode == 'P') handlePackageQueryLH (inBuffer, rtk, sequence); - else if (opcode == 'p') handlePackageIndLH (inBuffer, rtk, sequence); - else if (opcode == 'Q') handleClassQueryLH (inBuffer, rtk, sequence); - else if (opcode == 'q') handleClassIndLH (inBuffer, rtk, sequence); - else if (opcode == 'S') handleSchemaRequestLH (inBuffer, rte, rtk, sequence); - else if (opcode == 's') handleSchemaResponseLH (inBuffer, rtk, sequence); - else if (opcode == 'A') handleAttachRequestLH (inBuffer, rtk, sequence, msg.getPublisher()); - else if (opcode == 'G') handleGetQueryLH (inBuffer, rtk, sequence); - else if (opcode == 'M') handleMethodRequestLH (inBuffer, rtk, sequence, msg.getPublisher()); - } -} - -ManagementAgent::PackageMap::iterator ManagementAgent::findOrAddPackageLH(string name) -{ - PackageMap::iterator pIter = packages.find (name); - if (pIter != packages.end ()) - return pIter; - - // No such package found, create a new map entry. - pair<PackageMap::iterator, bool> result = - packages.insert(pair<string, ClassMap>(name, ClassMap())); - QPID_LOG (debug, "ManagementAgent added package " << name); - - // Publish a package-indication message - Buffer outBuffer (outputBuffer, MA_BUFFER_SIZE); - uint32_t outLen; - - encodeHeader (outBuffer, 'p'); - encodePackageIndication (outBuffer, result.first); - outLen = MA_BUFFER_SIZE - outBuffer.available (); - outBuffer.reset (); - sendBufferLH(outBuffer, outLen, mExchange, "schema.package"); - QPID_LOG(debug, "SEND PackageInd package=" << name << " to=schema.package"); - - return result.first; -} - -void ManagementAgent::addClassLH(uint8_t kind, - PackageMap::iterator pIter, - const string& className, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall) -{ - SchemaClassKey key; - ClassMap& cMap = pIter->second; - - key.name = className; - memcpy(&key.hash, md5Sum, 16); - - ClassMap::iterator cIter = cMap.find(key); - if (cIter != cMap.end()) - return; - - // No such class found, create a new class with local information. - QPID_LOG (debug, "ManagementAgent added class " << pIter->first << ":" << - key.name); - - cMap.insert(pair<SchemaClassKey, SchemaClass>(key, SchemaClass(kind, schemaCall))); - cIter = cMap.find(key); -} - -void ManagementAgent::encodePackageIndication(Buffer& buf, - PackageMap::iterator pIter) -{ - buf.putShortString((*pIter).first); -} - -void ManagementAgent::encodeClassIndication(Buffer& buf, - const std::string packageName, - const SchemaClassKey key, - uint8_t kind) -{ - buf.putOctet(kind); - buf.putShortString(packageName); - key.encode(buf); -} - -size_t ManagementAgent::validateSchema(Buffer& inBuffer, uint8_t kind) -{ - if (kind == ManagementItem::CLASS_KIND_TABLE) - return validateTableSchema(inBuffer); - else if (kind == ManagementItem::CLASS_KIND_EVENT) - return validateEventSchema(inBuffer); - return 0; -} - -size_t ManagementAgent::validateTableSchema(Buffer& inBuffer) -{ - uint32_t start = inBuffer.getPosition(); - uint32_t end; - string text; - uint8_t hash[16]; - - try { - inBuffer.record(); - uint8_t kind = inBuffer.getOctet(); - if (kind != ManagementItem::CLASS_KIND_TABLE) - return 0; - - inBuffer.getShortString(text); - inBuffer.getShortString(text); - inBuffer.getBin128(hash); - - uint8_t superType = 0; //inBuffer.getOctet(); - - uint16_t propCount = inBuffer.getShort(); - uint16_t statCount = inBuffer.getShort(); - uint16_t methCount = inBuffer.getShort(); - - if (superType == 1) { - inBuffer.getShortString(text); - inBuffer.getShortString(text); - inBuffer.getBin128(hash); - } - - for (uint16_t idx = 0; idx < propCount + statCount; idx++) { - FieldTable ft; - ft.decode(inBuffer); - } - - for (uint16_t idx = 0; idx < methCount; idx++) { - FieldTable ft; - ft.decode(inBuffer); - if (!ft.isSet("argCount")) - return 0; - int argCount = ft.getAsInt("argCount"); - for (int mIdx = 0; mIdx < argCount; mIdx++) { - FieldTable aft; - aft.decode(inBuffer); - } - } - } catch (exception& /*e*/) { - return 0; - } - - end = inBuffer.getPosition(); - inBuffer.restore(); // restore original position - return end - start; -} - -size_t ManagementAgent::validateEventSchema(Buffer& inBuffer) -{ - uint32_t start = inBuffer.getPosition(); - uint32_t end; - string text; - uint8_t hash[16]; - - try { - inBuffer.record(); - uint8_t kind = inBuffer.getOctet(); - if (kind != ManagementItem::CLASS_KIND_EVENT) - return 0; - - inBuffer.getShortString(text); - inBuffer.getShortString(text); - inBuffer.getBin128(hash); - - uint8_t superType = 0; //inBuffer.getOctet(); - - uint16_t argCount = inBuffer.getShort(); - - if (superType == 1) { - inBuffer.getShortString(text); - inBuffer.getShortString(text); - inBuffer.getBin128(hash); - } - for (uint16_t idx = 0; idx < argCount; idx++) { - FieldTable ft; - ft.decode(inBuffer); - } - } catch (exception& /*e*/) { - return 0; - } - - end = inBuffer.getPosition(); - inBuffer.restore(); // restore original position - return end - start; -} - -ManagementObjectMap::iterator ManagementAgent::numericFind(const ObjectId& oid) -{ - ManagementObjectMap::iterator iter = managementObjects.begin(); - for (; iter != managementObjects.end(); iter++) { - if (oid.equalV1(iter->first)) - break; - } - - return iter; -} - -void ManagementAgent::disallow(const string& className, const string& methodName, const string& message) { - disallowed[make_pair(className, methodName)] = message; -} - -void ManagementAgent::SchemaClassKey::mapEncode(Variant::Map& _map) const { - _map["_cname"] = name; - _map["_hash"] = qpid::types::Uuid(hash); -} - -void ManagementAgent::SchemaClassKey::mapDecode(const Variant::Map& _map) { - Variant::Map::const_iterator i; - - if ((i = _map.find("_cname")) != _map.end()) { - name = i->second.asString(); - } - - if ((i = _map.find("_hash")) != _map.end()) { - const qpid::types::Uuid& uuid = i->second.asUuid(); - memcpy(hash, uuid.data(), uuid.size()); - } -} - -void ManagementAgent::SchemaClassKey::encode(qpid::framing::Buffer& buffer) const { - buffer.checkAvailable(encodedBufSize()); - buffer.putShortString(name); - buffer.putBin128(hash); -} - -void ManagementAgent::SchemaClassKey::decode(qpid::framing::Buffer& buffer) { - buffer.checkAvailable(encodedBufSize()); - buffer.getShortString(name); - buffer.getBin128(hash); -} - -uint32_t ManagementAgent::SchemaClassKey::encodedBufSize() const { - return 1 + name.size() + 16 /* bin128 */; -} - -void ManagementAgent::SchemaClass::mapEncode(Variant::Map& _map) const { - _map["_type"] = kind; - _map["_pending_sequence"] = pendingSequence; - _map["_data"] = data; -} - -void ManagementAgent::SchemaClass::mapDecode(const Variant::Map& _map) { - Variant::Map::const_iterator i; - - if ((i = _map.find("_type")) != _map.end()) { - kind = i->second; - } - if ((i = _map.find("_pending_sequence")) != _map.end()) { - pendingSequence = i->second; - } - if ((i = _map.find("_data")) != _map.end()) { - data = i->second.asString(); - } -} - -void ManagementAgent::exportSchemas(string& out) { - Variant::List list_; - Variant::Map map_, kmap, cmap; - - for (PackageMap::const_iterator i = packages.begin(); i != packages.end(); ++i) { - string name = i->first; - const ClassMap& classes = i ->second; - for (ClassMap::const_iterator j = classes.begin(); j != classes.end(); ++j) { - const SchemaClassKey& key = j->first; - const SchemaClass& klass = j->second; - if (klass.writeSchemaCall == 0) { // Ignore built-in schemas. - // Encode name, schema-key, schema-class - - map_.clear(); - kmap.clear(); - cmap.clear(); - - key.mapEncode(kmap); - klass.mapEncode(cmap); - - map_["_pname"] = name; - map_["_key"] = kmap; - map_["_class"] = cmap; - list_.push_back(map_); - } - } - } - - ListCodec::encode(list_, out); -} - -void ManagementAgent::importSchemas(qpid::framing::Buffer& inBuf) { - - string buf(inBuf.getPointer(), inBuf.available()); - Variant::List content; - ListCodec::decode(buf, content); - Variant::List::const_iterator l; - - - for (l = content.begin(); l != content.end(); l++) { - string package; - SchemaClassKey key; - SchemaClass klass; - Variant::Map map_, kmap, cmap; - Variant::Map::const_iterator i; - - map_ = l->asMap(); - - if ((i = map_.find("_pname")) != map_.end()) { - package = i->second.asString(); - - if ((i = map_.find("_key")) != map_.end()) { - key.mapDecode(i->second.asMap()); - - if ((i = map_.find("_class")) != map_.end()) { - klass.mapDecode(i->second.asMap()); - - packages[package][key] = klass; - } - } - } - } -} - -void ManagementAgent::RemoteAgent::mapEncode(Variant::Map& map_) const { - Variant::Map _objId, _values; - - map_["_brokerBank"] = brokerBank; - map_["_agentBank"] = agentBank; - map_["_routingKey"] = routingKey; - - connectionRef.mapEncode(_objId); - map_["_object_id"] = _objId; - - mgmtObject->mapEncodeValues(_values, true, false); - map_["_values"] = _values; -} - -void ManagementAgent::RemoteAgent::mapDecode(const Variant::Map& map_) { - Variant::Map::const_iterator i; - - if ((i = map_.find("_brokerBank")) != map_.end()) { - brokerBank = i->second; - } - - if ((i = map_.find("_agentBank")) != map_.end()) { - agentBank = i->second; - } - - if ((i = map_.find("_routingKey")) != map_.end()) { - routingKey = i->second.getString(); - } - - if ((i = map_.find("_object_id")) != map_.end()) { - connectionRef.mapDecode(i->second.asMap()); - } - - mgmtObject = new _qmf::Agent(&agent, this); - - if ((i = map_.find("_values")) != map_.end()) { - mgmtObject->mapDecodeValues(i->second.asMap()); - } - - // TODO aconway 2010-03-04: see comment in encode(), readProperties doesn't set v2key. - mgmtObject->set_connectionRef(connectionRef); -} - -void ManagementAgent::exportAgents(string& out) { - Variant::List list_; - Variant::Map map_, omap, amap; - - for (RemoteAgentMap::const_iterator i = remoteAgents.begin(); - i != remoteAgents.end(); - ++i) - { - // TODO aconway 2010-03-04: see comment in ManagementAgent::RemoteAgent::encode - boost::shared_ptr<RemoteAgent> agent(i->second); - - map_.clear(); - amap.clear(); - - agent->mapEncode(amap); - map_["_remote_agent"] = amap; - list_.push_back(map_); - } - - ListCodec::encode(list_, out); -} - -void ManagementAgent::importAgents(qpid::framing::Buffer& inBuf) { - string buf(inBuf.getPointer(), inBuf.available()); - Variant::List content; - ListCodec::decode(buf, content); - Variant::List::const_iterator l; - sys::Mutex::ScopedLock lock(userLock); - - for (l = content.begin(); l != content.end(); l++) { - boost::shared_ptr<RemoteAgent> agent(new RemoteAgent(*this)); - Variant::Map map_; - Variant::Map::const_iterator i; - - map_ = l->asMap(); - - if ((i = map_.find("_remote_agent")) != map_.end()) { - - agent->mapDecode(i->second.asMap()); - - addObject (agent->mgmtObject, 0, false); - remoteAgents[agent->connectionRef] = agent; - } - } -} - -namespace { -bool isDeletedMap(const ManagementObjectMap::value_type& value) { - return value.second->isDeleted(); -} - -bool isDeletedVector(const ManagementObjectVector::value_type& value) { - return value->isDeleted(); -} - -string summarizeMap(const char* name, const ManagementObjectMap& map) { - ostringstream o; - size_t deleted = std::count_if(map.begin(), map.end(), isDeletedMap); - o << map.size() << " " << name << " (" << deleted << " deleted), "; - return o.str(); -} - -string summarizeVector(const char* name, const ManagementObjectVector& map) { - ostringstream o; - size_t deleted = std::count_if(map.begin(), map.end(), isDeletedVector); - o << map.size() << " " << name << " (" << deleted << " deleted), "; - return o.str(); -} - -string dumpMap(const ManagementObjectMap& map) { - ostringstream o; - for (ManagementObjectMap::const_iterator i = map.begin(); i != map.end(); ++i) { - o << endl << " " << i->second->getObjectId().getV2Key() - << (i->second->isDeleted() ? " (deleted)" : ""); - } - return o.str(); -} - -string dumpVector(const ManagementObjectVector& map) { - ostringstream o; - for (ManagementObjectVector::const_iterator i = map.begin(); i != map.end(); ++i) { - o << endl << " " << (*i)->getObjectId().getV2Key() - << ((*i)->isDeleted() ? " (deleted)" : ""); - } - return o.str(); -} - -} // namespace - -string ManagementAgent::summarizeAgents() { - ostringstream msg; - if (!remoteAgents.empty()) { - msg << remoteAgents.size() << " agents("; - for (RemoteAgentMap::const_iterator i=remoteAgents.begin(); - i != remoteAgents.end(); ++i) - msg << " " << i->second->routingKey; - msg << "), "; - } - return msg.str(); -} - - -void ManagementAgent::debugSnapshot(const char* title) { - QPID_LOG(debug, title << ": management snapshot: " - << packages.size() << " packages, " - << summarizeMap("objects", managementObjects) - << summarizeVector("new objects ", newManagementObjects) - << pendingDeletedObjs.size() << " pending deletes" - << summarizeAgents()); - - QPID_LOG_IF(trace, managementObjects.size(), - title << ": objects" << dumpMap(managementObjects)); - QPID_LOG_IF(trace, newManagementObjects.size(), - title << ": new objects" << dumpVector(newManagementObjects)); -} - -Variant::Map ManagementAgent::toMap(const FieldTable& from) -{ - Variant::Map map; - - for (FieldTable::const_iterator iter = from.begin(); iter != from.end(); iter++) { - const string& key(iter->first); - const FieldTable::ValuePtr& val(iter->second); - - map[key] = toVariant(val); - } - - return map; -} - -Variant::List ManagementAgent::toList(const List& from) -{ - Variant::List _list; - - for (List::const_iterator iter = from.begin(); iter != from.end(); iter++) { - const List::ValuePtr& val(*iter); - - _list.push_back(toVariant(val)); - } - - return _list; -} - -qpid::framing::FieldTable ManagementAgent::fromMap(const Variant::Map& from) -{ - qpid::framing::FieldTable ft; - - for (Variant::Map::const_iterator iter = from.begin(); - iter != from.end(); - iter++) { - const string& key(iter->first); - const Variant& val(iter->second); - - ft.set(key, toFieldValue(val)); - } - - return ft; -} - - -List ManagementAgent::fromList(const Variant::List& from) -{ - List fa; - - for (Variant::List::const_iterator iter = from.begin(); - iter != from.end(); - iter++) { - const Variant& val(*iter); - - fa.push_back(toFieldValue(val)); - } - - return fa; -} - - -boost::shared_ptr<FieldValue> ManagementAgent::toFieldValue(const Variant& in) -{ - - switch(in.getType()) { - - case types::VAR_VOID: return boost::shared_ptr<FieldValue>(new VoidValue()); - case types::VAR_BOOL: return boost::shared_ptr<FieldValue>(new BoolValue(in.asBool())); - case types::VAR_UINT8: return boost::shared_ptr<FieldValue>(new Unsigned8Value(in.asUint8())); - case types::VAR_UINT16: return boost::shared_ptr<FieldValue>(new Unsigned16Value(in.asUint16())); - case types::VAR_UINT32: return boost::shared_ptr<FieldValue>(new Unsigned32Value(in.asUint32())); - case types::VAR_UINT64: return boost::shared_ptr<FieldValue>(new Unsigned64Value(in.asUint64())); - case types::VAR_INT8: return boost::shared_ptr<FieldValue>(new Integer8Value(in.asInt8())); - case types::VAR_INT16: return boost::shared_ptr<FieldValue>(new Integer16Value(in.asInt16())); - case types::VAR_INT32: return boost::shared_ptr<FieldValue>(new Integer32Value(in.asInt32())); - case types::VAR_INT64: return boost::shared_ptr<FieldValue>(new Integer64Value(in.asInt64())); - case types::VAR_FLOAT: return boost::shared_ptr<FieldValue>(new FloatValue(in.asFloat())); - case types::VAR_DOUBLE: return boost::shared_ptr<FieldValue>(new DoubleValue(in.asDouble())); - case types::VAR_STRING: return boost::shared_ptr<FieldValue>(new Str16Value(in.asString())); - case types::VAR_UUID: return boost::shared_ptr<FieldValue>(new UuidValue(in.asUuid().data())); - case types::VAR_MAP: return boost::shared_ptr<FieldValue>(new FieldTableValue(ManagementAgent::fromMap(in.asMap()))); - case types::VAR_LIST: return boost::shared_ptr<FieldValue>(new ListValue(ManagementAgent::fromList(in.asList()))); - } - - QPID_LOG(error, "Unknown Variant type - not converted: [" << in.getType() << "]"); - return boost::shared_ptr<FieldValue>(new VoidValue()); -} - -// stolen from qpid/client/amqp0_10/Codecs.cpp - TODO: make Codecs public, and remove this dup. -Variant ManagementAgent::toVariant(const boost::shared_ptr<FieldValue>& in) -{ - const string iso885915("iso-8859-15"); - const string utf8("utf8"); - const string utf16("utf16"); - //const string binary("binary"); - const string amqp0_10_binary("amqp0-10:binary"); - //const string amqp0_10_bit("amqp0-10:bit"); - const string amqp0_10_datetime("amqp0-10:datetime"); - const string amqp0_10_struct("amqp0-10:struct"); - Variant out; - - //based on AMQP 0-10 typecode, pick most appropriate variant type - switch (in->getType()) { - //Fixed Width types: - case 0x00: //bin8 - case 0x01: out.setEncoding(amqp0_10_binary); // int8 - case 0x02: out = in->getIntegerValue<int8_t>(); break; //uint8 - case 0x03: out = in->getIntegerValue<uint8_t>(); break; // - // case 0x04: break; //TODO: iso-8859-15 char // char - case 0x08: out = static_cast<bool>(in->getIntegerValue<uint8_t>()); break; // bool int8 - - case 0x10: out.setEncoding(amqp0_10_binary); // bin16 - case 0x11: out = in->getIntegerValue<int16_t, 2>(); break; // int16 - case 0x12: out = in->getIntegerValue<uint16_t, 2>(); break; //uint16 - - case 0x20: out.setEncoding(amqp0_10_binary); // bin32 - case 0x21: out = in->getIntegerValue<int32_t, 4>(); break; // int32 - case 0x22: out = in->getIntegerValue<uint32_t, 4>(); break; // uint32 - - case 0x23: out = in->get<float>(); break; // float(32) - - // case 0x27: break; //TODO: utf-32 char - - case 0x30: out.setEncoding(amqp0_10_binary); // bin64 - case 0x31: out = in->getIntegerValue<int64_t, 8>(); break; //int64 - - case 0x38: out.setEncoding(amqp0_10_datetime); //treat datetime as uint64_t, but set encoding - case 0x32: out = in->getIntegerValue<uint64_t, 8>(); break; //uint64 - case 0x33: out = in->get<double>(); break; // double - - case 0x48: // uuid - { - unsigned char data[16]; - in->getFixedWidthValue<16>(data); - out = qpid::types::Uuid(data); - } break; - - //TODO: figure out whether and how to map values with codes 0x40-0xd8 - - case 0xf0: break;//void, which is the default value for Variant - // case 0xf1: out.setEncoding(amqp0_10_bit); break;//treat 'bit' as void, which is the default value for Variant - - //Variable Width types: - //strings: - case 0x80: // str8 - case 0x90: // str16 - case 0xa0: // str32 - out = in->get<string>(); - out.setEncoding(amqp0_10_binary); - break; - - case 0x84: // str8 - case 0x94: // str16 - out = in->get<string>(); - out.setEncoding(iso885915); - break; - - case 0x85: // str8 - case 0x95: // str16 - out = in->get<string>(); - out.setEncoding(utf8); - break; - - case 0x86: // str8 - case 0x96: // str16 - out = in->get<string>(); - out.setEncoding(utf16); - break; - - case 0xab: // str32 - out = in->get<string>(); - out.setEncoding(amqp0_10_struct); - break; - - case 0xa8: // map - out = ManagementAgent::toMap(in->get<FieldTable>()); - break; - - case 0xa9: // list of variant types - out = ManagementAgent::toList(in->get<List>()); - break; - //case 0xaa: //convert amqp0-10 array (uniform type) into variant list - // out = Variant::List(); - // translate<Array>(in, out.asList(), &toVariant); - // break; - - default: - //error? - QPID_LOG(error, "Unknown FieldValue type - not converted: [" << (unsigned int)(in->getType()) << "]"); - break; - } - - return out; -} - - -// Build up a list of the current set of deleted objects that are pending their -// next (last) publish-ment. -void ManagementAgent::exportDeletedObjects(DeletedObjectList& outList) -{ - outList.clear(); - - sys::Mutex::ScopedLock lock (userLock); - - moveNewObjectsLH(); - moveDeletedObjectsLH(); - - // now copy the pending deletes into the outList - for (PendingDeletedObjsMap::iterator mIter = pendingDeletedObjs.begin(); - mIter != pendingDeletedObjs.end(); mIter++) { - for (DeletedObjectList::iterator lIter = mIter->second.begin(); - lIter != mIter->second.end(); lIter++) { - outList.push_back(*lIter); - } - } -} - -// Called by cluster to reset the management agent's list of deleted -// objects to match the rest of the cluster. -void ManagementAgent::importDeletedObjects(const DeletedObjectList& inList) -{ - sys::Mutex::ScopedLock lock (userLock); - // Clear out any existing deleted objects - moveNewObjectsLH(); - pendingDeletedObjs.clear(); - ManagementObjectMap::iterator i = managementObjects.begin(); - // Silently drop any deleted objects left over from receiving the update. - while (i != managementObjects.end()) { - ManagementObject* object = i->second; - if (object->isDeleted()) { - delete object; - managementObjects.erase(i++); - } - else ++i; - } - for (DeletedObjectList::const_iterator lIter = inList.begin(); lIter != inList.end(); lIter++) { - - std::string classkey((*lIter)->packageName + std::string(":") + (*lIter)->className); - pendingDeletedObjs[classkey].push_back(*lIter); - } -} - - -// construct a DeletedObject from a management object. -ManagementAgent::DeletedObject::DeletedObject(ManagementObject *src, bool v1, bool v2) - : packageName(src->getPackageName()), - className(src->getClassName()) -{ - bool send_stats = (src->hasInst() && (src->getInstChanged() || src->getForcePublish())); - - stringstream oid; - oid << src->getObjectId(); - objectId = oid.str(); - - if (v1) { - src->writeProperties(encodedV1Config); - if (send_stats) { - src->writeStatistics(encodedV1Inst); - } - } - - if (v2) { - Variant::Map map_; - Variant::Map values; - Variant::Map oid; - - src->getObjectId().mapEncode(oid); - map_["_object_id"] = oid; - map_["_schema_id"] = mapEncodeSchemaId(src->getPackageName(), - src->getClassName(), - "_data", - src->getMd5Sum()); - src->writeTimestamps(map_); - src->mapEncodeValues(values, true, send_stats); - map_["_values"] = values; - - encodedV2 = map_; - } -} - - - -// construct a DeletedObject from an encoded representation. Used by -// clustering to move deleted objects between clustered brokers. See -// DeletedObject::encode() for the reverse. -ManagementAgent::DeletedObject::DeletedObject(const std::string& encoded) -{ - qpid::types::Variant::Map map_; - MapCodec::decode(encoded, map_); - - packageName = map_["_package_name"].getString(); - className = map_["_class_name"].getString(); - objectId = map_["_object_id"].getString(); - - encodedV1Config = map_["_v1_config"].getString(); - encodedV1Inst = map_["_v1_inst"].getString(); - encodedV2 = map_["_v2_data"].asMap(); -} - - -// encode a DeletedObject to a string buffer. Used by -// clustering to move deleted objects between clustered brokers. See -// DeletedObject(const std::string&) for the reverse. -void ManagementAgent::DeletedObject::encode(std::string& toBuffer) -{ - qpid::types::Variant::Map map_; - - - map_["_package_name"] = packageName; - map_["_class_name"] = className; - map_["_object_id"] = objectId; - - map_["_v1_config"] = encodedV1Config; - map_["_v1_inst"] = encodedV1Inst; - map_["_v2_data"] = encodedV2; - - MapCodec::encode(map_, toBuffer); -} - -// Remove Deleted objects, and save for later publishing... -bool ManagementAgent::moveDeletedObjectsLH() { - typedef vector<pair<ObjectId, ManagementObject*> > DeleteList; - DeleteList deleteList; - for (ManagementObjectMap::iterator iter = managementObjects.begin(); - iter != managementObjects.end(); - ++iter) - { - ManagementObject* object = iter->second; - if (object->isDeleted()) deleteList.push_back(*iter); - } - - // Iterate in reverse over deleted object list - for (DeleteList::reverse_iterator iter = deleteList.rbegin(); - iter != deleteList.rend(); - iter++) - { - ManagementObject* delObj = iter->second; - assert(delObj->isDeleted()); - DeletedObject::shared_ptr dptr(new DeletedObject(delObj, qmf1Support, qmf2Support)); - - pendingDeletedObjs[dptr->getKey()].push_back(dptr); - managementObjects.erase(iter->first); - delete iter->second; - } - return !deleteList.empty(); -} - -namespace qpid { -namespace management { - -namespace { -QPID_TSS const qpid::broker::ConnectionState* executionContext = 0; -} - -void setManagementExecutionContext(const qpid::broker::ConnectionState* ctxt) -{ - executionContext = ctxt; -} -const qpid::broker::ConnectionState* getManagementExecutionContext() -{ - return executionContext; -} - -}} diff --git a/cpp/src/qpid/management/ManagementAgent.h b/cpp/src/qpid/management/ManagementAgent.h deleted file mode 100644 index fb15dc6ed1..0000000000 --- a/cpp/src/qpid/management/ManagementAgent.h +++ /dev/null @@ -1,432 +0,0 @@ -#ifndef _ManagementAgent_ -#define _ManagementAgent_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/Options.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Timer.h" -#include "qpid/broker/ConnectionToken.h" -#include "qpid/management/ManagementObject.h" -#include "qpid/management/ManagementEvent.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Agent.h" -#include "qpid/types/Variant.h" -#include <qpid/framing/AMQFrame.h> -#include <qpid/framing/FieldValue.h> -#include <qpid/framing/ResizableBuffer.h> -#include <memory> -#include <string> -#include <map> - -namespace qpid { -namespace broker { -class ConnectionState; -} -namespace management { - -class ManagementAgent -{ -private: - - int threadPoolSize; - -public: - typedef enum { - SEV_EMERG = 0, - SEV_ALERT = 1, - SEV_CRIT = 2, - SEV_ERROR = 3, - SEV_WARN = 4, - SEV_NOTE = 5, - SEV_INFO = 6, - SEV_DEBUG = 7, - SEV_DEFAULT = 8 - } severity_t; - - - ManagementAgent (const bool qmfV1, const bool qmfV2); - virtual ~ManagementAgent (); - - /** Called before plugins are initialized */ - void configure (const std::string& dataDir, uint16_t interval, - qpid::broker::Broker* broker, int threadPoolSize); - /** Called after plugins are initialized. */ - void pluginsInitialized(); - - /** Called by cluster to suppress management output during update. */ - void suppress(bool s) { suppressed = s; } - - void setName(const std::string& vendor, - const std::string& product, - const std::string& instance=""); - void getName(std::string& vendor, std::string& product, std::string& instance); - const std::string& getAddress(); - - void setInterval(uint16_t _interval) { interval = _interval; } - void setExchange(qpid::broker::Exchange::shared_ptr mgmtExchange, - qpid::broker::Exchange::shared_ptr directExchange); - void setExchangeV2(qpid::broker::Exchange::shared_ptr topicExchange, - qpid::broker::Exchange::shared_ptr directExchange); - - int getMaxThreads () { return threadPoolSize; } - QPID_BROKER_EXTERN void registerClass (const std::string& packageName, - const std::string& className, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall); - QPID_BROKER_EXTERN void registerEvent (const std::string& packageName, - const std::string& eventName, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall); - QPID_BROKER_EXTERN ObjectId addObject (ManagementObject* object, - uint64_t persistId = 0, - bool persistent = false); - QPID_BROKER_EXTERN ObjectId addObject (ManagementObject* object, - const std::string& key, - bool persistent = false); - QPID_BROKER_EXTERN void raiseEvent(const ManagementEvent& event, - severity_t severity = SEV_DEFAULT); - QPID_BROKER_EXTERN void clientAdded (const std::string& routingKey); - - QPID_BROKER_EXTERN void clusterUpdate(); - - bool dispatchCommand (qpid::broker::Deliverable& msg, - const std::string& routingKey, - const framing::FieldTable* args, - const bool topic, - int qmfVersion); - - /** Disallow a method. Attempts to call it will receive an exception with message. */ - void disallow(const std::string& className, const std::string& methodName, const std::string& message); - - /** Disallow all QMFv1 methods (used in clustered brokers). */ - void disallowV1Methods() { disallowAllV1Methods = true; } - - /** Serialize my schemas as a binary blob into schemaOut */ - void exportSchemas(std::string& schemaOut); - - /** Serialize my remote-agent map as a binary blob into agentsOut */ - void exportAgents(std::string& agentsOut); - - /** Decode a serialized schemas and add to my schema cache */ - void importSchemas(framing::Buffer& inBuf); - - /** Decode a serialized agent map */ - void importAgents(framing::Buffer& inBuf); - - // these are in support of the managementSetup-state stuff, for synch'ing clustered brokers - uint64_t getNextObjectId(void) { return nextObjectId; } - void setNextObjectId(uint64_t o) { nextObjectId = o; } - - uint16_t getBootSequence(void) { return bootSequence; } - void setBootSequence(uint16_t b) { bootSequence = b; writeData(); } - - const framing::Uuid& getUuid() const { return uuid; } - void setUuid(const framing::Uuid& id) { uuid = id; writeData(); } - - // TODO: remove these when Variant API moved into common library. - static types::Variant::Map toMap(const framing::FieldTable& from); - static framing::FieldTable fromMap(const types::Variant::Map& from); - static types::Variant::List toList(const framing::List& from); - static framing::List fromList(const types::Variant::List& from); - static boost::shared_ptr<framing::FieldValue> toFieldValue(const types::Variant& in); - static types::Variant toVariant(const boost::shared_ptr<framing::FieldValue>& val); - - // For Clustering: management objects that have been marked as - // "deleted", but are waiting for their last published object - // update are not visible to the cluster replication code. These - // interfaces allow clustering to gather up all the management - // objects that are deleted in order to allow all clustered - // brokers to publish the same set of deleted objects. - - class DeletedObject { - public: - typedef boost::shared_ptr<DeletedObject> shared_ptr; - DeletedObject(ManagementObject *, bool v1, bool v2); - DeletedObject( const std::string &encoded ); - ~DeletedObject() {}; - void encode( std::string& toBuffer ); - const std::string getKey() const { - // used to batch up objects of the same class type - return std::string(packageName + std::string(":") + className); - } - - private: - friend class ManagementAgent; - - std::string packageName; - std::string className; - std::string objectId; - - std::string encodedV1Config; // qmfv1 properties - std::string encodedV1Inst; // qmfv1 statistics - qpid::types::Variant::Map encodedV2; - }; - - typedef std::vector<DeletedObject::shared_ptr> DeletedObjectList; - - /** returns a snapshot of all currently deleted management objects. */ - void exportDeletedObjects( DeletedObjectList& outList ); - - /** Import a list of deleted objects to send on next publish interval. */ - void importDeletedObjects( const DeletedObjectList& inList ); - -private: - struct Periodic : public qpid::sys::TimerTask - { - ManagementAgent& agent; - - Periodic (ManagementAgent& agent, uint32_t seconds); - virtual ~Periodic (); - void fire (); - }; - - // Storage for tracking remote management agents, attached via the client - // management agent API. - // - struct RemoteAgent : public Manageable - { - ManagementAgent& agent; - uint32_t brokerBank; - uint32_t agentBank; - std::string routingKey; - ObjectId connectionRef; - qmf::org::apache::qpid::broker::Agent* mgmtObject; - RemoteAgent(ManagementAgent& _agent) : agent(_agent), mgmtObject(0) {} - ManagementObject* GetManagementObject (void) const { return mgmtObject; } - - virtual ~RemoteAgent (); - void mapEncode(qpid::types::Variant::Map& _map) const; - void mapDecode(const qpid::types::Variant::Map& _map); - }; - - typedef std::map<ObjectId, boost::shared_ptr<RemoteAgent> > RemoteAgentMap; - - // Storage for known schema classes: - // - // SchemaClassKey -- Key elements for map lookups - // SchemaClassKeyComp -- Comparison class for SchemaClassKey - // SchemaClass -- Non-key elements for classes - // - struct SchemaClassKey - { - std::string name; - uint8_t hash[16]; - - void mapEncode(qpid::types::Variant::Map& _map) const; - void mapDecode(const qpid::types::Variant::Map& _map); - void encode(framing::Buffer& buffer) const; - void decode(framing::Buffer& buffer); - uint32_t encodedBufSize() const; - }; - - struct SchemaClassKeyComp - { - bool operator() (const SchemaClassKey& lhs, const SchemaClassKey& rhs) const - { - if (lhs.name != rhs.name) - return lhs.name < rhs.name; - else - for (int i = 0; i < 16; i++) - if (lhs.hash[i] != rhs.hash[i]) - return lhs.hash[i] < rhs.hash[i]; - return false; - } - }; - - - struct SchemaClass - { - uint8_t kind; - ManagementObject::writeSchemaCall_t writeSchemaCall; - std::string data; - uint32_t pendingSequence; - - SchemaClass(uint8_t _kind=0, uint32_t seq=0) : - kind(_kind), writeSchemaCall(0), pendingSequence(seq) {} - SchemaClass(uint8_t _kind, ManagementObject::writeSchemaCall_t call) : - kind(_kind), writeSchemaCall(call), pendingSequence(0) {} - bool hasSchema () { return (writeSchemaCall != 0) || !data.empty(); } - void appendSchema (framing::Buffer& buf); - - void mapEncode(qpid::types::Variant::Map& _map) const; - void mapDecode(const qpid::types::Variant::Map& _map); - }; - - typedef std::map<SchemaClassKey, SchemaClass, SchemaClassKeyComp> ClassMap; - typedef std::map<std::string, ClassMap> PackageMap; - - RemoteAgentMap remoteAgents; - PackageMap packages; - - // - // Protected by userLock - // - ManagementObjectMap managementObjects; - - // - // Protected by addLock - // - ManagementObjectVector newManagementObjects; - - framing::Uuid uuid; - - // - // Lock hierarchy: If a thread needs to take both addLock and userLock, - // it MUST take userLock first, then addLock. - // - sys::Mutex userLock; - sys::Mutex addLock; - - qpid::broker::Exchange::shared_ptr mExchange; - qpid::broker::Exchange::shared_ptr dExchange; - qpid::broker::Exchange::shared_ptr v2Topic; - qpid::broker::Exchange::shared_ptr v2Direct; - std::string dataDir; - uint16_t interval; - qpid::broker::Broker* broker; - qpid::sys::Timer* timer; - uint16_t bootSequence; - uint32_t nextObjectId; - uint32_t brokerBank; - uint32_t nextRemoteBank; - uint32_t nextRequestSequence; - bool clientWasAdded; - const qpid::sys::AbsTime startTime; - bool suppressed; - - typedef std::pair<std::string,std::string> MethodName; - typedef std::map<MethodName, std::string> DisallowedMethods; - DisallowedMethods disallowed; - bool disallowAllV1Methods; - - // Agent name and address - qpid::types::Variant::Map attrMap; - std::string name_address; - std::string vendorNameKey; // "." --> "_" - std::string productNameKey; // "." --> "_" - std::string instanceNameKey; // "." --> "_" - - // supported management protocol - bool qmf1Support; - bool qmf2Support; - - // Maximum # of objects allowed in a single V2 response - // message. - uint32_t maxReplyObjs; - - // list of objects that have been deleted, but have yet to be published - // one final time. - // Indexed by a string composed of the object's package and class name. - // Protected by userLock. - typedef std::map<std::string, DeletedObjectList> PendingDeletedObjsMap; - PendingDeletedObjsMap pendingDeletedObjs; - -# define MA_BUFFER_SIZE 65536 - char inputBuffer[MA_BUFFER_SIZE]; - char outputBuffer[MA_BUFFER_SIZE]; - char eventBuffer[MA_BUFFER_SIZE]; - framing::ResizableBuffer msgBuffer; - - void writeData (); - void periodicProcessing (void); - void deleteObjectNowLH(const ObjectId& oid); - void encodeHeader (framing::Buffer& buf, uint8_t opcode, uint32_t seq = 0); - bool checkHeader (framing::Buffer& buf, uint8_t *opcode, uint32_t *seq); - void sendBufferLH(framing::Buffer& buf, - uint32_t length, - qpid::broker::Exchange::shared_ptr exchange, - const std::string& routingKey); - void sendBufferLH(framing::Buffer& buf, - uint32_t length, - const std::string& exchange, - const std::string& routingKey); - void sendBufferLH(const std::string& data, - const std::string& cid, - const qpid::types::Variant::Map& headers, - const std::string& content_type, - qpid::broker::Exchange::shared_ptr exchange, - const std::string& routingKey, - uint64_t ttl_msec = 0); - void sendBufferLH(const std::string& data, - const std::string& cid, - const qpid::types::Variant::Map& headers, - const std::string& content_type, - const std::string& exchange, - const std::string& routingKey, - uint64_t ttl_msec = 0); - void moveNewObjectsLH(); - bool moveDeletedObjectsLH(); - - bool authorizeAgentMessageLH(qpid::broker::Message& msg); - void dispatchAgentCommandLH(qpid::broker::Message& msg, bool viaLocal=false); - - PackageMap::iterator findOrAddPackageLH(std::string name); - void addClassLH(uint8_t kind, - PackageMap::iterator pIter, - const std::string& className, - uint8_t* md5Sum, - ManagementObject::writeSchemaCall_t schemaCall); - void encodePackageIndication (framing::Buffer& buf, - PackageMap::iterator pIter); - void encodeClassIndication (framing::Buffer& buf, - const std::string packageName, - const struct SchemaClassKey key, - uint8_t kind); - bool bankInUse (uint32_t bank); - uint32_t allocateNewBank (); - uint32_t assignBankLH (uint32_t requestedPrefix); - void deleteOrphanedAgentsLH(); - void sendCommandCompleteLH(const std::string& replyToKey, uint32_t sequence, - uint32_t code = 0, const std::string& text = "OK"); - void sendExceptionLH(const std::string& rte, const std::string& rtk, const std::string& cid, const std::string& text, uint32_t code=1, bool viaLocal=false); - void handleBrokerRequestLH (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handlePackageQueryLH (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handlePackageIndLH (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handleClassQueryLH (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handleClassIndLH (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handleSchemaRequestLH (framing::Buffer& inBuffer, const std::string& replyToEx, const std::string& replyToKey, uint32_t sequence); - void handleSchemaResponseLH (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handleAttachRequestLH (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence, const qpid::broker::ConnectionToken* connToken); - void handleGetQueryLH (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence); - void handleMethodRequestLH (framing::Buffer& inBuffer, const std::string& replyToKey, uint32_t sequence, const qpid::broker::ConnectionToken* connToken); - void handleGetQueryLH (const std::string& body, const std::string& replyToEx, const std::string& replyToKey, const std::string& cid, bool viaLocal); - void handleMethodRequestLH (const std::string& body, const std::string& replyToEx, const std::string& replyToKey, const std::string& cid, const qpid::broker::ConnectionToken* connToken, bool viaLocal); - void handleLocateRequestLH (const std::string& body, const std::string& replyToEx, const std::string &replyToKey, const std::string& cid); - - - size_t validateSchema(framing::Buffer&, uint8_t kind); - size_t validateTableSchema(framing::Buffer&); - size_t validateEventSchema(framing::Buffer&); - ManagementObjectMap::iterator numericFind(const ObjectId& oid); - - std::string summarizeAgents(); - void debugSnapshot(const char* title); -}; - -void setManagementExecutionContext(const qpid::broker::ConnectionState*); -const qpid::broker::ConnectionState* getManagementExecutionContext(); -}} - -#endif /*!_ManagementAgent_*/ diff --git a/cpp/src/qpid/management/ManagementDirectExchange.cpp b/cpp/src/qpid/management/ManagementDirectExchange.cpp deleted file mode 100644 index 1d5f8bbd6b..0000000000 --- a/cpp/src/qpid/management/ManagementDirectExchange.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/management/ManagementDirectExchange.h" -#include "qpid/log/Statement.h" -#include <assert.h> - -using namespace qpid::management; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -ManagementDirectExchange::ManagementDirectExchange(const string& _name, Manageable* _parent, Broker* b) : - Exchange (_name, _parent, b), - DirectExchange(_name, _parent, b), - managementAgent(0) {} -ManagementDirectExchange::ManagementDirectExchange(const std::string& _name, - bool _durable, - const FieldTable& _args, - Manageable* _parent, Broker* b) : - Exchange (_name, _durable, _args, _parent, b), - DirectExchange(_name, _durable, _args, _parent, b), - managementAgent(0) {} - -void ManagementDirectExchange::route(Deliverable& msg, - const string& routingKey, - const FieldTable* args) -{ - bool routeIt = true; - - if (managementAgent) - routeIt = managementAgent->dispatchCommand(msg, routingKey, args, false, qmfVersion); - - if (routeIt) - DirectExchange::route(msg, routingKey, args); -} - -void ManagementDirectExchange::setManagmentAgent(ManagementAgent* agent, int qv) -{ - managementAgent = agent; - qmfVersion = qv; - assert(qmfVersion == 2); // QMFv1 doesn't use a specialized direct exchange -} - - -ManagementDirectExchange::~ManagementDirectExchange() {} - -const std::string ManagementDirectExchange::typeName("management-direct"); - diff --git a/cpp/src/qpid/management/ManagementDirectExchange.h b/cpp/src/qpid/management/ManagementDirectExchange.h deleted file mode 100644 index 7507179c06..0000000000 --- a/cpp/src/qpid/management/ManagementDirectExchange.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ManagementDirectExchange_ -#define _ManagementDirectExchange_ - -#include "qpid/broker/DirectExchange.h" -#include "qpid/management/ManagementAgent.h" - -namespace qpid { -namespace broker { - -class ManagementDirectExchange : public virtual DirectExchange -{ - private: - management::ManagementAgent* managementAgent; - int qmfVersion; - - public: - static const std::string typeName; - - ManagementDirectExchange(const std::string& name, Manageable* _parent = 0, Broker* broker = 0); - ManagementDirectExchange(const std::string& _name, bool _durable, - const qpid::framing::FieldTable& _args, - Manageable* _parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - void setManagmentAgent(management::ManagementAgent* agent, int qmfVersion); - - virtual ~ManagementDirectExchange(); -}; - - -} -} - -#endif diff --git a/cpp/src/qpid/management/ManagementObject.cpp b/cpp/src/qpid/management/ManagementObject.cpp deleted file mode 100644 index b4d469afbe..0000000000 --- a/cpp/src/qpid/management/ManagementObject.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/management/Manageable.h" -#include "qpid/management/ManagementObject.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/Buffer.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" -#include "qpid/log/Statement.h" -#include <boost/lexical_cast.hpp> - -#include <stdlib.h> - -using namespace std; -using namespace qpid; -using namespace qpid::management; - -void AgentAttachment::setBanks(uint32_t broker, uint32_t bank) -{ - first = - ((uint64_t) (broker & 0x000fffff)) << 28 | - ((uint64_t) (bank & 0x0fffffff)); -} - -// Deprecated -ObjectId::ObjectId(uint8_t flags, uint16_t seq, uint32_t broker, uint64_t object) - : agent(0), agentEpoch(seq) -{ - first = - ((uint64_t) (flags & 0x0f)) << 60 | - ((uint64_t) (seq & 0x0fff)) << 48 | - ((uint64_t) (broker & 0x000fffff)) << 28; - second = object; -} - - -ObjectId::ObjectId(uint8_t flags, uint16_t seq, uint32_t broker) - : agent(0), second(0), agentEpoch(seq) -{ - first = - ((uint64_t) (flags & 0x0f)) << 60 | - ((uint64_t) (seq & 0x0fff)) << 48 | - ((uint64_t) (broker & 0x000fffff)) << 28; -} - -ObjectId::ObjectId(AgentAttachment* _agent, uint8_t flags, uint16_t seq) - : agent(_agent), second(0), agentEpoch(seq) -{ - - first = - ((uint64_t) (flags & 0x0f)) << 60 | - ((uint64_t) (seq & 0x0fff)) << 48; -} - - -ObjectId::ObjectId(istream& in) : agent(0) -{ - string text; - in >> text; - fromString(text); -} - -ObjectId::ObjectId(const string& text) : agent(0) -{ - fromString(text); -} - -void ObjectId::fromString(const string& text) -{ -#define FIELDS 5 -#if defined (_WIN32) && !defined (atoll) -# define atoll(X) _atoi64(X) -#endif - - // format: - // V1: <flags>-<sequence>-<broker-bank>-<agent-bank>-<uint64-app-id> - // V2: Not used - - string copy(text.c_str()); - char* cText; - char* field[FIELDS]; - bool atFieldStart = true; - int idx = 0; - - cText = const_cast<char*>(copy.c_str()); - for (char* cursor = cText; *cursor; cursor++) { - if (atFieldStart) { - if (idx >= FIELDS) - throw Exception("Invalid ObjectId format"); - field[idx++] = cursor; - atFieldStart = false; - } else { - if (*cursor == '-') { - *cursor = '\0'; - atFieldStart = true; - } - } - } - - if (idx != FIELDS) - throw Exception("Invalid ObjectId format"); - - agentEpoch = atoll(field[1]); - - first = (atoll(field[0]) << 60) + - (atoll(field[1]) << 48) + - (atoll(field[2]) << 28); - - agentName = string(field[3]); - second = atoll(field[4]); -} - - -bool ObjectId::operator==(const ObjectId &other) const -{ - return v2Key == other.v2Key; -} - -bool ObjectId::operator<(const ObjectId &other) const -{ - return v2Key < other.v2Key; -} - -bool ObjectId::equalV1(const ObjectId &other) const -{ - uint64_t otherFirst = agent == 0 ? other.first : other.first & 0xffff000000000000LL; - return first == otherFirst && second == other.second; -} - -// encode as V1-format binary -void ObjectId::encode(string& buffer) const -{ - const uint32_t len = 16; - char _data[len]; - qpid::framing::Buffer body(_data, len); - - if (agent == 0) - body.putLongLong(first); - else - body.putLongLong(first | agent->first); - body.putLongLong(second); - - body.reset(); - body.getRawData(buffer, len); -} - -// decode as V1-format binary -void ObjectId::decode(const string& buffer) -{ - const uint32_t len = 16; - char _data[len]; - qpid::framing::Buffer body(_data, len); - - body.checkAvailable(buffer.length()); - body.putRawData(buffer); - body.reset(); - first = body.getLongLong(); - second = body.getLongLong(); - v2Key = boost::lexical_cast<string>(second); -} - -// generate the V2 key from the index fields defined -// in the schema. -void ObjectId::setV2Key(const ManagementObject& object) -{ - stringstream oname; - oname << object.getPackageName() << ":" << object.getClassName() << ":" << object.getKey(); - v2Key = oname.str(); -} - - -// encode as V2-format map -void ObjectId::mapEncode(types::Variant::Map& map) const -{ - map["_object_name"] = v2Key; - if (!agentName.empty()) - map["_agent_name"] = agentName; - if (agentEpoch) - map["_agent_epoch"] = agentEpoch; -} - -// decode as v2-format map -void ObjectId::mapDecode(const types::Variant::Map& map) -{ - types::Variant::Map::const_iterator i; - - if ((i = map.find("_object_name")) != map.end()) - v2Key = i->second.asString(); - else - throw Exception("Required _object_name field missing."); - - if ((i = map.find("_agent_name")) != map.end()) - agentName = i->second.asString(); - - if ((i = map.find("_agent_epoch")) != map.end()) - agentEpoch = i->second.asInt64(); -} - - -ObjectId::operator types::Variant::Map() const -{ - types::Variant::Map m; - mapEncode(m); - return m; -} - - - -namespace qpid { -namespace management { - -ostream& operator<<(ostream& out, const ObjectId& i) -{ - uint64_t virtFirst = i.first; - if (i.agent) - virtFirst |= i.agent->getFirst(); - - out << ((virtFirst & 0xF000000000000000LL) >> 60) << - "-" << ((virtFirst & 0x0FFF000000000000LL) >> 48) << - "-" << ((virtFirst & 0x0000FFFFF0000000LL) >> 28) << - "-" << i.agentName << - "-" << i.second << - "(" << i.v2Key << ")"; - return out; -} - -}} - -ManagementObject::ManagementObject(Manageable* _core) : -createTime(qpid::sys::Duration(sys::EPOCH, sys::now())), - destroyTime(0), updateTime(createTime), configChanged(true), - instChanged(true), deleted(false), - coreObject(_core), flags(0), forcePublish(false) {} - -void ManagementObject::setUpdateTime() -{ - updateTime = sys::Duration(sys::EPOCH, sys::now()); -} - -void ManagementObject::resourceDestroy() -{ - QPID_LOG(trace, "Management object marked deleted: " << getObjectId().getV2Key()); - destroyTime = sys::Duration(sys::EPOCH, sys::now()); - deleted = true; -} - -int ManagementObject::maxThreads = 1; -int ManagementObject::nextThreadIndex = 0; - -void ManagementObject::writeTimestamps (string& buf) const -{ - char _data[4000]; - qpid::framing::Buffer body(_data, 4000); - - body.putShortString (getPackageName ()); - body.putShortString (getClassName ()); - body.putBin128 (getMd5Sum ()); - body.putLongLong (updateTime); - body.putLongLong (createTime); - body.putLongLong (destroyTime); - - uint32_t len = body.getPosition(); - body.reset(); - body.getRawData(buf, len); - - string oid; - objectId.encode(oid); - buf += oid; -} - -void ManagementObject::readTimestamps (const string& buf) -{ - char _data[4000]; - qpid::framing::Buffer body(_data, 4000); - string unused; - uint8_t unusedUuid[16]; - - body.checkAvailable(buf.length()); - body.putRawData(buf); - body.reset(); - - body.getShortString(unused); - body.getShortString(unused); - body.getBin128(unusedUuid); - updateTime = body.getLongLong(); - createTime = body.getLongLong(); - destroyTime = body.getLongLong(); -} - -uint32_t ManagementObject::writeTimestampsSize() const -{ - return 1 + getPackageName().length() + // str8 - 1 + getClassName().length() + // str8 - 16 + // bin128 - 8 + // uint64 - 8 + // uint64 - 8 + // uint64 - objectId.encodedSize(); // objectId -} - - -void ManagementObject::writeTimestamps (types::Variant::Map& map) const -{ - // types::Variant::Map oid, sid; - - // sid["_package_name"] = getPackageName(); - // sid["_class_name"] = getClassName(); - // sid["_hash"] = qpid::types::Uuid(getMd5Sum()); - // map["_schema_id"] = sid; - - // objectId.mapEncode(oid); - // map["_object_id"] = oid; - - map["_update_ts"] = updateTime; - map["_create_ts"] = createTime; - map["_delete_ts"] = destroyTime; -} - -void ManagementObject::readTimestamps (const types::Variant::Map& map) -{ - types::Variant::Map::const_iterator i; - - if ((i = map.find("_update_ts")) != map.end()) - updateTime = i->second.asUint64(); - if ((i = map.find("_create_ts")) != map.end()) - createTime = i->second.asUint64(); - if ((i = map.find("_delete_ts")) != map.end()) - destroyTime = i->second.asUint64(); -} - - -void ManagementObject::setReference(ObjectId) {} - -int ManagementObject::getThreadIndex() { - static QPID_TSS int thisIndex = -1; - if (thisIndex == -1) { - Mutex::ScopedLock mutex(accessLock); - thisIndex = nextThreadIndex; - if (nextThreadIndex < maxThreads - 1) - nextThreadIndex++; - } - return thisIndex; -} - - -// void ManagementObject::mapEncode(types::Variant::Map& map, -// bool includeProperties, -// bool includeStatistics) -// { -// types::Variant::Map values; - -// writeTimestamps(map); - -// mapEncodeValues(values, includeProperties, includeStatistics); -// map["_values"] = values; -// } - -// void ManagementObject::mapDecode(const types::Variant::Map& map) -// { -// types::Variant::Map::const_iterator i; - -// readTimestamps(map); - -// if ((i = map.find("_values")) != map.end()) -// mapDecodeValues(i->second.asMap()); -// } diff --git a/cpp/src/qpid/management/ManagementTopicExchange.cpp b/cpp/src/qpid/management/ManagementTopicExchange.cpp deleted file mode 100644 index ee8657646f..0000000000 --- a/cpp/src/qpid/management/ManagementTopicExchange.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/management/ManagementTopicExchange.h" -#include "qpid/log/Statement.h" - -using namespace qpid::management; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -ManagementTopicExchange::ManagementTopicExchange(const string& _name, Manageable* _parent, Broker* b) : - Exchange (_name, _parent, b), - TopicExchange(_name, _parent, b), - managementAgent(0) {} -ManagementTopicExchange::ManagementTopicExchange(const std::string& _name, - bool _durable, - const FieldTable& _args, - Manageable* _parent, Broker* b) : - Exchange (_name, _durable, _args, _parent, b), - TopicExchange(_name, _durable, _args, _parent, b), - managementAgent(0) {} - -void ManagementTopicExchange::route(Deliverable& msg, - const string& routingKey, - const FieldTable* args) -{ - bool routeIt = true; - - // Intercept management agent commands - if (managementAgent) - routeIt = managementAgent->dispatchCommand(msg, routingKey, args, true, qmfVersion); - - if (routeIt) - TopicExchange::route(msg, routingKey, args); -} - -bool ManagementTopicExchange::bind(Queue::shared_ptr queue, - const string& routingKey, - const qpid::framing::FieldTable* args) -{ - if (qmfVersion == 1) - managementAgent->clientAdded(routingKey); - return TopicExchange::bind(queue, routingKey, args); -} - -void ManagementTopicExchange::setManagmentAgent(ManagementAgent* agent, int qv) -{ - managementAgent = agent; - qmfVersion = qv; -} - - -ManagementTopicExchange::~ManagementTopicExchange() {} - -const std::string ManagementTopicExchange::typeName("management-topic"); - diff --git a/cpp/src/qpid/management/ManagementTopicExchange.h b/cpp/src/qpid/management/ManagementTopicExchange.h deleted file mode 100644 index 232300265e..0000000000 --- a/cpp/src/qpid/management/ManagementTopicExchange.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ManagementTopicExchange_ -#define _ManagementTopicExchange_ - -#include "qpid/broker/TopicExchange.h" -#include "qpid/management/ManagementAgent.h" - -namespace qpid { -namespace broker { - -class ManagementTopicExchange : public virtual TopicExchange -{ - private: - management::ManagementAgent* managementAgent; - int qmfVersion; - - public: - static const std::string typeName; - - ManagementTopicExchange(const std::string& name, Manageable* _parent = 0, Broker* broker = 0); - ManagementTopicExchange(const std::string& _name, bool _durable, - const qpid::framing::FieldTable& _args, - Manageable* _parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - void setManagmentAgent(management::ManagementAgent* agent, int qmfVersion); - - virtual ~ManagementTopicExchange(); -}; - - -} -} - -#endif diff --git a/cpp/src/qpid/management/Mutex.cpp b/cpp/src/qpid/management/Mutex.cpp deleted file mode 100644 index f05abb01dc..0000000000 --- a/cpp/src/qpid/management/Mutex.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * Copyright (c) 2008 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/management/Mutex.h" -#include "qpid/sys/Mutex.h" - -using namespace std; -using namespace qpid::management; - -Mutex::Mutex() : impl(new sys::Mutex()) {} -Mutex::~Mutex() { delete impl; } -void Mutex::lock() { impl->lock(); } -void Mutex::unlock() { impl->unlock(); } - diff --git a/cpp/src/qpid/memory.h b/cpp/src/qpid/memory.h deleted file mode 100644 index 99d7a71e7b..0000000000 --- a/cpp/src/qpid/memory.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef QPID_AUTO_PTR_H -#define QPID_AUTO_PTR_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <memory> -namespace qpid { -/** Convenient template for creating auto_ptr in-place in an argument list. */ -template <class T> -std::auto_ptr<T> make_auto_ptr(T* ptr) { return std::auto_ptr<T>(ptr); } - -} // namespace qpid - - - -#endif /*!QPID_AUTO_PTR_H*/ diff --git a/cpp/src/qpid/messaging/Address.cpp b/cpp/src/qpid/messaging/Address.cpp deleted file mode 100644 index a516959edb..0000000000 --- a/cpp/src/qpid/messaging/Address.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Address.h" -#include "qpid/framing/Uuid.h" -#include <sstream> -#include <boost/format.hpp> - -namespace qpid { -namespace messaging { - -using namespace qpid::types; - -namespace { -const std::string SUBJECT_DIVIDER = "/"; -const std::string OPTIONS_DIVIDER = ";"; -const std::string SPACE = " "; -const std::string TYPE = "type"; -} -class AddressImpl -{ - public: - std::string name; - std::string subject; - Variant::Map options; - - AddressImpl() {} - AddressImpl(const std::string& n, const std::string& s, const Variant::Map& o) : - name(n), subject(s), options(o) {} -}; - -class AddressParser -{ - public: - AddressParser(const std::string&); - bool parse(Address& address); - private: - const std::string& input; - std::string::size_type current; - static const std::string RESERVED; - - bool readChar(char c); - bool readQuotedString(std::string& s); - bool readQuotedValue(Variant& value); - bool readString(std::string& value, char delimiter); - bool readWord(std::string& word, const std::string& delims = RESERVED); - bool readSimpleValue(Variant& word); - bool readKey(std::string& key); - bool readValue(Variant& value); - bool readKeyValuePair(Variant::Map& map); - bool readMap(Variant& value); - bool readList(Variant& value); - bool readName(std::string& name); - bool readSubject(std::string& subject); - bool error(const std::string& message); - bool eos(); - bool iswhitespace(); - bool in(const std::string& delims); - bool isreserved(); -}; - -Address::Address() : impl(new AddressImpl()) {} -Address::Address(const std::string& address) : impl(new AddressImpl()) -{ - AddressParser parser(address); - parser.parse(*this); -} -Address::Address(const std::string& name, const std::string& subject, const Variant::Map& options, - const std::string& type) - : impl(new AddressImpl(name, subject, options)) { setType(type); } -Address::Address(const Address& a) : - impl(new AddressImpl(a.impl->name, a.impl->subject, a.impl->options)) {} -Address::~Address() { delete impl; } - -Address& Address::operator=(const Address& a) { *impl = *a.impl; return *this; } - - -std::string Address::str() const -{ - std::stringstream out; - out << impl->name; - if (!impl->subject.empty()) out << SUBJECT_DIVIDER << impl->subject; - if (!impl->options.empty()) out << OPTIONS_DIVIDER << impl->options; - return out.str(); -} -Address::operator bool() const { return !impl->name.empty(); } -bool Address::operator !() const { return impl->name.empty(); } - -const std::string& Address::getName() const { return impl->name; } -void Address::setName(const std::string& name) { impl->name = name; } -const std::string& Address::getSubject() const { return impl->subject; } -void Address::setSubject(const std::string& subject) { impl->subject = subject; } -const Variant::Map& Address::getOptions() const { return impl->options; } -Variant::Map& Address::getOptions() { return impl->options; } -void Address::setOptions(const Variant::Map& options) { impl->options = options; } - - -namespace{ -const Variant EMPTY_VARIANT; -const std::string EMPTY_STRING; -const std::string NODE_PROPERTIES="node"; -} - -const Variant& find(const Variant::Map& map, const std::string& key) -{ - Variant::Map::const_iterator i = map.find(key); - if (i == map.end()) return EMPTY_VARIANT; - else return i->second; -} - -std::string Address::getType() const -{ - const Variant& props = find(impl->options, NODE_PROPERTIES); - if (props.getType() == VAR_MAP) { - const Variant& type = find(props.asMap(), TYPE); - if (!type.isVoid()) return type.asString(); - } - return EMPTY_STRING; -} - -void Address::setType(const std::string& type) -{ - Variant& props = impl->options[NODE_PROPERTIES]; - if (props.isVoid()) props = Variant::Map(); - props.asMap()[TYPE] = type; -} - -std::ostream& operator<<(std::ostream& out, const Address& address) -{ - out << address.str(); - return out; -} - -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/AddressParser.cpp b/cpp/src/qpid/messaging/AddressParser.cpp deleted file mode 100644 index 4c8f35fbc5..0000000000 --- a/cpp/src/qpid/messaging/AddressParser.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "AddressParser.h" -#include "qpid/framing/Uuid.h" -#include <boost/format.hpp> - -namespace qpid { -namespace messaging { - -using namespace qpid::types; - -AddressParser::AddressParser(const std::string& s) : input(s), current(0) {} - -bool AddressParser::error(const std::string& message) -{ - throw MalformedAddress((boost::format("%1%, character %2% of %3%") % message % current % input).str()); -} - -bool AddressParser::parse(Address& address) -{ - std::string name; - if (readName(name)) { - if (name.find('#') == 0) name = qpid::framing::Uuid(true).str() + name; - address.setName(name); - if (readChar('/')) { - std::string subject; - readSubject(subject); - address.setSubject(subject); - } - if (readChar(';')) { - Variant options = Variant::Map(); - if (readMap(options)) { - address.setOptions(options.asMap()); - } - } - //skip trailing whitespace - while (!eos() && iswhitespace()) ++current; - return eos() || error("Unexpected chars in address: " + input.substr(current)); - } else { - return input.empty() || error("Expected name"); - } -} - -bool AddressParser::parseMap(Variant::Map& map) -{ - if (readChar('{')) { - readMapEntries(map); - return readChar('}') || error("Unmatched '{'!"); - } else { - return false; - } -} - -bool AddressParser::parseList(Variant::List& list) -{ - if (readChar('[')) { - readListItems(list); - return readChar(']') || error("Unmatched '['!"); - } else { - return false; - } -} - - -bool AddressParser::readList(Variant& value) -{ - if (readChar('[')) { - value = Variant::List(); - readListItems(value.asList()); - return readChar(']') || error("Unmatched '['!"); - } else { - return false; - } -} - -void AddressParser::readListItems(Variant::List& list) -{ - Variant item; - while (readValueIfExists(item)) { - list.push_back(item); - if (!readChar(',')) break; - } -} - -bool AddressParser::readMap(Variant& value) -{ - if (readChar('{')) { - value = Variant::Map(); - readMapEntries(value.asMap()); - return readChar('}') || error("Unmatched '{'!"); - } else { - return false; - } -} - -void AddressParser::readMapEntries(Variant::Map& map) -{ - while (readKeyValuePair(map) && readChar(',')) {} -} - -bool AddressParser::readKeyValuePair(Variant::Map& map) -{ - std::string key; - Variant value; - if (readKey(key)) { - if (readChar(':') && readValue(value)) { - map[key] = value; - return true; - } else { - return error("Bad key-value pair, expected ':'"); - } - } else { - return false; - } -} - -bool AddressParser::readKey(std::string& key) -{ - return readWord(key) || readQuotedString(key); -} - -bool AddressParser::readValue(Variant& value) -{ - return readValueIfExists(value) || error("Expected value"); -} - -bool AddressParser::readValueIfExists(Variant& value) -{ - return readSimpleValue(value) || readQuotedValue(value) || - readMap(value) || readList(value); -} - -bool AddressParser::readString(std::string& value, char delimiter) -{ - if (readChar(delimiter)) { - std::string::size_type start = current++; - while (!eos()) { - if (input.at(current) == delimiter) { - if (current > start) { - value = input.substr(start, current - start); - } else { - value = ""; - } - ++current; - return true; - } else { - ++current; - } - } - return error("Unmatched delimiter"); - } else { - return false; - } -} - -bool AddressParser::readName(std::string& name) -{ - return readQuotedString(name) || readWord(name, "/;"); -} - -bool AddressParser::readSubject(std::string& subject) -{ - return readQuotedString(subject) || readWord(subject, ";"); -} - -bool AddressParser::readQuotedString(std::string& s) -{ - return readString(s, '"') || readString(s, '\''); -} - -bool AddressParser::readQuotedValue(Variant& value) -{ - std::string s; - if (readQuotedString(s)) { - value = s; - return true; - } else { - return false; - } -} - -bool AddressParser::readSimpleValue(Variant& value) -{ - std::string s; - if (readWord(s)) { - value.parse(s); - return true; - } else { - return false; - } -} - -bool AddressParser::readWord(std::string& value, const std::string& delims) -{ - //skip leading whitespace - while (!eos() && iswhitespace()) ++current; - - //read any number of non-whitespace, non-reserved chars into value - std::string::size_type start = current; - while (!eos() && !iswhitespace() && !in(delims)) ++current; - - if (current > start) { - value = input.substr(start, current - start); - return true; - } else { - return false; - } -} - -bool AddressParser::readChar(char c) -{ - while (!eos()) { - if (iswhitespace()) { - ++current; - } else if (input.at(current) == c) { - ++current; - return true; - } else { - return false; - } - } - return false; -} - -bool AddressParser::iswhitespace() -{ - return ::isspace(input.at(current)); -} - -bool AddressParser::isreserved() -{ - return in(RESERVED); -} - -bool AddressParser::in(const std::string& chars) -{ - return chars.find(input.at(current)) != std::string::npos; -} - -bool AddressParser::eos() -{ - return current >= input.size(); -} - -const std::string AddressParser::RESERVED = "\'\"{}[],:/"; - -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/AddressParser.h b/cpp/src/qpid/messaging/AddressParser.h deleted file mode 100644 index 1635331d19..0000000000 --- a/cpp/src/qpid/messaging/AddressParser.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef QPID_MESSAGING_ADDRESSPARSER_H -#define QPID_MESSAGING_ADDRESSPARSER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Address.h" - -namespace qpid { -namespace messaging { - -class AddressParser -{ - public: - AddressParser(const std::string&); - bool parse(Address& address); - bool parseMap(qpid::types::Variant::Map& map); - bool parseList(qpid::types::Variant::List& list); - private: - const std::string& input; - std::string::size_type current; - static const std::string RESERVED; - - bool readChar(char c); - bool readQuotedString(std::string& s); - bool readQuotedValue(qpid::types::Variant& value); - bool readString(std::string& value, char delimiter); - bool readWord(std::string& word, const std::string& delims = RESERVED); - bool readSimpleValue(qpid::types::Variant& word); - bool readKey(std::string& key); - bool readValue(qpid::types::Variant& value); - bool readValueIfExists(qpid::types::Variant& value); - bool readKeyValuePair(qpid::types::Variant::Map& map); - bool readMap(qpid::types::Variant& value); - bool readList(qpid::types::Variant& value); - bool readName(std::string& name); - bool readSubject(std::string& subject); - bool error(const std::string& message); - bool eos(); - bool iswhitespace(); - bool in(const std::string& delims); - bool isreserved(); - void readListItems(qpid::types::Variant::List& list); - void readMapEntries(qpid::types::Variant::Map& map); -}; - -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_ADDRESSPARSER_H*/ diff --git a/cpp/src/qpid/messaging/Connection.cpp b/cpp/src/qpid/messaging/Connection.cpp deleted file mode 100644 index bd90aa54a7..0000000000 --- a/cpp/src/qpid/messaging/Connection.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/AddressParser.h" -#include "qpid/messaging/ConnectionImpl.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/SessionImpl.h" -#include "qpid/messaging/PrivateImplRef.h" -#include "qpid/client/amqp0_10/ConnectionImpl.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace messaging { - -using namespace qpid::types; - -typedef PrivateImplRef<qpid::messaging::Connection> PI; - -Connection::Connection(ConnectionImpl* impl) { PI::ctor(*this, impl); } -Connection::Connection(const Connection& c) : Handle<ConnectionImpl>() { PI::copy(*this, c); } -Connection& Connection::operator=(const Connection& c) { return PI::assign(*this, c); } -Connection::~Connection() { PI::dtor(*this); } - -Connection::Connection(const std::string& url, const std::string& o) -{ - Variant::Map options; - AddressParser parser(o); - if (o.empty() || parser.parseMap(options)) { - PI::ctor(*this, new qpid::client::amqp0_10::ConnectionImpl(url, options)); - } else { - throw InvalidOptionString("Invalid option string: " + o); - } -} -Connection::Connection(const std::string& url, const Variant::Map& options) -{ - PI::ctor(*this, new qpid::client::amqp0_10::ConnectionImpl(url, options)); -} - -Connection::Connection() -{ - Variant::Map options; - std::string url = "amqp:tcp:127.0.0.1:5672"; - PI::ctor(*this, new qpid::client::amqp0_10::ConnectionImpl(url, options)); -} - -void Connection::open() { impl->open(); } -bool Connection::isOpen() { return impl->isOpen(); } -bool Connection::isOpen() const { return impl->isOpen(); } -void Connection::close() { impl->close(); } -Session Connection::createSession(const std::string& name) { return impl->newSession(false, name); } -Session Connection::createTransactionalSession(const std::string& name) -{ - return impl->newSession(true, name); -} -Session Connection::getSession(const std::string& name) const { return impl->getSession(name); } -void Connection::setOption(const std::string& name, const Variant& value) -{ - impl->setOption(name, value); -} -std::string Connection::getAuthenticatedUsername() -{ - return impl->getAuthenticatedUsername(); -} -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/ConnectionImpl.h b/cpp/src/qpid/messaging/ConnectionImpl.h deleted file mode 100644 index 1e11d9a6d5..0000000000 --- a/cpp/src/qpid/messaging/ConnectionImpl.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_MESSAGING_CONNECTIONIMPL_H -#define QPID_MESSAGING_CONNECTIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <string> -#include "qpid/RefCounted.h" - -namespace qpid { - -namespace types { -class Variant; -} - -namespace messaging { - -class Session; - -class ConnectionImpl : public virtual qpid::RefCounted -{ - public: - virtual ~ConnectionImpl() {} - virtual void open() = 0; - virtual bool isOpen() const = 0; - virtual void close() = 0; - virtual Session newSession(bool transactional, const std::string& name) = 0; - virtual Session getSession(const std::string& name) const = 0; - virtual void setOption(const std::string& name, const qpid::types::Variant& value) = 0; - virtual std::string getAuthenticatedUsername() = 0; - private: -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_CONNECTIONIMPL_H*/ diff --git a/cpp/src/qpid/messaging/Duration.cpp b/cpp/src/qpid/messaging/Duration.cpp deleted file mode 100644 index a23e9f5bcb..0000000000 --- a/cpp/src/qpid/messaging/Duration.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Duration.h" -#include <limits> - -namespace qpid { -namespace messaging { - -Duration::Duration(uint64_t ms) : milliseconds(ms) {} -uint64_t Duration::getMilliseconds() const { return milliseconds; } - -Duration operator*(const Duration& duration, uint64_t multiplier) -{ - return Duration(duration.getMilliseconds() * multiplier); -} - -Duration operator*(uint64_t multiplier, const Duration& duration) -{ - return Duration(duration.getMilliseconds() * multiplier); -} - -bool operator==(const Duration& a, const Duration& b) -{ - return a.getMilliseconds() == b.getMilliseconds(); -} - -bool operator!=(const Duration& a, const Duration& b) -{ - return a.getMilliseconds() != b.getMilliseconds(); -} - -const Duration Duration::FOREVER(std::numeric_limits<uint64_t>::max()); -const Duration Duration::IMMEDIATE(0); -const Duration Duration::SECOND(1000); -const Duration Duration::MINUTE(SECOND * 60); - -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/FailoverUpdates.cpp b/cpp/src/qpid/messaging/FailoverUpdates.cpp deleted file mode 100644 index 4f2fcf2e82..0000000000 --- a/cpp/src/qpid/messaging/FailoverUpdates.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/FailoverUpdates.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Session.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" -#include "qpid/Url.h" -#include "qpid/framing/Uuid.h" -#include <vector> - -namespace qpid { -namespace messaging { -using framing::Uuid; - -struct FailoverUpdatesImpl : qpid::sys::Runnable -{ - Connection connection; - Session session; - Receiver receiver; - qpid::sys::Thread thread; - - FailoverUpdatesImpl(Connection& c) : connection(c) - { - session = connection.createSession("failover-updates."+Uuid(true).str()); - receiver = session.createReceiver("amq.failover"); - thread = qpid::sys::Thread(*this); - } - - ~FailoverUpdatesImpl() { - try { - session.close(); - } catch(...) {} // Squash exceptions in a destructor. - thread.join(); - } - - void run() - { - try { - Message message; - while (receiver.fetch(message)) { - connection.setOption("reconnect-urls", message.getProperties()["amq.failover"]); - QPID_LOG(debug, "Set reconnect-urls to " << message.getProperties()["amq.failover"]); - session.acknowledge(); - } - } - catch (const ClosedException&) {} - catch (const qpid::TransportFailure& e) { - QPID_LOG(warning, "Failover updates stopped on loss of connection. " << e.what()); - } - catch (const std::exception& e) { - QPID_LOG(warning, "Failover updates stopped due to exception: " << e.what()); - } - } -}; - -FailoverUpdates::FailoverUpdates(Connection& connection) : impl(new FailoverUpdatesImpl(connection)) {} -FailoverUpdates::~FailoverUpdates() { if (impl) { delete impl; } } -FailoverUpdates::FailoverUpdates(const FailoverUpdates&) : impl(0) {} -FailoverUpdates& FailoverUpdates::operator=(const FailoverUpdates&) { return *this; } - - -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/HandleInstantiator.cpp b/cpp/src/qpid/messaging/HandleInstantiator.cpp deleted file mode 100644 index c9a7680bb4..0000000000 --- a/cpp/src/qpid/messaging/HandleInstantiator.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-#include "qpid/messaging/Connection.h"
-#include "qpid/messaging/Receiver.h"
-#include "qpid/messaging/Sender.h"
-#include "qpid/messaging/Session.h"
-
-namespace qpid {
-namespace messaging {
-
-using namespace qpid::types;
-
-void HandleInstantiatorDoNotCall(void)
-{
- // This function exists to instantiate various template Handle
- // bool functions. The instances are then available to
- // the qpidmessaging DLL and subsequently exported.
- // This function must not be exported nor called called.
- // For further information refer to
- // https://issues.apache.org/jira/browse/QPID-2926
-
- Connection connection;
- if (connection.isValid()) connection.close();
- if (connection.isNull() ) connection.close();
- if (connection ) connection.close();
- if (!connection ) connection.close();
-
- Receiver receiver;
- if (receiver.isValid()) receiver.close();
- if (receiver.isNull() ) receiver.close();
- if (receiver ) receiver.close();
- if (!receiver ) receiver.close();
-
- Sender sender;
- if (sender.isValid()) sender.close();
- if (sender.isNull() ) sender.close();
- if (sender ) sender.close();
- if (!sender ) sender.close();
-
- Session session;
- if (session.isValid()) session.close();
- if (session.isNull() ) session.close();
- if (session ) session.close();
- if (!session ) session.close();
-}
-}} // namespace qpid::messaging
diff --git a/cpp/src/qpid/messaging/Message.cpp b/cpp/src/qpid/messaging/Message.cpp deleted file mode 100644 index 83cdfd3c55..0000000000 --- a/cpp/src/qpid/messaging/Message.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Message.h" -#include "qpid/messaging/MessageImpl.h" -#include "qpid/amqp_0_10/Codecs.h" -#include <boost/format.hpp> - -namespace qpid { -namespace messaging { - -using namespace qpid::types; - -Message::Message(const std::string& bytes) : impl(new MessageImpl(bytes)) {} -Message::Message(const char* bytes, size_t count) : impl(new MessageImpl(bytes, count)) {} - -Message::Message(const Message& m) : impl(new MessageImpl(*m.impl)) {} -Message::~Message() { delete impl; } - -Message& Message::operator=(const Message& m) { *impl = *m.impl; return *this; } - -void Message::setReplyTo(const Address& d) { impl->setReplyTo(d); } -const Address& Message::getReplyTo() const { return impl->getReplyTo(); } - -void Message::setSubject(const std::string& s) { impl->setSubject(s); } -const std::string& Message::getSubject() const { return impl->getSubject(); } - -void Message::setContentType(const std::string& s) { impl->setContentType(s); } -const std::string& Message::getContentType() const { return impl->getContentType(); } - -void Message::setMessageId(const std::string& id) { impl->messageId = id; } -const std::string& Message::getMessageId() const { return impl->messageId; } - -void Message::setUserId(const std::string& id) { impl->userId = id; } -const std::string& Message::getUserId() const { return impl->userId; } - -void Message::setCorrelationId(const std::string& id) { impl->correlationId = id; } -const std::string& Message::getCorrelationId() const { return impl->correlationId; } - -uint8_t Message::getPriority() const { return impl->priority; } -void Message::setPriority(uint8_t priority) { impl->priority = priority; } - -void Message::setTtl(Duration ttl) { impl->ttl = ttl.getMilliseconds(); } -Duration Message::getTtl() const { return Duration(impl->ttl); } - -void Message::setDurable(bool durable) { impl->durable = durable; } -bool Message::getDurable() const { return impl->durable; } - -bool Message::getRedelivered() const { return impl->redelivered; } -void Message::setRedelivered(bool redelivered) { impl->redelivered = redelivered; } - -const Variant::Map& Message::getProperties() const { return impl->getHeaders(); } -Variant::Map& Message::getProperties() { return impl->getHeaders(); } -void Message::setProperty(const std::string& k, const qpid::types::Variant& v) { impl->setHeader(k,v); } - -void Message::setContent(const std::string& c) { impl->setBytes(c); } -void Message::setContent(const char* chars, size_t count) { impl->setBytes(chars, count); } -std::string Message::getContent() const { return impl->getBytes(); } - -const char* Message::getContentPtr() const -{ - return impl->getBytes().data(); -} - -size_t Message::getContentSize() const -{ - return impl->getBytes().size(); -} - -EncodingException::EncodingException(const std::string& msg) : qpid::types::Exception(msg) {} - -const std::string BAD_ENCODING("Unsupported encoding: %1% (only %2% is supported at present)."); - -template <class C> struct MessageCodec -{ - static bool checkEncoding(const std::string& requested) - { - if (requested.size()) { - if (requested == C::contentType) return true; - else throw EncodingException((boost::format(BAD_ENCODING) % requested % C::contentType).str()); - } else { - return false; - } - } - - /* - * Currently only support a single encoding type for both list and - * map, based on AMQP 0-10, though wider support is anticipated in the - * future. This method simply checks that the desired encoding (if one - * is specified, either through the message-content or through an - * override) is indeed supported. - */ - static void checkEncoding(const Message& message, const std::string& requested) - { - checkEncoding(requested) || checkEncoding(message.getContentType()); - } - - static void decode(const Message& message, typename C::ObjectType& object, const std::string& encoding) - { - checkEncoding(message, encoding); - C::decode(message.getContent(), object); - } - - static void encode(const typename C::ObjectType& map, Message& message, const std::string& encoding) - { - checkEncoding(message, encoding); - std::string content; - C::encode(map, content); - message.setContentType(C::contentType); - message.setContent(content); - } -}; - -void decode(const Message& message, Variant::Map& map, const std::string& encoding) -{ - MessageCodec<qpid::amqp_0_10::MapCodec>::decode(message, map, encoding); -} -void decode(const Message& message, Variant::List& list, const std::string& encoding) -{ - MessageCodec<qpid::amqp_0_10::ListCodec>::decode(message, list, encoding); -} -void encode(const Variant::Map& map, Message& message, const std::string& encoding) -{ - MessageCodec<qpid::amqp_0_10::MapCodec>::encode(map, message, encoding); -} -void encode(const Variant::List& list, Message& message, const std::string& encoding) -{ - MessageCodec<qpid::amqp_0_10::ListCodec>::encode(list, message, encoding); -} - -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/MessageImpl.cpp b/cpp/src/qpid/messaging/MessageImpl.cpp deleted file mode 100644 index 0601800e46..0000000000 --- a/cpp/src/qpid/messaging/MessageImpl.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "MessageImpl.h" -#include "qpid/messaging/Message.h" - -namespace qpid { -namespace messaging { - -namespace { -const std::string EMPTY_STRING = ""; -} - -using namespace qpid::types; - -MessageImpl::MessageImpl(const std::string& c) : - priority(0), - ttl(0), - durable(false), - redelivered(false), - bytes(c), - internalId(0) {} -MessageImpl::MessageImpl(const char* chars, size_t count) : - priority(0), - ttl(0), - durable (false), - redelivered(false), - bytes(chars, count), - internalId(0) {} - -void MessageImpl::setReplyTo(const Address& d) { replyTo = d; } -const Address& MessageImpl::getReplyTo() const { return replyTo; } - -void MessageImpl::setSubject(const std::string& s) { subject = s; } -const std::string& MessageImpl::getSubject() const { return subject; } - -void MessageImpl::setContentType(const std::string& s) { contentType = s; } -const std::string& MessageImpl::getContentType() const { return contentType; } - -const Variant::Map& MessageImpl::getHeaders() const { return headers; } -Variant::Map& MessageImpl::getHeaders() { return headers; } -void MessageImpl::setHeader(const std::string& key, const qpid::types::Variant& val) { headers[key] = val; } - -//should these methods be on MessageContent? -void MessageImpl::setBytes(const std::string& c) { bytes = c; } -void MessageImpl::setBytes(const char* chars, size_t count) { bytes.assign(chars, count); } -const std::string& MessageImpl::getBytes() const { return bytes; } -std::string& MessageImpl::getBytes() { return bytes; } - -void MessageImpl::setInternalId(qpid::framing::SequenceNumber i) { internalId = i; } -qpid::framing::SequenceNumber MessageImpl::getInternalId() { return internalId; } - -MessageImpl& MessageImplAccess::get(Message& msg) -{ - return *msg.impl; -} -const MessageImpl& MessageImplAccess::get(const Message& msg) -{ - return *msg.impl; -} - -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/MessageImpl.h b/cpp/src/qpid/messaging/MessageImpl.h deleted file mode 100644 index 57df6b3fda..0000000000 --- a/cpp/src/qpid/messaging/MessageImpl.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef QPID_MESSAGING_MESSAGEIMPL_H -#define QPID_MESSAGING_MESSAGEIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Address.h" -#include "qpid/types/Variant.h" -#include "qpid/framing/SequenceNumber.h" - -namespace qpid { -namespace messaging { - -struct MessageImpl -{ - Address replyTo; - std::string subject; - std::string contentType; - std::string messageId; - std::string userId; - std::string correlationId; - uint8_t priority; - uint64_t ttl; - bool durable; - bool redelivered; - qpid::types::Variant::Map headers; - - std::string bytes; - - qpid::framing::SequenceNumber internalId; - - MessageImpl(const std::string& c); - MessageImpl(const char* chars, size_t count); - - void setReplyTo(const Address& d); - const Address& getReplyTo() const; - - void setSubject(const std::string& s); - const std::string& getSubject() const; - - void setContentType(const std::string& s); - const std::string& getContentType() const; - - const qpid::types::Variant::Map& getHeaders() const; - qpid::types::Variant::Map& getHeaders(); - void setHeader(const std::string& key, const qpid::types::Variant& val); - - void setBytes(const std::string& bytes); - void setBytes(const char* chars, size_t count); - const std::string& getBytes() const; - std::string& getBytes(); - - void setInternalId(qpid::framing::SequenceNumber id); - qpid::framing::SequenceNumber getInternalId(); - -}; - -class Message; - -/** - * Provides access to the internal MessageImpl for a message which is - * useful when accessing any message state not exposed directly - * through the public API. - */ -struct MessageImplAccess -{ - static MessageImpl& get(Message&); - static const MessageImpl& get(const Message&); -}; - -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_MESSAGEIMPL_H*/ diff --git a/cpp/src/qpid/messaging/PrivateImplRef.h b/cpp/src/qpid/messaging/PrivateImplRef.h deleted file mode 100644 index e77c58d071..0000000000 --- a/cpp/src/qpid/messaging/PrivateImplRef.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef QPID_MESSAGING_PRIVATEIMPL_H -#define QPID_MESSAGING_PRIVATEIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/messaging/ImportExport.h" -#include <boost/intrusive_ptr.hpp> -#include "qpid/RefCounted.h" - -namespace qpid { -namespace messaging { - -/** - * Helper class to implement a class with a private, reference counted - * implementation and reference semantics. - * - * Such classes are used in the public API to hide implementation, they - * should. Example of use: - * - * === Foo.h - * - * template <class T> PrivateImplRef; - * class FooImpl; - * - * Foo : public Handle<FooImpl> { - * public: - * Foo(FooImpl* = 0); - * Foo(const Foo&); - * ~Foo(); - * Foo& operator=(const Foo&); - * - * int fooDo(); // and other Foo functions... - * - * private: - * typedef FooImpl Impl; - * Impl* impl; - * friend class PrivateImplRef<Foo>; - * - * === Foo.cpp - * - * typedef PrivateImplRef<Foo> PI; - * Foo::Foo(FooImpl* p) { PI::ctor(*this, p); } - * Foo::Foo(const Foo& c) : Handle<FooImpl>() { PI::copy(*this, c); } - * Foo::~Foo() { PI::dtor(*this); } - * Foo& Foo::operator=(const Foo& c) { return PI::assign(*this, c); } - * - * int foo::fooDo() { return impl->fooDo(); } - * - */ -template <class T> class PrivateImplRef { - public: - typedef typename T::Impl Impl; - typedef boost::intrusive_ptr<Impl> intrusive_ptr; - - /** Get the implementation pointer from a handle */ - static intrusive_ptr get(const T& t) { return intrusive_ptr(t.impl); } - - /** Set the implementation pointer in a handle */ - static void set(T& t, const intrusive_ptr& p) { - if (t.impl == p) return; - if (t.impl) boost::intrusive_ptr_release(t.impl); - t.impl = p.get(); - if (t.impl) boost::intrusive_ptr_add_ref(t.impl); - } - - // Helper functions to implement the ctor, dtor, copy, assign - static void ctor(T& t, Impl* p) { t.impl = p; if (p) boost::intrusive_ptr_add_ref(p); } - static void copy(T& t, const T& x) { if (&t == &x) return; t.impl = 0; assign(t, x); } - static void dtor(T& t) { if(t.impl) boost::intrusive_ptr_release(t.impl); } - static T& assign(T& t, const T& x) { set(t, get(x)); return t;} -}; - -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_PRIVATEIMPL_H*/ diff --git a/cpp/src/qpid/messaging/Receiver.cpp b/cpp/src/qpid/messaging/Receiver.cpp deleted file mode 100644 index 78e0c5daa3..0000000000 --- a/cpp/src/qpid/messaging/Receiver.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/ReceiverImpl.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/PrivateImplRef.h" - -namespace qpid { -namespace messaging { - -typedef PrivateImplRef<qpid::messaging::Receiver> PI; - -Receiver::Receiver(ReceiverImpl* impl) { PI::ctor(*this, impl); } -Receiver::Receiver(const Receiver& s) : Handle<ReceiverImpl>() { PI::copy(*this, s); } -Receiver::~Receiver() { PI::dtor(*this); } -Receiver& Receiver::operator=(const Receiver& s) { return PI::assign(*this, s); } -bool Receiver::get(Message& message, Duration timeout) { return impl->get(message, timeout); } -Message Receiver::get(Duration timeout) { return impl->get(timeout); } -bool Receiver::fetch(Message& message, Duration timeout) { return impl->fetch(message, timeout); } -Message Receiver::fetch(Duration timeout) { return impl->fetch(timeout); } -void Receiver::setCapacity(uint32_t c) { impl->setCapacity(c); } -uint32_t Receiver::getCapacity() { return impl->getCapacity(); } -uint32_t Receiver::getAvailable() { return impl->getAvailable(); } -uint32_t Receiver::getUnsettled() { return impl->getUnsettled(); } -void Receiver::close() { impl->close(); } -const std::string& Receiver::getName() const { return impl->getName(); } -Session Receiver::getSession() const { return impl->getSession(); } -bool Receiver::isClosed() const { return impl->isClosed(); } -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/ReceiverImpl.h b/cpp/src/qpid/messaging/ReceiverImpl.h deleted file mode 100644 index 57059bfd28..0000000000 --- a/cpp/src/qpid/messaging/ReceiverImpl.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_MESSAGING_RECEIVERIMPL_H -#define QPID_MESSAGING_RECEIVERIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/RefCounted.h" - -namespace qpid { -namespace messaging { - -class Message; -class MessageListener; -class Session; - -class ReceiverImpl : public virtual qpid::RefCounted -{ - public: - virtual ~ReceiverImpl() {} - virtual bool get(Message& message, Duration timeout) = 0; - virtual Message get(Duration timeout) = 0; - virtual bool fetch(Message& message, Duration timeout) = 0; - virtual Message fetch(Duration timeout) = 0; - virtual void setCapacity(uint32_t) = 0; - virtual uint32_t getCapacity() = 0; - virtual uint32_t getAvailable() = 0; - virtual uint32_t getUnsettled() = 0; - virtual void close() = 0; - virtual const std::string& getName() const = 0; - virtual Session getSession() const = 0; - virtual bool isClosed() const = 0; -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_RECEIVERIMPL_H*/ diff --git a/cpp/src/qpid/messaging/Sender.cpp b/cpp/src/qpid/messaging/Sender.cpp deleted file mode 100644 index 53dbb69777..0000000000 --- a/cpp/src/qpid/messaging/Sender.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/SenderImpl.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/PrivateImplRef.h" - -namespace qpid { -namespace messaging { -typedef PrivateImplRef<qpid::messaging::Sender> PI; - -Sender::Sender(SenderImpl* impl) { PI::ctor(*this, impl); } -Sender::Sender(const Sender& s) : qpid::messaging::Handle<SenderImpl>() { PI::copy(*this, s); } -Sender::~Sender() { PI::dtor(*this); } -Sender& Sender::operator=(const Sender& s) { return PI::assign(*this, s); } -void Sender::send(const Message& message, bool sync) { impl->send(message, sync); } -void Sender::close() { impl->close(); } -void Sender::setCapacity(uint32_t c) { impl->setCapacity(c); } -uint32_t Sender::getCapacity() { return impl->getCapacity(); } -uint32_t Sender::getUnsettled() { return impl->getUnsettled(); } -uint32_t Sender::getAvailable() { return getCapacity() - getUnsettled(); } -const std::string& Sender::getName() const { return impl->getName(); } -Session Sender::getSession() const { return impl->getSession(); } - -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/SenderImpl.h b/cpp/src/qpid/messaging/SenderImpl.h deleted file mode 100644 index a1ca02c72c..0000000000 --- a/cpp/src/qpid/messaging/SenderImpl.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_MESSAGING_SENDERIMPL_H -#define QPID_MESSAGING_SENDERIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/RefCounted.h" - -namespace qpid { -namespace messaging { - -class Message; -class Session; - -class SenderImpl : public virtual qpid::RefCounted -{ - public: - virtual ~SenderImpl() {} - virtual void send(const Message& message, bool sync) = 0; - virtual void close() = 0; - virtual void setCapacity(uint32_t) = 0; - virtual uint32_t getCapacity() = 0; - virtual uint32_t getUnsettled() = 0; - virtual const std::string& getName() const = 0; - virtual Session getSession() const = 0; - private: -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_SENDERIMPL_H*/ diff --git a/cpp/src/qpid/messaging/Session.cpp b/cpp/src/qpid/messaging/Session.cpp deleted file mode 100644 index 496953a8e5..0000000000 --- a/cpp/src/qpid/messaging/Session.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/Session.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/SessionImpl.h" -#include "qpid/messaging/PrivateImplRef.h" - -namespace qpid { -namespace messaging { - -typedef PrivateImplRef<qpid::messaging::Session> PI; - -Session::Session(SessionImpl* impl) { PI::ctor(*this, impl); } -Session::Session(const Session& s) : Handle<SessionImpl>() { PI::copy(*this, s); } -Session::~Session() { PI::dtor(*this); } -Session& Session::operator=(const Session& s) { return PI::assign(*this, s); } -void Session::commit() { impl->commit(); } -void Session::rollback() { impl->rollback(); } -void Session::acknowledge(bool sync) { impl->acknowledge(sync); } -void Session::acknowledge(Message& m, bool s) { impl->acknowledge(m); sync(s); } -void Session::reject(Message& m) { impl->reject(m); } -void Session::release(Message& m) { impl->release(m); } -void Session::close() { impl->close(); } - -Sender Session::createSender(const Address& address) -{ - return impl->createSender(address); -} -Receiver Session::createReceiver(const Address& address) -{ - return impl->createReceiver(address); -} - -Sender Session::createSender(const std::string& address) -{ - return impl->createSender(Address(address)); -} -Receiver Session::createReceiver(const std::string& address) -{ - return impl->createReceiver(Address(address)); -} - -void Session::sync(bool block) -{ - impl->sync(block); -} - -bool Session::nextReceiver(Receiver& receiver, Duration timeout) -{ - return impl->nextReceiver(receiver, timeout); -} - - -Receiver Session::nextReceiver(Duration timeout) -{ - return impl->nextReceiver(timeout); -} - -uint32_t Session::getReceivable() { return impl->getReceivable(); } -uint32_t Session::getUnsettledAcks() { return impl->getUnsettledAcks(); } - -Sender Session::getSender(const std::string& name) const -{ - return impl->getSender(name); -} -Receiver Session::getReceiver(const std::string& name) const -{ - return impl->getReceiver(name); -} - -Connection Session::getConnection() const -{ - return impl->getConnection(); -} - -void Session::checkError() { impl->checkError(); } -bool Session::hasError() -{ - try { - checkError(); - return false; - } catch (const std::exception&) { - return true; - } -} - -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/messaging/SessionImpl.h b/cpp/src/qpid/messaging/SessionImpl.h deleted file mode 100644 index 02a254e4f2..0000000000 --- a/cpp/src/qpid/messaging/SessionImpl.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef QPID_MESSAGING_SESSIONIMPL_H -#define QPID_MESSAGING_SESSIONIMPL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/RefCounted.h" -#include <string> -#include "qpid/messaging/Duration.h" - -namespace qpid { -namespace messaging { - -class Address; -class Connection; -class Message; -class Sender; -class Receiver; - -class SessionImpl : public virtual qpid::RefCounted -{ - public: - virtual ~SessionImpl() {} - virtual void commit() = 0; - virtual void rollback() = 0; - virtual void acknowledge(bool sync) = 0; - virtual void acknowledge(Message&) = 0; - virtual void reject(Message&) = 0; - virtual void release(Message&) = 0; - virtual void close() = 0; - virtual void sync(bool block) = 0; - virtual Sender createSender(const Address& address) = 0; - virtual Receiver createReceiver(const Address& address) = 0; - virtual bool nextReceiver(Receiver& receiver, Duration timeout) = 0; - virtual Receiver nextReceiver(Duration timeout) = 0; - virtual uint32_t getReceivable() = 0; - virtual uint32_t getUnsettledAcks() = 0; - virtual Sender getSender(const std::string& name) const = 0; - virtual Receiver getReceiver(const std::string& name) const = 0; - virtual Connection getConnection() const = 0; - virtual void checkError() = 0; - private: -}; -}} // namespace qpid::messaging - -#endif /*!QPID_MESSAGING_SESSIONIMPL_H*/ diff --git a/cpp/src/qpid/messaging/exceptions.cpp b/cpp/src/qpid/messaging/exceptions.cpp deleted file mode 100644 index 5d2683fffe..0000000000 --- a/cpp/src/qpid/messaging/exceptions.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/messaging/exceptions.h" - -namespace qpid { -namespace messaging { - -MessagingException::MessagingException(const std::string& msg) : qpid::types::Exception(msg) {} -MessagingException::~MessagingException() throw() {} - -InvalidOptionString::InvalidOptionString(const std::string& msg) : MessagingException(msg) {} -KeyError::KeyError(const std::string& msg) : MessagingException(msg) {} - - -LinkError::LinkError(const std::string& msg) : MessagingException(msg) {} - -AddressError::AddressError(const std::string& msg) : LinkError(msg) {} -ResolutionError::ResolutionError(const std::string& msg) : AddressError(msg) {} -MalformedAddress::MalformedAddress(const std::string& msg) : AddressError(msg) {} -AssertionFailed::AssertionFailed(const std::string& msg) : ResolutionError(msg) {} -NotFound::NotFound(const std::string& msg) : ResolutionError(msg) {} - -ReceiverError::ReceiverError(const std::string& msg) : LinkError(msg) {} -FetchError::FetchError(const std::string& msg) : ReceiverError(msg) {} -NoMessageAvailable::NoMessageAvailable() : FetchError("No message to fetch") {} - -SenderError::SenderError(const std::string& msg) : LinkError(msg) {} -SendError::SendError(const std::string& msg) : SenderError(msg) {} -TargetCapacityExceeded::TargetCapacityExceeded(const std::string& msg) : SendError(msg) {} - -SessionError::SessionError(const std::string& msg) : MessagingException(msg) {} -TransactionError::TransactionError(const std::string& msg) : SessionError(msg) {} -TransactionAborted::TransactionAborted(const std::string& msg) : TransactionError(msg) {} -UnauthorizedAccess::UnauthorizedAccess(const std::string& msg) : SessionError(msg) {} - -ConnectionError::ConnectionError(const std::string& msg) : MessagingException(msg) {} - -TransportFailure::TransportFailure(const std::string& msg) : MessagingException(msg) {} - -}} // namespace qpid::messaging diff --git a/cpp/src/qpid/pointer_to_other.h b/cpp/src/qpid/pointer_to_other.h deleted file mode 100644 index a99dc89658..0000000000 --- a/cpp/src/qpid/pointer_to_other.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_POINTERTOOTHER_H -#define QPID_POINTERTOOTHER_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -namespace qpid { - -// Defines the same pointer type (raw or smart) to another pointee type - -template<class T, class U> -struct pointer_to_other; - -template<class T, class U, - template<class> class Sp> -struct pointer_to_other< Sp<T>, U > - { - typedef Sp<U> type; - }; - -template<class T, class T2, class U, - template<class, class> class Sp> -struct pointer_to_other< Sp<T, T2>, U > - { - typedef Sp<U, T2> type; - }; - -template<class T, class T2, class T3, class U, - template<class, class, class> class Sp> -struct pointer_to_other< Sp<T, T2, T3>, U > - { - typedef Sp<U, T2, T3> type; - }; - -template<class T, class U> -struct pointer_to_other< T*, U > -{ - typedef U* type; -}; - -} // namespace qpid - - - -#endif /*!QPID_POINTERTOOTHER_H*/ diff --git a/cpp/src/qpid/ptr_map.h b/cpp/src/qpid/ptr_map.h deleted file mode 100644 index 6ffcd48e89..0000000000 --- a/cpp/src/qpid/ptr_map.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QPID_PTR_MAP -#define QPID_PTR_MAP - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/ptr_container/ptr_map.hpp> -#include <boost/utility/enable_if.hpp> -#include <boost/type_traits/is_same.hpp> -#include <boost/type_traits/remove_const.hpp> - -namespace qpid { - -/** @file - * Workaround for API change between boost 1.33 and 1.34. - * - * To be portable across these versions, code using boost::ptr_map - * iterators should use ptr_map_ptr(i) to get the pointer from - * boost::ptr_map::iterator i. - * - * @see http://www.boost.org/libs/ptr_container/doc/ptr_container.html#upgrading-from-boost-v-1-33 - */ - - -typedef boost::is_same<boost::ptr_map<int, int>::iterator::value_type, int> IsOldPtrMap; - -template <class Iter> -typename boost::enable_if<IsOldPtrMap, typename Iter::value_type*>::type -ptr_map_ptr(const Iter& i) { return &*i; } - -template <class Iter> -typename boost::disable_if<IsOldPtrMap, - typename boost::remove_const<typename Iter::value_type::second_type>::type - >::type -ptr_map_ptr(const Iter& i) { return i->second; } - -} // namespace qpid - -#endif /*!QPID_PTR_MAP*/ diff --git a/cpp/src/qpid/replication/ReplicatingEventListener.cpp b/cpp/src/qpid/replication/ReplicatingEventListener.cpp deleted file mode 100644 index b7d52372f4..0000000000 --- a/cpp/src/qpid/replication/ReplicatingEventListener.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/replication/ReplicatingEventListener.h" -#include "qpid/replication/constants.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/QueueEvents.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace replication { - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::replication::constants; - -void ReplicatingEventListener::handle(QueueEvents::Event event) -{ - switch (event.type) { - case QueueEvents::ENQUEUE: - deliverEnqueueMessage(event.msg); - QPID_LOG(debug, "Queuing 'enqueue' event on " << event.msg.queue->getName() << " for replication"); - break; - case QueueEvents::DEQUEUE: - deliverDequeueMessage(event.msg); - QPID_LOG(debug, "Queuing 'dequeue' event from " << event.msg.queue->getName() << " for replication, (from position " - << event.msg.position << ")"); - break; - } -} - -namespace { -const std::string EMPTY; -} - -void ReplicatingEventListener::deliverDequeueMessage(const QueuedMessage& dequeued) -{ - FieldTable headers; - headers.setString(REPLICATION_TARGET_QUEUE, dequeued.queue->getName()); - headers.setInt(REPLICATION_EVENT_TYPE, DEQUEUE); - headers.setInt(DEQUEUED_MESSAGE_POSITION, dequeued.position); - boost::intrusive_ptr<Message> msg(createMessage(headers)); - DeliveryProperties* props = msg->getFrames().getHeaders()->get<DeliveryProperties>(true); - props->setRoutingKey(dequeued.queue->getName()); - route(msg); -} - -void ReplicatingEventListener::deliverEnqueueMessage(const QueuedMessage& enqueued) -{ - boost::intrusive_ptr<Message> msg(cloneMessage(*(enqueued.queue), enqueued.payload)); - FieldTable& headers = msg->getProperties<MessageProperties>()->getApplicationHeaders(); - headers.setString(REPLICATION_TARGET_QUEUE, enqueued.queue->getName()); - headers.setInt(REPLICATION_EVENT_TYPE, ENQUEUE); - headers.setInt(QUEUE_MESSAGE_POSITION,enqueued.position); - route(msg); -} - -void ReplicatingEventListener::route(boost::intrusive_ptr<qpid::broker::Message> msg) -{ - try { - if (exchange) { - DeliverableMessage deliverable(msg); - exchange->route(deliverable, msg->getRoutingKey(), msg->getApplicationHeaders()); - } else if (queue) { - queue->deliver(msg); - } else { - QPID_LOG(error, "Cannot route replication event, neither replication queue nor exchange configured"); - } - } catch (const std::exception& e) { - QPID_LOG(error, "Error enqueing replication event: " << e.what()); - } -} - - -boost::intrusive_ptr<Message> ReplicatingEventListener::createMessage(const FieldTable& headers) -{ - boost::intrusive_ptr<Message> msg(new Message()); - AMQFrame method((MessageTransferBody(ProtocolVersion(), EMPTY, 0, 0))); - AMQFrame header((AMQHeaderBody())); - header.setBof(false); - header.setEof(true); - header.setBos(true); - header.setEos(true); - msg->getFrames().append(method); - msg->getFrames().append(header); - MessageProperties* props = msg->getFrames().getHeaders()->get<MessageProperties>(true); - props->setApplicationHeaders(headers); - return msg; -} - -struct AppendingHandler : FrameHandler -{ - boost::intrusive_ptr<Message> msg; - - AppendingHandler(boost::intrusive_ptr<Message> m) : msg(m) {} - - void handle(AMQFrame& f) - { - msg->getFrames().append(f); - } -}; - -boost::intrusive_ptr<Message> ReplicatingEventListener::cloneMessage(Queue& queue, boost::intrusive_ptr<Message> original) -{ - boost::intrusive_ptr<Message> copy(new Message()); - AMQFrame method((MessageTransferBody(ProtocolVersion(), EMPTY, 0, 0))); - AppendingHandler handler(copy); - handler.handle(method); - - //To avoid modifying original headers, create new frame with - //cloned body: - AMQFrame header(*original->getFrames().getHeaders()); - header.setBof(false); - header.setEof(!original->getFrames().getContentSize());//if there is any content then the header is not the end of the frameset - header.setBos(true); - header.setEos(true); - handler.handle(header); - - original->sendContent(queue, handler, std::numeric_limits<int16_t>::max()); - return copy; -} - -Options* ReplicatingEventListener::getOptions() -{ - return &options; -} - -void ReplicatingEventListener::initialize(Plugin::Target& target) -{ - Broker* broker = dynamic_cast<broker::Broker*>(&target); - if (broker) { - broker->addFinalizer(boost::bind(&ReplicatingEventListener::shutdown, this)); - if (!options.exchange.empty()) { - if (!options.queue.empty()) { - QPID_LOG(warning, "Replication queue option ignored as replication exchange has been specified"); - } - try { - exchange = broker->getExchanges().declare(options.exchange, options.exchangeType).first; - } catch (const UnknownExchangeTypeException&) { - QPID_LOG(error, "Replication disabled due to invalid type: " << options.exchangeType); - } - } else if (!options.queue.empty()) { - if (options.createQueue) { - queue = broker->getQueues().declare(options.queue).first; - } else { - queue = broker->getQueues().find(options.queue); - } - if (queue) { - queue->insertSequenceNumbers(REPLICATION_EVENT_SEQNO); - } else { - QPID_LOG(error, "Replication queue named '" << options.queue << "' does not exist; replication plugin disabled."); - } - } - if (queue || exchange) { - QueueEvents::EventListener callback = boost::bind(&ReplicatingEventListener::handle, this, _1); - broker->getQueueEvents().registerListener(options.name, callback); - QPID_LOG(info, "Registered replicating queue event listener"); - } - } -} - -void ReplicatingEventListener::earlyInitialize(Target&) {} -void ReplicatingEventListener::shutdown() { queue.reset(); exchange.reset(); } - -ReplicatingEventListener::PluginOptions::PluginOptions() : Options("Queue Replication Options"), - exchangeType("direct"), - name("replicator"), - createQueue(false) -{ - addOptions() - ("replication-exchange-name", optValue(exchange, "EXCHANGE"), "Exchange to which events for other queues are routed") - ("replication-exchange-type", optValue(exchangeType, "direct|topic etc"), "Type of exchange to use") - ("replication-queue", optValue(queue, "QUEUE"), "Queue on which events for other queues are recorded") - ("replication-listener-name", optValue(name, "NAME"), "name by which to register the replicating event listener") - ("create-replication-queue", optValue(createQueue), "if set, the replication will be created if it does not exist"); -} - -static ReplicatingEventListener plugin; - -}} // namespace qpid::replication diff --git a/cpp/src/qpid/replication/ReplicatingEventListener.h b/cpp/src/qpid/replication/ReplicatingEventListener.h deleted file mode 100644 index 74418d00e6..0000000000 --- a/cpp/src/qpid/replication/ReplicatingEventListener.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_REPLICATION_REPLICATINGEVENTLISTENER_H -#define QPID_REPLICATION_REPLICATINGEVENTLISTENER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueEvents.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/SequenceNumber.h" - -namespace qpid { -namespace replication { - -/** - * An event listener plugin that records queue events as messages on a - * replication queue, from where they can be consumed (e.g. by an - * inter-broker link to the corresponding QueueReplicationExchange - * plugin. - */ -class ReplicatingEventListener : public Plugin -{ - public: - Options* getOptions(); - void earlyInitialize(Plugin::Target& target); - void initialize(Plugin::Target& target); - void handle(qpid::broker::QueueEvents::Event); - private: - struct PluginOptions : public Options - { - std::string queue; - std::string exchange; - std::string exchangeType; - std::string name; - bool createQueue; - - PluginOptions(); - }; - - PluginOptions options; - qpid::broker::Queue::shared_ptr queue; - qpid::broker::Exchange::shared_ptr exchange; - - void deliverDequeueMessage(const qpid::broker::QueuedMessage& enqueued); - void deliverEnqueueMessage(const qpid::broker::QueuedMessage& enqueued); - void route(boost::intrusive_ptr<qpid::broker::Message>); - void shutdown(); - - boost::intrusive_ptr<qpid::broker::Message> createMessage(const qpid::framing::FieldTable& headers); - boost::intrusive_ptr<qpid::broker::Message> cloneMessage(qpid::broker::Queue& queue, - boost::intrusive_ptr<qpid::broker::Message> original); -}; - -}} // namespace qpid::replication - -#endif /*!QPID_REPLICATION_REPLICATINGEVENTLISTENER_H*/ diff --git a/cpp/src/qpid/replication/ReplicationExchange.cpp b/cpp/src/qpid/replication/ReplicationExchange.cpp deleted file mode 100644 index 4b6d25ac7d..0000000000 --- a/cpp/src/qpid/replication/ReplicationExchange.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/replication/ReplicationExchange.h" -#include "qpid/replication/constants.h" -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace replication { - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::replication::constants; - -const std::string SEQUENCE_VALUE("qpid.replication-event.sequence"); -ReplicationExchange::ReplicationExchange(const std::string& name, bool durable, - const FieldTable& _args, - QueueRegistry& qr, - Manageable* parent, Broker* broker) - : Exchange(name, durable, _args, parent, broker), queues(qr), sequence(args.getAsInt64(SEQUENCE_VALUE)), init(false) -{ - args.setInt64(SEQUENCE_VALUE, sequence); - if (mgmtExchange != 0) - mgmtExchange->set_type(typeName); -} - -std::string ReplicationExchange::getType() const { return typeName; } - -void ReplicationExchange::route(Deliverable& msg, const std::string& /*routingKey*/, const FieldTable* args) -{ - if (mgmtExchange != 0) { - mgmtExchange->inc_msgReceives(); - mgmtExchange->inc_byteReceives(msg.contentSize()); - } - if (args) { - int eventType = args->getAsInt(REPLICATION_EVENT_TYPE); - if (eventType) { - if (isDuplicate(args)) return; - switch (eventType) { - case ENQUEUE: - handleEnqueueEvent(args, msg); - return; - case DEQUEUE: - handleDequeueEvent(args, msg); - return; - default: - throw IllegalArgumentException(QPID_MSG("Illegal value for " << REPLICATION_EVENT_TYPE << ": " << eventType)); - } - } - } else { - QPID_LOG(warning, "Dropping unexpected message with no headers"); - if (mgmtExchange != 0) { - mgmtExchange->inc_msgDrops(); - mgmtExchange->inc_byteDrops(msg.contentSize()); - } - } -} - -void ReplicationExchange::handleEnqueueEvent(const FieldTable* args, Deliverable& msg) -{ - std::string queueName = args->getAsString(REPLICATION_TARGET_QUEUE); - Queue::shared_ptr queue = queues.find(queueName); - if (queue) { - - SequenceNumber seqno1(args->getAsInt(QUEUE_MESSAGE_POSITION)); - - // note that queue will ++ before enqueue. - if (queue->getPosition() > --seqno1) // test queue.pos < seqnumber - { - QPID_LOG(error, "Cannot enqueue replicated message. Destination Queue " << queueName << " ahead of source queue"); - mgmtExchange->inc_msgDrops(); - mgmtExchange->inc_byteDrops(msg.contentSize()); - } else { - queue->setPosition(seqno1); - - FieldTable& headers = msg.getMessage().getProperties<MessageProperties>()->getApplicationHeaders(); - headers.erase(REPLICATION_TARGET_QUEUE); - headers.erase(REPLICATION_EVENT_SEQNO); - headers.erase(REPLICATION_EVENT_TYPE); - headers.erase(QUEUE_MESSAGE_POSITION); - msg.deliverTo(queue); - QPID_LOG(debug, "Enqueued replicated message onto " << queueName); - if (mgmtExchange != 0) { - mgmtExchange->inc_msgRoutes(); - mgmtExchange->inc_byteRoutes( msg.contentSize()); - } - } - } else { - QPID_LOG(error, "Cannot enqueue replicated message. Queue " << queueName << " does not exist"); - if (mgmtExchange != 0) { - mgmtExchange->inc_msgDrops(); - mgmtExchange->inc_byteDrops(msg.contentSize()); - } - } -} - -void ReplicationExchange::handleDequeueEvent(const FieldTable* args, Deliverable& msg) -{ - std::string queueName = args->getAsString(REPLICATION_TARGET_QUEUE); - Queue::shared_ptr queue = queues.find(queueName); - if (queue) { - SequenceNumber position(args->getAsInt(DEQUEUED_MESSAGE_POSITION)); - QueuedMessage dequeued; - if (queue->acquireMessageAt(position, dequeued)) { - queue->dequeue(0, dequeued); - QPID_LOG(debug, "Processed replicated 'dequeue' event from " << queueName << " at position " << position); - if (mgmtExchange != 0) { - mgmtExchange->inc_msgRoutes(); - mgmtExchange->inc_byteRoutes(msg.contentSize()); - } - } else { - QPID_LOG(warning, "Could not acquire message " << position << " from " << queueName); - if (mgmtExchange != 0) { - mgmtExchange->inc_msgDrops(); - mgmtExchange->inc_byteDrops(msg.contentSize()); - } - } - } else { - QPID_LOG(error, "Cannot process replicated 'dequeue' event. Queue " << queueName << " does not exist"); - if (mgmtExchange != 0) { - mgmtExchange->inc_msgDrops(); - mgmtExchange->inc_byteDrops(msg.contentSize()); - } - } -} - -bool ReplicationExchange::isDuplicate(const FieldTable* args) -{ - if (!args->get(REPLICATION_EVENT_SEQNO)) return false; - SequenceNumber seqno(args->getAsInt(REPLICATION_EVENT_SEQNO)); - if (!init) { - init = true; - sequence = seqno; - return false; - } else if (seqno > sequence) { - if (seqno - sequence > 1) { - QPID_LOG(error, "Gap in replication event sequence between: " << sequence << " and " << seqno); - } - sequence = seqno; - return false; - } else { - QPID_LOG(info, "Duplicate detected: seqno=" << seqno << " (last seqno=" << sequence << ")"); - return true; - } -} - -bool ReplicationExchange::bind(Queue::shared_ptr /*queue*/, const std::string& /*routingKey*/, const FieldTable* /*args*/) -{ - throw NotImplementedException("Replication exchange does not support bind operation"); -} - -bool ReplicationExchange::unbind(Queue::shared_ptr /*queue*/, const std::string& /*routingKey*/, const FieldTable* /*args*/) -{ - throw NotImplementedException("Replication exchange does not support unbind operation"); -} - -bool ReplicationExchange::isBound(Queue::shared_ptr /*queue*/, const string* const /*routingKey*/, const FieldTable* const /*args*/) -{ - return false; -} - -const std::string ReplicationExchange::typeName("replication"); - - -void ReplicationExchange::encode(Buffer& buffer) const -{ - args.setInt64(std::string(SEQUENCE_VALUE), sequence); - Exchange::encode(buffer); -} - - -struct ReplicationExchangePlugin : Plugin -{ - Broker* broker; - - ReplicationExchangePlugin(); - void earlyInitialize(Plugin::Target& target); - void initialize(Plugin::Target& target); - Exchange::shared_ptr create(const std::string& name, bool durable, - const framing::FieldTable& args, - management::Manageable* parent, - qpid::broker::Broker* broker); -}; - -ReplicationExchangePlugin::ReplicationExchangePlugin() : broker(0) {} - -Exchange::shared_ptr ReplicationExchangePlugin::create(const std::string& name, bool durable, - const framing::FieldTable& args, - management::Manageable* parent, qpid::broker::Broker* broker) -{ - Exchange::shared_ptr e(new ReplicationExchange(name, durable, args, broker->getQueues(), parent, broker)); - return e; -} - - -void ReplicationExchangePlugin::earlyInitialize(Plugin::Target& target) -{ - broker = dynamic_cast<broker::Broker*>(&target); - if (broker) { - ExchangeRegistry::FactoryFunction f = boost::bind(&ReplicationExchangePlugin::create, this, _1, _2, _3, _4, _5); - broker->getExchanges().registerType(ReplicationExchange::typeName, f); - QPID_LOG(info, "Registered replication exchange"); - } -} - -void ReplicationExchangePlugin::initialize(Target&) {} - -static ReplicationExchangePlugin exchangePlugin; - -}} // namespace qpid::replication diff --git a/cpp/src/qpid/replication/ReplicationExchange.h b/cpp/src/qpid/replication/ReplicationExchange.h deleted file mode 100644 index 4b34e0df13..0000000000 --- a/cpp/src/qpid/replication/ReplicationExchange.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef QPID_REPLICATION_REPLICATIONEXCHANGE_H -#define QPID_REPLICATION_REPLICATIONEXCHANGE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Exchange.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/SequenceNumber.h" - -namespace qpid { - -namespace broker { -class QueueRegistry; -} - -namespace replication { - -/** - * A custom exchange plugin that processes incoming messages - * representing enqueue or dequeue events for particular queues and - * carries out the corresponding action to replicate that on the local - * broker. - */ -class ReplicationExchange : public qpid::broker::Exchange -{ - public: - static const std::string typeName; - - ReplicationExchange(const std::string& name, bool durable, - const qpid::framing::FieldTable& args, - qpid::broker::QueueRegistry& queues, - qpid::management::Manageable* parent = 0, - qpid::broker::Broker* broker = 0); - - std::string getType() const; - - void route(qpid::broker::Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args); - - bool bind(boost::shared_ptr<broker::Queue> queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - bool unbind(boost::shared_ptr<broker::Queue> queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - bool isBound(boost::shared_ptr<broker::Queue> queue, const std::string* const routingKey, const qpid::framing::FieldTable* const args); - private: - qpid::broker::QueueRegistry& queues; - qpid::framing::SequenceNumber sequence; - bool init; - - bool isDuplicate(const qpid::framing::FieldTable* args); - void handleEnqueueEvent(const qpid::framing::FieldTable* args, qpid::broker::Deliverable& msg); - void handleDequeueEvent(const qpid::framing::FieldTable* args, qpid::broker::Deliverable& msg); - void encode(framing::Buffer& buffer) const; -}; -}} // namespace qpid::replication - -#endif /*!QPID_REPLICATION_REPLICATIONEXCHANGE_H*/ diff --git a/cpp/src/qpid/replication/constants.h b/cpp/src/qpid/replication/constants.h deleted file mode 100644 index c5ba7d3d6a..0000000000 --- a/cpp/src/qpid/replication/constants.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -namespace qpid { -namespace replication { -namespace constants { - -const std::string REPLICATION_EVENT_TYPE("qpid.replication.type"); -const std::string REPLICATION_EVENT_SEQNO("qpid.replication.seqno"); -const std::string REPLICATION_TARGET_QUEUE("qpid.replication.target_queue"); -const std::string DEQUEUED_MESSAGE_POSITION("qpid.replication.message"); -const std::string QUEUE_MESSAGE_POSITION("qpid.replication.queue.position"); - -const int ENQUEUE(1); -const int DEQUEUE(2); - -}}} diff --git a/cpp/src/qpid/store/CMakeLists.txt b/cpp/src/qpid/store/CMakeLists.txt deleted file mode 100644 index 464d2de052..0000000000 --- a/cpp/src/qpid/store/CMakeLists.txt +++ /dev/null @@ -1,111 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -project(qpidc_store) - -#set (CMAKE_VERBOSE_MAKEFILE ON) # for debugging - -include_directories( ${Boost_INCLUDE_DIR} ) - -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -include_directories( ${CMAKE_HOME_DIRECTORY}/include ) - -link_directories( ${Boost_LIBRARY_DIRS} ) - -set (store_SOURCES - MessageStorePlugin.cpp - ) -add_library (store MODULE ${store_SOURCES}) -target_link_libraries (store qpidbroker ${Boost_PROGRAM_OPTIONS_LIBRARY}) -if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties (store PROPERTIES - PREFIX "" - LINK_FLAGS -Wl,--no-undefined) -endif (CMAKE_COMPILER_IS_GNUCXX) - -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - if (MSVC) - add_definitions( - /D "NOMINMAX" - /D "WIN32_LEAN_AND_MEAN" - ) - endif (MSVC) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -set_target_properties (store PROPERTIES VERSION ${qpidc_version}) -install (TARGETS store # RUNTIME - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - -# Build the MS SQL Storage Provider plugin -set (mssql_default ON) -if (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) - set(mssql_default OFF) -endif (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) -option(BUILD_MSSQL "Build MS SQL Store provider plugin" ${mssql_default}) -if (BUILD_MSSQL) - add_library (mssql_store MODULE - ms-sql/MsSqlProvider.cpp - ms-sql/AmqpTransaction.cpp - ms-sql/BindingRecordset.cpp - ms-sql/BlobAdapter.cpp - ms-sql/BlobEncoder.cpp - ms-sql/BlobRecordset.cpp - ms-sql/DatabaseConnection.cpp - ms-sql/MessageMapRecordset.cpp - ms-sql/MessageRecordset.cpp - ms-sql/Recordset.cpp - ms-sql/SqlTransaction.cpp - ms-sql/State.cpp - ms-sql/TplRecordset.cpp - ms-sql/VariantHelper.cpp) - target_link_libraries (mssql_store qpidbroker qpidcommon ${Boost_PROGRAM_OPTIONS_LIBRARY}) - install (TARGETS mssql_store # RUNTIME - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) -endif (BUILD_MSSQL) - -# Build the MS SQL-CLFS Storage Provider plugin -set (msclfs_default ON) -if (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) - set(msclfs_default OFF) -endif (NOT CMAKE_SYSTEM_NAME STREQUAL Windows) -option(BUILD_MSCLFS "Build MS hybrid SQL-CLFS Store provider plugin" ${msclfs_default}) -if (BUILD_MSCLFS) - add_library (msclfs_store MODULE - ms-clfs/MsSqlClfsProvider.cpp - ms-clfs/Log.cpp - ms-clfs/MessageLog.cpp - ms-clfs/Messages.cpp - ms-clfs/Transaction.cpp - ms-clfs/TransactionLog.cpp - ms-sql/BindingRecordset.cpp - ms-sql/BlobAdapter.cpp - ms-sql/BlobEncoder.cpp - ms-sql/BlobRecordset.cpp - ms-sql/DatabaseConnection.cpp - ms-sql/Recordset.cpp - ms-sql/State.cpp - ms-sql/VariantHelper.cpp) - include_directories(ms-sql) - target_link_libraries (msclfs_store qpidbroker qpidcommon ${Boost_PROGRAM_OPTIONS_LIBRARY} clfsw32.lib) - install (TARGETS msclfs_store # RUNTIME - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) -endif (BUILD_MSCLFS) diff --git a/cpp/src/qpid/store/MessageStorePlugin.cpp b/cpp/src/qpid/store/MessageStorePlugin.cpp deleted file mode 100644 index 2a8d971987..0000000000 --- a/cpp/src/qpid/store/MessageStorePlugin.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "MessageStorePlugin.h" -#include "StorageProvider.h" -#include "StoreException.h" -#include "qpid/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/DataDir.h" -#include "qpid/log/Statement.h" - -/* - * The MessageStore pointer given to the Broker points to static storage. - * Thus, it cannot be deleted, especially by the broker. To prevent deletion, - * this no-op deleter is used with the boost::shared_ptr. When the last - * shared_ptr is destroyed, the deleter is called rather than delete(). - */ -namespace { - class NoopDeleter { - public: - NoopDeleter() {} - void operator()(qpid::broker::MessageStore * /*p*/) {} - }; -} - -namespace qpid { -namespace store { - -static MessageStorePlugin static_instance_registers_plugin; - - -MessageStorePlugin::StoreOptions::StoreOptions(const std::string& name) : - qpid::Options(name) -{ - addOptions() - ("storage-provider", qpid::optValue(providerName, "PROVIDER"), - "Name of the storage provider to use.") - ; -} - - -void -MessageStorePlugin::earlyInitialize (qpid::Plugin::Target& target) -{ - qpid::broker::Broker* b = - dynamic_cast<qpid::broker::Broker*>(&target); - if (0 == b) - return; // Only listen to Broker targets - - broker = b; - - // See if there are any storage provider plugins ready. If not, we can't - // do a message store. - qpid::Plugin::earlyInitAll(*this); - - if (providers.empty()) { - QPID_LOG(warning, - "Message store plugin: No storage providers available."); - provider = providers.end(); - return; - } - if (!options.providerName.empty()) { - // If specific one was chosen, locate it in loaded set of providers. - provider = providers.find(options.providerName); - if (provider == providers.end()) - throw Exception("Message store plugin: storage provider '" + - options.providerName + - "' does not exist."); - } - else { - // No specific provider chosen; if there's only one, use it. Else - // report the need to pick one. - if (providers.size() > 1) { - provider = providers.end(); - throw Exception("Message store plugin: multiple provider plugins " - "loaded; must either load only one or select one " - "using --storage-provider"); - } - provider = providers.begin(); - } - - provider->second->activate(*this); - NoopDeleter d; - boost::shared_ptr<qpid::broker::MessageStore> sp(this, d); - broker->setStore(sp); - target.addFinalizer(boost::bind(&MessageStorePlugin::finalizeMe, this)); -} - -void -MessageStorePlugin::initialize(qpid::Plugin::Target& target) -{ - qpid::broker::Broker* broker = - dynamic_cast<qpid::broker::Broker*>(&target); - if (0 == broker) - return; // Only listen to Broker targets - - // Pass along the initialize step to the provider that's activated. - if (provider != providers.end()) { - provider->second->initialize(*this); - } - // qpid::Plugin::initializeAll(*this); -} - -void -MessageStorePlugin::finalizeMe() -{ - finalize(); // Call finalizers on any Provider plugins -} - -void -MessageStorePlugin::providerAvailable(const std::string name, - StorageProvider *be) -{ - ProviderMap::value_type newSp(name, be); - std::pair<ProviderMap::iterator, bool> inserted = providers.insert(newSp); - if (inserted.second == false) - QPID_LOG(warning, "Storage provider " << name << " duplicate; ignored."); -} - -void -MessageStorePlugin::truncateInit(const bool /*saveStoreContent*/) -{ - QPID_LOG(info, "Store: truncateInit"); -} - - -/** - * Record the existence of a durable queue - */ -void -MessageStorePlugin::create(broker::PersistableQueue& queue, - const framing::FieldTable& args) -{ - if (queue.getName().size() == 0) - { - QPID_LOG(error, - "Cannot create store for empty (null) queue name - " - "ignoring and attempting to continue."); - return; - } - if (queue.getPersistenceId()) { - THROW_STORE_EXCEPTION("Queue already created: " + queue.getName()); - } - provider->second->create(queue, args); -} - -/** - * Destroy a durable queue - */ -void -MessageStorePlugin::destroy(broker::PersistableQueue& queue) -{ - provider->second->destroy(queue); -} - -/** - * Record the existence of a durable exchange - */ -void -MessageStorePlugin::create(const broker::PersistableExchange& exchange, - const framing::FieldTable& args) -{ - if (exchange.getPersistenceId()) { - THROW_STORE_EXCEPTION("Exchange already created: " + exchange.getName()); - } - provider->second->create(exchange, args); -} - -/** - * Destroy a durable exchange - */ -void -MessageStorePlugin::destroy(const broker::PersistableExchange& exchange) -{ - provider->second->destroy(exchange); -} - -/** - * Record a binding - */ -void -MessageStorePlugin::bind(const broker::PersistableExchange& exchange, - const broker::PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args) -{ - provider->second->bind(exchange, queue, key, args); -} - -/** - * Forget a binding - */ -void -MessageStorePlugin::unbind(const broker::PersistableExchange& exchange, - const broker::PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args) -{ - provider->second->unbind(exchange, queue, key, args); -} - -/** - * Record generic durable configuration - */ -void -MessageStorePlugin::create(const broker::PersistableConfig& config) -{ - if (config.getPersistenceId()) { - THROW_STORE_EXCEPTION("Config item already created: " + - config.getName()); - } - provider->second->create(config); -} - -/** - * Destroy generic durable configuration - */ -void -MessageStorePlugin::destroy(const broker::PersistableConfig& config) -{ - provider->second->destroy(config); -} - -/** - * Stores a message before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). - */ -void -MessageStorePlugin::stage(const boost::intrusive_ptr<broker::PersistableMessage>& msg) -{ - if (msg->getPersistenceId() == 0 && !msg->isContentReleased()) { - provider->second->stage(msg); - } -} - -/** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ -void -MessageStorePlugin::destroy(broker::PersistableMessage& msg) -{ - if (msg.getPersistenceId()) - provider->second->destroy(msg); -} - -/** - * Appends content to a previously staged message - */ -void -MessageStorePlugin::appendContent - (const boost::intrusive_ptr<const broker::PersistableMessage>& msg, - const std::string& data) -{ - if (msg->getPersistenceId()) - provider->second->appendContent(msg, data); - else - THROW_STORE_EXCEPTION("Cannot append content. Message not known to store!"); -} - -/** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ -void -MessageStorePlugin::loadContent(const broker::PersistableQueue& queue, - const boost::intrusive_ptr<const broker::PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length) -{ - if (msg->getPersistenceId()) - provider->second->loadContent(queue, msg, data, offset, length); - else - THROW_STORE_EXCEPTION("Cannot load content. Message not known to store!"); -} - -/** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - */ -void -MessageStorePlugin::enqueue(broker::TransactionContext* ctxt, - const boost::intrusive_ptr<broker::PersistableMessage>& msg, - const broker::PersistableQueue& queue) -{ - if (queue.getPersistenceId() == 0) { - THROW_STORE_EXCEPTION("Queue not created: " + queue.getName()); - } - provider->second->enqueue(ctxt, msg, queue); -} - -/** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - */ -void -MessageStorePlugin::dequeue(broker::TransactionContext* ctxt, - const boost::intrusive_ptr<broker::PersistableMessage>& msg, - const broker::PersistableQueue& queue) -{ - provider->second->dequeue(ctxt, msg, queue); -} - -/** - * Flushes all async messages to disk for the specified queue - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - */ -void -MessageStorePlugin::flush(const broker::PersistableQueue& queue) -{ - provider->second->flush(queue); -} - -/** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk. - */ -uint32_t -MessageStorePlugin::outstandingQueueAIO(const broker::PersistableQueue& queue) -{ - return provider->second->outstandingQueueAIO(queue); -} - -std::auto_ptr<broker::TransactionContext> -MessageStorePlugin::begin() -{ - return provider->second->begin(); -} - -std::auto_ptr<broker::TPCTransactionContext> -MessageStorePlugin::begin(const std::string& xid) -{ - return provider->second->begin(xid); -} - -void -MessageStorePlugin::prepare(broker::TPCTransactionContext& ctxt) -{ - provider->second->prepare(ctxt); -} - -void -MessageStorePlugin::commit(broker::TransactionContext& ctxt) -{ - provider->second->commit(ctxt); -} - -void -MessageStorePlugin::abort(broker::TransactionContext& ctxt) -{ - provider->second->abort(ctxt); -} - -void -MessageStorePlugin::collectPreparedXids(std::set<std::string>& xids) -{ - provider->second->collectPreparedXids(xids); -} - -/** - * Request recovery of queue and message state; inherited from Recoverable - */ -void -MessageStorePlugin::recover(broker::RecoveryManager& recoverer) -{ - ExchangeMap exchanges; - QueueMap queues; - MessageMap messages; - MessageQueueMap messageQueueMap; - std::vector<std::string> xids; - PreparedTransactionMap dtxMap; - - provider->second->recoverConfigs(recoverer); - provider->second->recoverExchanges(recoverer, exchanges); - provider->second->recoverQueues(recoverer, queues); - provider->second->recoverBindings(recoverer, exchanges, queues); - // Important to recover messages before transactions in the SQL-CLFS - // case. If this becomes a problem, it may be possible to resolve it. - // If in doubt please raise a jira and notify Steve Huston - // <shuston@riverace.com>. - provider->second->recoverMessages(recoverer, messages, messageQueueMap); - provider->second->recoverTransactions(recoverer, dtxMap); - // Enqueue msgs where needed. - for (MessageQueueMap::const_iterator i = messageQueueMap.begin(); - i != messageQueueMap.end(); - ++i) { - // Locate the message corresponding to the current message Id - MessageMap::const_iterator iMsg = messages.find(i->first); - if (iMsg == messages.end()) { - std::ostringstream oss; - oss << "No matching message trying to re-enqueue message " - << i->first; - THROW_STORE_EXCEPTION(oss.str()); - } - broker::RecoverableMessage::shared_ptr msg = iMsg->second; - // Now for each queue referenced in the queue map, locate it - // and re-enqueue the message. - for (std::vector<QueueEntry>::const_iterator j = i->second.begin(); - j != i->second.end(); - ++j) { - // Locate the queue corresponding to the current queue Id - QueueMap::const_iterator iQ = queues.find(j->queueId); - if (iQ == queues.end()) { - std::ostringstream oss; - oss << "No matching queue trying to re-enqueue message " - << " on queue Id " << j->queueId; - THROW_STORE_EXCEPTION(oss.str()); - } - // Messages involved in prepared transactions have their status - // updated accordingly. First, though, restore a message that - // is expected to be on a queue, including non-transacted - // messages and those pending dequeue in a dtx. - if (j->tplStatus != QueueEntry::ADDING) - iQ->second->recover(msg); - switch(j->tplStatus) { - case QueueEntry::ADDING: - dtxMap[j->xid]->enqueue(iQ->second, msg); - break; - case QueueEntry::REMOVING: - dtxMap[j->xid]->dequeue(iQ->second, msg); - break; - default: - break; - } - } - } -} - -}} // namespace qpid::store diff --git a/cpp/src/qpid/store/MessageStorePlugin.h b/cpp/src/qpid/store/MessageStorePlugin.h deleted file mode 100644 index 4a9bb2aecb..0000000000 --- a/cpp/src/qpid/store/MessageStorePlugin.h +++ /dev/null @@ -1,288 +0,0 @@ -#ifndef QPID_STORE_MESSAGESTOREPLUGIN_H -#define QPID_STORE_MESSAGESTOREPLUGIN_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/PersistableExchange.h" -#include "qpid/broker/PersistableMessage.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/management/Manageable.h" - -#include <string> - -using namespace qpid; - -namespace qpid { -namespace store { - -class StorageProvider; - -/** - * @class MessageStorePlugin - * - * MessageStorePlugin is the front end of the persistent message store - * plugin. It is responsible for coordinating recovery, initialization, - * transactions (both local and distributed), flow-to-disk loading and - * unloading and persisting broker state (queues, bindings etc.). - * Actual storage operations are carried out by a message store storage - * provider that implements the qpid::store::StorageProvider interface. - */ -class MessageStorePlugin : - public qpid::Plugin, - public qpid::broker::MessageStore, // Frontend classes - public qpid::Plugin::Target // Provider target - // @TODO Need a mgmt story for this. Maybe allow r/o access to provider store info? public qpid::management::Manageable -{ - public: - MessageStorePlugin() : broker(0) {} - - /** - * @name Methods inherited from qpid::Plugin - */ - //@{ - virtual Options* getOptions() { return &options; } - virtual void earlyInitialize (Plugin::Target& target); - virtual void initialize(Plugin::Target& target); - //@} - - /// Finalizer; calls Target::finalize() to run finalizers on - /// StorageProviders. - void finalizeMe(); - - /** - * Called by StorageProvider instances during the earlyInitialize sequence. - * Each StorageProvider must supply a unique name by which it is known and a - * pointer to itself. - */ - virtual void providerAvailable(const std::string name, StorageProvider *be); - - /** - * @name Methods inherited from qpid::broker::MessageStore - */ - //@{ - /** - * If called before recovery, will discard the database and reinitialize - * using an empty store. This is used when cluster nodes recover and - * must get their content from a cluster sync rather than directly from - * the store. - * - * @param saveStoreContent If true, the store's contents should be - * saved to a backup location before - * reinitializing the store content. - */ - virtual void truncateInit(const bool saveStoreContent = false); - - /** - * Record the existence of a durable queue - */ - virtual void create(broker::PersistableQueue& queue, - const framing::FieldTable& args); - /** - * Destroy a durable queue - */ - virtual void destroy(broker::PersistableQueue& queue); - - /** - * Record the existence of a durable exchange - */ - virtual void create(const broker::PersistableExchange& exchange, - const framing::FieldTable& args); - /** - * Destroy a durable exchange - */ - virtual void destroy(const broker::PersistableExchange& exchange); - - /** - * Record a binding - */ - virtual void bind(const broker::PersistableExchange& exchange, - const broker::PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - - /** - * Forget a binding - */ - virtual void unbind(const broker::PersistableExchange& exchange, - const broker::PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - - /** - * Record generic durable configuration - */ - virtual void create(const broker::PersistableConfig& config); - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const broker::PersistableConfig& config); - - /** - * Stores a message before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr<broker::PersistableMessage>& msg); - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(broker::PersistableMessage& msg); - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr<const broker::PersistableMessage>& msg, - const std::string& data); - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const broker::PersistableQueue& queue, - const boost::intrusive_ptr<const broker::PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(broker::TransactionContext* ctxt, - const boost::intrusive_ptr<broker::PersistableMessage>& msg, - const broker::PersistableQueue& queue); - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(broker::TransactionContext* ctxt, - const boost::intrusive_ptr<broker::PersistableMessage>& msg, - const broker::PersistableQueue& queue); - - /** - * Flushes all async messages to disk for the specified queue - * - * - * Note: The operation is asynchronous so the return of this function does - * not mean the operation is complete. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const broker::PersistableQueue& queue); - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const broker::PersistableQueue& queue); - //@} - - /** - * @name Methods inherited from qpid::broker::TransactionalStore - */ - //@{ - std::auto_ptr<broker::TransactionContext> begin(); - - std::auto_ptr<broker::TPCTransactionContext> begin(const std::string& xid); - - void prepare(broker::TPCTransactionContext& ctxt); - - void commit(broker::TransactionContext& ctxt); - - void abort(broker::TransactionContext& ctxt); - - void collectPreparedXids(std::set<std::string>& xids); - //@} - - /** - * Request recovery of queue and message state; inherited from Recoverable - */ - virtual void recover(broker::RecoveryManager& recoverer); - - // inline management::Manageable::status_t ManagementMethod (uint32_t, management::Args&, std::string&) - // { return management::Manageable::STATUS_OK; } - - // So storage provider can get the broker info. - broker::Broker *getBroker() { return broker; } - - protected: - - struct StoreOptions : public qpid::Options { - StoreOptions(const std::string& name="Store Options"); - std::string providerName; - }; - StoreOptions options; - - typedef std::map<const std::string, StorageProvider*> ProviderMap; - ProviderMap providers; - ProviderMap::const_iterator provider; - - broker::Broker *broker; - -}; // class MessageStoreImpl - -}} // namespace qpid::store - -#endif /* QPID_SERIALIZER_H */ diff --git a/cpp/src/qpid/store/StorageProvider.h b/cpp/src/qpid/store/StorageProvider.h deleted file mode 100644 index bc8d187517..0000000000 --- a/cpp/src/qpid/store/StorageProvider.h +++ /dev/null @@ -1,343 +0,0 @@ -#ifndef QPID_STORE_STORAGEPROVIDER_H -#define QPID_STORE_STORAGEPROVIDER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <map> -#include <stdexcept> -#include <vector> -#include "qpid/Exception.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include "qpid/broker/MessageStore.h" - -using qpid::broker::PersistableConfig; -using qpid::broker::PersistableExchange; -using qpid::broker::PersistableMessage; -using qpid::broker::PersistableQueue; - -namespace qpid { -namespace store { - -typedef std::map<uint64_t, qpid::broker::RecoverableExchange::shared_ptr> - ExchangeMap; -typedef std::map<uint64_t, qpid::broker::RecoverableQueue::shared_ptr> - QueueMap; -typedef std::map<uint64_t, qpid::broker::RecoverableMessage::shared_ptr> - MessageMap; -// Msg Id -> vector of queue entries where message is queued -struct QueueEntry { - enum TplStatus { NONE = 0, ADDING = 1, REMOVING = 2 }; - uint64_t queueId; - TplStatus tplStatus; - std::string xid; - - QueueEntry(uint64_t id, TplStatus tpl = NONE, const std::string& x = "") - : queueId(id), tplStatus(tpl), xid(x) {} - - bool operator==(const QueueEntry& rhs) { - if (queueId != rhs.queueId) return false; - if (tplStatus == NONE && rhs.tplStatus == NONE) return true; - return xid == rhs.xid; - } -}; -typedef std::map<uint64_t, std::vector<QueueEntry> > MessageQueueMap; -typedef std::map<std::string, qpid::broker::RecoverableTransaction::shared_ptr> - PreparedTransactionMap; - -class MessageStorePlugin; - -/** - * @class StorageProvider - * - * StorageProvider defines the interface for the storage provider plugin to the - * Qpid broker persistence store plugin. - * - * @TODO Should StorageProvider also inherit from MessageStore? If so, then - * maybe remove Recoverable from MessageStore's inheritance and move it - * to MessageStorePlugin? In any event, somehow the discardInit() feature - * needs to get added here. - */ -class StorageProvider : public qpid::Plugin, public qpid::broker::MessageStore -{ -public: - - class Exception : public qpid::Exception - { - public: - virtual ~Exception() throw() {} - virtual const char *what() const throw() = 0; - }; - - /** - * @name Methods inherited from qpid::Plugin - */ - //@{ - /** - * Return a pointer to the provider's options. The options will be - * updated during option parsing by the host program; therefore, the - * referenced Options object must remain valid past this function's return. - * - * @return An options group or 0 for no options. Default returns 0. - * Plugin retains ownership of return value. - */ - virtual qpid::Options* getOptions() = 0; - - /** - * Initialize Plugin functionality on a Target, called before - * initializing the target. - * - * StorageProviders should respond only to Targets of class - * qpid::store::MessageStorePlugin and ignore all others. - * - * When called, the provider should invoke the method - * qpid::store::MessageStorePlugin::providerAvailable() to alert the - * message store of StorageProvider's availability. - * - * Called before the target itself is initialized. - */ - virtual void earlyInitialize (Plugin::Target& target) = 0; - - /** - * Initialize StorageProvider functionality. Called after initializing - * the target. - * - * StorageProviders should respond only to Targets of class - * qpid::store::MessageStorePlugin and ignore all others. - * - * Called after the target is fully initialized. - */ - virtual void initialize(Plugin::Target& target) = 0; - //@} - - /** - * Receive notification that this provider is the one that will actively - * handle storage for the target. If the provider is to be used, this - * method will be called after earlyInitialize() and before any - * recovery operations (recovery, in turn, precedes call to initialize()). - * Thus, it is wise to not actually do any database ops from within - * earlyInitialize() - they can wait until activate() is called because - * at that point it is certain the database will be needed. - */ - virtual void activate(MessageStorePlugin &store) = 0; - - /** - * @name Methods inherited from qpid::broker::MessageStore - */ - //@{ - /** - * If called after init() but before recovery, will discard the database - * and reinitialize using an empty store dir. If @a pushDownStoreFiles - * is true, the content of the store dir will be moved to a backup dir - * inside the store dir. This is used when cluster nodes recover and must - * get thier content from a cluster sync rather than directly fromt the - * store. - * - * @param pushDownStoreFiles If true, will move content of the store dir - * into a subdir, leaving the store dir - * otherwise empty. - */ - virtual void truncateInit(const bool pushDownStoreFiles = false) = 0; - - /** - * Record the existence of a durable queue - */ - virtual void create(PersistableQueue& queue, - const qpid::framing::FieldTable& args) = 0; - /** - * Destroy a durable queue - */ - virtual void destroy(PersistableQueue& queue) = 0; - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args) = 0; - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange) = 0; - - /** - * Record a binding - */ - virtual void bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) = 0; - - /** - * Forget a binding - */ - virtual void unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) = 0; - - /** - * Record generic durable configuration - */ - virtual void create(const PersistableConfig& config) = 0; - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const PersistableConfig& config) = 0; - - /** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr<PersistableMessage>& msg) = 0; - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(PersistableMessage& msg) = 0; - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const std::string& data) = 0; - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const PersistableQueue& queue, - const boost::intrusive_ptr<const PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length) = 0; - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) = 0; - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) = 0; - - /** - * Flushes all async messages to disk for the specified queue - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const qpid::broker::PersistableQueue& queue) = 0; - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue) = 0; - //@} - - /** - * @TODO This should probably not be here - it's only here because - * MessageStore inherits from Recoverable... maybe move that derivation. - * - * As it is now, we don't use this. Separate recover methods are - * declared below for individual types, which also set up maps of - * messages, queues, transactions for the main store plugin to handle - * properly. - * - * Request recovery of queue and message state. - */ - virtual void recover(qpid::broker::RecoveryManager& /*recoverer*/) {} - - /** - * @name Methods that do the recovery of the various objects that - * were saved. - */ - //@{ - - /** - * Recover bindings. - */ - virtual void recoverConfigs(qpid::broker::RecoveryManager& recoverer) = 0; - virtual void recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap) = 0; - virtual void recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap) = 0; - virtual void recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap) = 0; - virtual void recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap) = 0; - virtual void recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap) = 0; - //@} -}; - -}} // namespace qpid::store - -#endif /* QPID_STORE_STORAGEPROVIDER_H */ diff --git a/cpp/src/qpid/store/StoreException.h b/cpp/src/qpid/store/StoreException.h deleted file mode 100644 index 1dc7f670ec..0000000000 --- a/cpp/src/qpid/store/StoreException.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef QPID_STORE_STOREEXCEPTION_H -#define QPID_STORE_STOREEXCEPTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <exception> -#include <boost/format.hpp> -#include "StorageProvider.h" - -namespace qpid { -namespace store { - -class StoreException : public std::exception -{ - std::string text; -public: - StoreException(const std::string& _text) : text(_text) {} - StoreException(const std::string& _text, - const StorageProvider::Exception& cause) - : text(_text + ": " + cause.what()) {} - virtual ~StoreException() throw() {} - virtual const char* what() const throw() { return text.c_str(); } -}; - -#define THROW_STORE_EXCEPTION(MESSAGE) throw qpid::store::StoreException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__)) -#define THROW_STORE_EXCEPTION_2(MESSAGE, EXCEPTION) throw qpid::store::StoreException(boost::str(boost::format("%s (%s:%d)") % (MESSAGE) % __FILE__ % __LINE__), EXCEPTION) - -}} // namespace qpid::store - -#endif /* QPID_STORE_STOREEXCEPTION_H */ diff --git a/cpp/src/qpid/store/ms-clfs/Log.cpp b/cpp/src/qpid/store/ms-clfs/Log.cpp deleted file mode 100644 index e6cb10c133..0000000000 --- a/cpp/src/qpid/store/ms-clfs/Log.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <windows.h> -#include <clfsw32.h> -#include <clfsmgmtw32.h> -#include <sstream> -#include <string> -#include <vector> -#include <stdlib.h> -#include <qpid/sys/windows/check.h> - -#include "Log.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -Log::~Log() -{ - if (marshal != 0) - ::DeleteLogMarshallingArea(marshal); - ::CloseHandle(handle); -} - -void -Log::open(const std::string& path, const TuningParameters& params) -{ - this->containerSize = static_cast<ULONGLONG>(params.containerSize); - logPath = path; - std::string logSpec = "log:" + path; - size_t specLength = logSpec.length(); - std::auto_ptr<wchar_t> wLogSpec(new wchar_t[specLength + 1]); - size_t converted; - mbstowcs_s(&converted, - wLogSpec.get(), specLength+1, - logSpec.c_str(), specLength); - handle = ::CreateLogFile(wLogSpec.get(), - GENERIC_WRITE | GENERIC_READ, - 0, - 0, - OPEN_ALWAYS, - 0); - QPID_WINDOWS_CHECK_NOT(handle, INVALID_HANDLE_VALUE); - CLFS_INFORMATION info; - ULONG infoSize = sizeof(info); - BOOL ok = ::GetLogFileInformation(handle, &info, &infoSize); - QPID_WINDOWS_CHECK_NOT(ok, 0); - ok = ::RegisterManageableLogClient(handle, 0); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - // Set up policies for how many containers to initially create and how - // large each container should be. Also, auto-grow the log when container - // space runs out. - CLFS_MGMT_POLICY logPolicy; - logPolicy.Version = CLFS_MGMT_POLICY_VERSION; - logPolicy.LengthInBytes = sizeof(logPolicy); - logPolicy.PolicyFlags = 0; - - // If this is the first time this log is opened, give an opportunity to - // initialize its content. - bool needInitialize(false); - if (info.TotalContainers == 0) { - // New log; set the configured container size and create the - // initial set of containers. - logPolicy.PolicyType = ClfsMgmtPolicyNewContainerSize; - logPolicy.PolicyParameters.NewContainerSize.SizeInBytes = containerSize; - ok = ::InstallLogPolicy(handle, &logPolicy); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - ULONGLONG desired(params.containers), actual(0); - ok = ::SetLogFileSizeWithPolicy(handle, &desired, &actual); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - needInitialize = true; - } - // Ensure that the log is extended as needed and will shrink when 50% - // becomes unused. - logPolicy.PolicyType = ClfsMgmtPolicyAutoGrow; - logPolicy.PolicyParameters.AutoGrow.Enabled = 1; - ok = ::InstallLogPolicy(handle, &logPolicy); - QPID_WINDOWS_CHECK_NOT(ok, 0); - logPolicy.PolicyType = ClfsMgmtPolicyAutoShrink; - logPolicy.PolicyParameters.AutoShrink.Percentage = params.shrinkPct; - ok = ::InstallLogPolicy(handle, &logPolicy); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - // Need a marshaling area - ok = ::CreateLogMarshallingArea(handle, - NULL, NULL, NULL, // Alloc, free, context - marshallingBufferSize(), - params.maxWriteBuffers, - 1, // Max read buffers - &marshal); - QPID_WINDOWS_CHECK_NOT(ok, 0); - if (needInitialize) - initialize(); -} - -uint32_t -Log::marshallingBufferSize() -{ - // Default implementation returns the minimum marshalling buffer size; - // derived ones should come up with a more fitting value. - // - // Find the directory name part of the log specification, including the - // trailing '\'. - size_t dirMarker = logPath.rfind('\\'); - if (dirMarker == std::string::npos) - dirMarker = logPath.rfind('/'); - DWORD bytesPerSector; - DWORD dontCare; - ::GetDiskFreeSpace(logPath.substr(0, dirMarker).c_str(), - &dontCare, - &bytesPerSector, - &dontCare, - &dontCare); - return bytesPerSector; -} - -CLFS_LSN -Log::write(void* entry, uint32_t length, CLFS_LSN* prev) -{ - CLFS_WRITE_ENTRY desc; - desc.Buffer = entry; - desc.ByteLength = length; - CLFS_LSN lsn; - BOOL ok = ::ReserveAndAppendLog(marshal, - &desc, 1, // Buffer descriptor - 0, prev, // Undo-Next, Prev - 0, 0, // Reservation - CLFS_FLAG_FORCE_FLUSH, - &lsn, - 0); - QPID_WINDOWS_CHECK_NOT(ok, 0); - return lsn; -} - -// Get the current base LSN of the log. -CLFS_LSN -Log::getBase() -{ - CLFS_INFORMATION info; - ULONG infoSize = sizeof(info); - BOOL ok = ::GetLogFileInformation(handle, &info, &infoSize); - QPID_WINDOWS_CHECK_NOT(ok, 0); - return info.BaseLsn; -} - -void -Log::moveTail(const CLFS_LSN& oldest) -{ - BOOL ok = ::AdvanceLogBase(marshal, - const_cast<PCLFS_LSN>(&oldest), - 0, NULL); - // If multiple threads are manipulating things they may get out of - // order when moving the tail; if someone already moved it further - // than this, it's ok - ignore it. - if (ok || ::GetLastError() == ERROR_LOG_START_OF_LOG) - return; - QPID_WINDOWS_CHECK_NOT(ok, 0); -} - -}}} // namespace qpid::store::ms_clfs diff --git a/cpp/src/qpid/store/ms-clfs/Log.h b/cpp/src/qpid/store/ms-clfs/Log.h deleted file mode 100644 index 2f7eb6cada..0000000000 --- a/cpp/src/qpid/store/ms-clfs/Log.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_LOG_H -#define QPID_STORE_MSCLFS_LOG_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include <windows.h> -#include <clfsw32.h> -#include <qpid/sys/IntegerTypes.h> - -namespace qpid { -namespace store { -namespace ms_clfs { - -/** - * @class Log - * - * Represents a CLFS-housed log. - */ -class Log { - -protected: - HANDLE handle; - ULONGLONG containerSize; - std::string logPath; - PVOID marshal; - - // Give subclasses a chance to initialize a new log. Called after a new - // log is created, initial set of containers is added, and marshalling - // area is allocated. - virtual void initialize() {} - -public: - struct TuningParameters { - size_t containerSize; - unsigned short containers; - unsigned short shrinkPct; - uint32_t maxWriteBuffers; - }; - - Log() : handle(INVALID_HANDLE_VALUE), containerSize(0), marshal(0) {} - virtual ~Log(); - - void open(const std::string& path, const TuningParameters& params); - - virtual uint32_t marshallingBufferSize(); - - CLFS_LSN write(void* entry, uint32_t length, CLFS_LSN* prev = 0); - - // Get the current base LSN of the log. - CLFS_LSN getBase(); - - // Move the log tail to the indicated LSN. - void moveTail(const CLFS_LSN& oldest); -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_LOG_H */ diff --git a/cpp/src/qpid/store/ms-clfs/Lsn.h b/cpp/src/qpid/store/ms-clfs/Lsn.h deleted file mode 100644 index 7f46c1f266..0000000000 --- a/cpp/src/qpid/store/ms-clfs/Lsn.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_LSN_H -#define QPID_STORE_MSCLFS_LSN_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <clfsw32.h> - -namespace { - // Make it easy to assign LSNs - inline CLFS_LSN idToLsn(const uint64_t val) - { CLFS_LSN lsn; lsn.Internal = val; return lsn; } - - inline uint64_t lsnToId(const CLFS_LSN& lsn) - { uint64_t val = lsn.Internal; return val; } -} - -#endif /* QPID_STORE_MSCLFS_LSN_H */ diff --git a/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp b/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp deleted file mode 100644 index 586aaaf980..0000000000 --- a/cpp/src/qpid/store/ms-clfs/MSSqlClfsProvider.cpp +++ /dev/null @@ -1,1121 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <list> -#include <map> -#include <set> -#include <stdlib.h> -#include <string> -#include <windows.h> -#include <clfsw32.h> -#include <qpid/broker/RecoverableQueue.h> -#include <qpid/log/Statement.h> -#include <qpid/store/MessageStorePlugin.h> -#include <qpid/store/StoreException.h> -#include <qpid/store/StorageProvider.h> -#include <qpid/sys/Mutex.h> -#include <boost/foreach.hpp> -#include <boost/make_shared.hpp> - -// From ms-sql... -#include "BlobAdapter.h" -#include "BlobRecordset.h" -#include "BindingRecordset.h" -#include "DatabaseConnection.h" -#include "Exception.h" -#include "State.h" -#include "VariantHelper.h" -using qpid::store::ms_sql::BlobAdapter; -using qpid::store::ms_sql::BlobRecordset; -using qpid::store::ms_sql::BindingRecordset; -using qpid::store::ms_sql::DatabaseConnection; -using qpid::store::ms_sql::ADOException; -using qpid::store::ms_sql::State; -using qpid::store::ms_sql::VariantHelper; - -#include "Log.h" -#include "Messages.h" -#include "Transaction.h" -#include "TransactionLog.h" - -// Bring in ADO 2.8 (yes, I know it says "15", but that's it...) -#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ - no_namespace rename("EOF", "EndOfFile") -#include <comdef.h> -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; - -// Table names -const std::string TblBinding("tblBinding"); -const std::string TblConfig("tblConfig"); -const std::string TblExchange("tblExchange"); -const std::string TblQueue("tblQueue"); - -} - -namespace qpid { -namespace store { -namespace ms_clfs { - -/** - * @class MSSqlClfsProvider - * - * Implements a qpid::store::StorageProvider that uses a hybrid Microsoft - * SQL Server and Windows CLFS approach as the backend data store for Qpid. - */ -class MSSqlClfsProvider : public qpid::store::StorageProvider -{ -protected: - void finalizeMe(); - - void dump(); - -public: - MSSqlClfsProvider(); - ~MSSqlClfsProvider(); - - virtual qpid::Options* getOptions() { return &options; } - - virtual void earlyInitialize (Plugin::Target& target); - virtual void initialize(Plugin::Target& target); - - /** - * Receive notification that this provider is the one that will actively - * handle provider storage for the target. If the provider is to be used, - * this method will be called after earlyInitialize() and before any - * recovery operations (recovery, in turn, precedes call to initialize()). - */ - virtual void activate(MessageStorePlugin &store); - - /** - * @name Methods inherited from qpid::broker::MessageStore - */ - //@{ - /** - * If called after init() but before recovery, will discard the database - * and reinitialize using an empty store dir. If @a pushDownStoreFiles - * is true, the content of the store dir will be moved to a backup dir - * inside the store dir. This is used when cluster nodes recover and must - * get their content from a cluster sync rather than directly from the - * store. - * - * @param pushDownStoreFiles If true, will move content of the store dir - * into a subdir, leaving the store dir - * otherwise empty. - */ - virtual void truncateInit(const bool pushDownStoreFiles = false); - - /** - * Record the existence of a durable queue - */ - virtual void create(PersistableQueue& queue, - const qpid::framing::FieldTable& args); - /** - * Destroy a durable queue - */ - virtual void destroy(PersistableQueue& queue); - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args); - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange); - - /** - * Record a binding - */ - virtual void bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - /** - * Forget a binding - */ - virtual void unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - /** - * Record generic durable configuration - */ - virtual void create(const PersistableConfig& config); - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const PersistableConfig& config); - - /** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr<PersistableMessage>& msg); - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(PersistableMessage& msg); - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const std::string& data); - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr<const PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - - /** - * Flushes all async messages to disk for the specified queue - * - * Note: this is a no-op for this provider. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const PersistableQueue& queue) {}; - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue) - {return 0;} - //@} - - /** - * @name Methods inherited from qpid::broker::TransactionalStore - */ - //@{ - virtual std::auto_ptr<qpid::broker::TransactionContext> begin(); - virtual std::auto_ptr<qpid::broker::TPCTransactionContext> begin(const std::string& xid); - virtual void prepare(qpid::broker::TPCTransactionContext& txn); - virtual void commit(qpid::broker::TransactionContext& txn); - virtual void abort(qpid::broker::TransactionContext& txn); - virtual void collectPreparedXids(std::set<std::string>& xids); - //@} - - virtual void recoverConfigs(qpid::broker::RecoveryManager& recoverer); - virtual void recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap); - virtual void recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap); - virtual void recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap); - virtual void recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap); - virtual void recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap); - -private: - struct ProviderOptions : public qpid::Options - { - std::string connectString; - std::string catalogName; - std::string storeDir; - size_t containerSize; - unsigned short initialContainers; - uint32_t maxWriteBuffers; - - ProviderOptions(const std::string &name) - : qpid::Options(name), - catalogName("QpidStore"), - containerSize(1024 * 1024), - initialContainers(2), - maxWriteBuffers(10) - { - const enum { NAMELEN = MAX_COMPUTERNAME_LENGTH + 1 }; - TCHAR myName[NAMELEN]; - DWORD myNameLen = NAMELEN; - GetComputerName(myName, &myNameLen); - connectString = "Data Source="; - connectString += myName; - connectString += "\\SQLEXPRESS;Integrated Security=SSPI"; - addOptions() - ("connect", - qpid::optValue(connectString, "STRING"), - "Connection string for the database to use. Will prepend " - "Provider=SQLOLEDB;") - ("catalog", - qpid::optValue(catalogName, "DB NAME"), - "Catalog (database) name") - ("store-dir", - qpid::optValue(storeDir, "DIR"), - "Location to store message and transaction data " - "(default uses data-dir if available)") - ("container-size", - qpid::optValue(containerSize, "VALUE"), - "Bytes per container; min 512K. Only used when creating " - "a new log") - ("initial-containers", - qpid::optValue(initialContainers, "VALUE"), - "Number of containers to add if creating a new log") - ("max-write-buffers", - qpid::optValue(maxWriteBuffers, "VALUE"), - "Maximum write buffers outstanding before log is flushed " - "(0 means no limit)") - ; - } - }; - ProviderOptions options; - std::string brokerDataDir; - Messages messages; - // TransactionLog requires itself to have a shared_ptr reference to start. - TransactionLog::shared_ptr transactions; - - // Each thread has a separate connection to the database and also needs - // to manage its COM initialize/finalize individually. This is done by - // keeping a thread-specific State. - boost::thread_specific_ptr<State> dbState; - - State *initState(); - DatabaseConnection *initConnection(void); - void createDb(DatabaseConnection *db, const std::string &name); - void createLogs(); -}; - -static MSSqlClfsProvider static_instance_registers_plugin; - -void -MSSqlClfsProvider::finalizeMe() -{ - dbState.reset(); -} - -MSSqlClfsProvider::MSSqlClfsProvider() - : options("MS SQL/CLFS Provider options") -{ - transactions = boost::make_shared<TransactionLog>(); -} - -MSSqlClfsProvider::~MSSqlClfsProvider() -{ -} - -void -MSSqlClfsProvider::earlyInitialize(Plugin::Target &target) -{ - MessageStorePlugin *store = dynamic_cast<MessageStorePlugin *>(&target); - if (store) { - // Check the store dir option; if not specified, need to - // grab the broker's data dir. - if (options.storeDir.empty()) { - DataDir& dir = store->getBroker()->getDataDir(); - if (dir.isEnabled()) { - options.storeDir = dir.getPath(); - } - else { - QPID_LOG(error, - "MSSQL-CLFS: --store-dir required if --no-data-dir specified"); - return; - } - } - - // If CLFS is not available on this system, give up now. - try { - Log::TuningParameters params; - params.containerSize = options.containerSize; - params.containers = options.initialContainers; - params.shrinkPct = 50; - params.maxWriteBuffers = options.maxWriteBuffers; - std::string msgPath = options.storeDir + "\\" + "messages"; - messages.openLog(msgPath, params); - std::string transPath = options.storeDir + "\\" + "transactions"; - transactions->open(transPath, params); - } - catch (std::exception &e) { - QPID_LOG(error, e.what()); - return; - } - - // If the database init fails, report it and don't register; give - // the rest of the broker a chance to run. - // - // Don't try to initConnection() since that will fail if the - // database doesn't exist. Instead, try to open a connection without - // a database name, then search for the database. There's still a - // chance this provider won't be selected for the store too, so be - // be sure to close the database connection before return to avoid - // leaving a connection up that will not be used. - try { - initState(); // This initializes COM - std::auto_ptr<DatabaseConnection> db(new DatabaseConnection()); - db->open(options.connectString, ""); - _ConnectionPtr conn(*db); - _RecordsetPtr pCatalogs = NULL; - VariantHelper<std::string> catalogName(options.catalogName); - pCatalogs = conn->OpenSchema(adSchemaCatalogs, catalogName); - if (pCatalogs->EndOfFile) { - // Database doesn't exist; create it - QPID_LOG(notice, - "MSSQL-CLFS: Creating database " + options.catalogName); - createDb(db.get(), options.catalogName); - } - else { - QPID_LOG(notice, - "MSSQL-CLFS: Database located: " + options.catalogName); - } - if (pCatalogs) { - if (pCatalogs->State == adStateOpen) - pCatalogs->Close(); - pCatalogs = 0; - } - db->close(); - store->providerAvailable("MSSQL-CLFS", this); - } - catch (qpid::Exception &e) { - QPID_LOG(error, e.what()); - return; - } - store->addFinalizer(boost::bind(&MSSqlClfsProvider::finalizeMe, this)); - } -} - -void -MSSqlClfsProvider::initialize(Plugin::Target& target) -{ -} - -void -MSSqlClfsProvider::activate(MessageStorePlugin &store) -{ - QPID_LOG(info, "MS SQL/CLFS Provider is up"); -} - -void -MSSqlClfsProvider::truncateInit(const bool pushDownStoreFiles) -{ -} - -void -MSSqlClfsProvider::create(PersistableQueue& queue, - const qpid::framing::FieldTable& /*args needed for jrnl*/) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - try { - db->beginTransaction(); - rsQueues.open(db, TblQueue); - rsQueues.add(queue); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating queue " + queue.getName(), e, errs); - } - catch(std::exception& e) { - db->rollbackTransaction(); - THROW_STORE_EXCEPTION(e.what()); - } -} - -/** - * Destroy a durable queue - */ -void -MSSqlClfsProvider::destroy(PersistableQueue& queue) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsQueues.open(db, TblQueue); - rsBindings.open(db, TblBinding); - // Remove bindings first; the queue IDs can't be ripped out from - // under the references in the bindings table. - rsBindings.removeForQueue(queue.getPersistenceId()); - rsQueues.remove(queue); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting queue " + queue.getName(), e, errs); - } - - /* - * Now that the SQL stuff has recorded the queue deletion, expunge - * all record of the queue from the messages set. Any errors logging - * these removals are swallowed because during a recovery the queue - * Id won't be present (the SQL stuff already committed) so any references - * to it in message operations will be removed. - */ - messages.expunge(queue.getPersistenceId()); -} - -/** - * Record the existence of a durable exchange - */ -void -MSSqlClfsProvider::create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - try { - db->beginTransaction(); - rsExchanges.open(db, TblExchange); - rsExchanges.add(exchange); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating exchange " + exchange.getName(), - e, - errs); - } -} - -/** - * Destroy a durable exchange - */ -void -MSSqlClfsProvider::destroy(const PersistableExchange& exchange) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsExchanges.open(db, TblExchange); - rsBindings.open(db, TblBinding); - // Remove bindings first; the exchange IDs can't be ripped out from - // under the references in the bindings table. - rsBindings.removeForExchange(exchange.getPersistenceId()); - rsExchanges.remove(exchange); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting exchange " + exchange.getName(), - e, - errs); - } -} - -/** - * Record a binding - */ -void -MSSqlClfsProvider::bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsBindings.open(db, TblBinding); - rsBindings.add(exchange.getPersistenceId(), - queue.getPersistenceId(), - key, - args); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error binding exchange " + exchange.getName() + - " to queue " + queue.getName(), - e, - errs); - } -} - -/** - * Forget a binding - */ -void -MSSqlClfsProvider::unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsBindings.open(db, TblBinding); - rsBindings.remove(exchange.getPersistenceId(), - queue.getPersistenceId(), - key, - args); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error unbinding exchange " + exchange.getName() + - " from queue " + queue.getName(), - e, - errs); - } -} - -/** - * Record generic durable configuration - */ -void -MSSqlClfsProvider::create(const PersistableConfig& config) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - try { - db->beginTransaction(); - rsConfigs.open(db, TblConfig); - rsConfigs.add(config); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating config " + config.getName(), e, errs); - } -} - -/** - * Destroy generic durable configuration - */ -void -MSSqlClfsProvider::destroy(const PersistableConfig& config) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - try { - db->beginTransaction(); - rsConfigs.open(db, TblConfig); - rsConfigs.remove(config); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting config " + config.getName(), e, errs); - } -} - -/** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ -void -MSSqlClfsProvider::stage(const boost::intrusive_ptr<PersistableMessage>& msg) -{ -#if 0 - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.add(msg); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error staging message", e, errs); - } -#endif -} - -/** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ -void -MSSqlClfsProvider::destroy(PersistableMessage& msg) -{ -#if 0 - DatabaseConnection *db = initConnection(); - BlobRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.remove(msg); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting message", e, errs); - } -#endif -} - -/** - * Appends content to a previously staged message - */ -void -MSSqlClfsProvider::appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const std::string& data) -{ -#if 0 - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.append(msg, data); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error appending to message", e, errs); - } -#endif -} - -/** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ -void -MSSqlClfsProvider::loadContent(const qpid::broker::PersistableQueue& /*queue*/, - const boost::intrusive_ptr<const PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length) -{ - // Message log keeps all messages in one log, so we don't need the - // queue reference. - messages.loadContent(msg->getPersistenceId(), data, offset, length); -} - -/** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * @param ctxt The transaction context under which this enqueue happens. - * @param msg The message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - */ -void -MSSqlClfsProvider::enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) -{ - Transaction::shared_ptr t; - TransactionContext *ctx = dynamic_cast<TransactionContext*>(ctxt); - if (ctx) - t = ctx->getTransaction(); - else { - TPCTransactionContext *tctx; - tctx = dynamic_cast<TPCTransactionContext*>(ctxt); - if (tctx) - t = tctx->getTransaction(); - } - uint64_t msgId = msg->getPersistenceId(); - if (msgId == 0) { - messages.add(msg); - msgId = msg->getPersistenceId(); - } - messages.enqueue(msgId, queue.getPersistenceId(), t); - msg->enqueueComplete(); -} - -/** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * @param ctxt The transaction context under which this dequeue happens. - * @param msg The message to dequeue - * @param queue The queue from which it is to be dequeued - */ -void -MSSqlClfsProvider::dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) -{ - Transaction::shared_ptr t; - TransactionContext *ctx = dynamic_cast<TransactionContext*>(ctxt); - if (ctx) - t = ctx->getTransaction(); - else { - TPCTransactionContext *tctx; - tctx = dynamic_cast<TPCTransactionContext*>(ctxt); - if (tctx) - t = tctx->getTransaction(); - } - messages.dequeue(msg->getPersistenceId(), queue.getPersistenceId(), t); - msg->dequeueComplete(); -} - -std::auto_ptr<qpid::broker::TransactionContext> -MSSqlClfsProvider::begin() -{ - Transaction::shared_ptr t = transactions->begin(); - std::auto_ptr<qpid::broker::TransactionContext> tc(new TransactionContext(t)); - return tc; -} - -std::auto_ptr<qpid::broker::TPCTransactionContext> -MSSqlClfsProvider::begin(const std::string& xid) -{ - TPCTransaction::shared_ptr t = transactions->begin(xid); - std::auto_ptr<qpid::broker::TPCTransactionContext> tc(new TPCTransactionContext(t)); - return tc; -} - -void -MSSqlClfsProvider::prepare(qpid::broker::TPCTransactionContext& txn) -{ - TPCTransactionContext *ctx = dynamic_cast<TPCTransactionContext*> (&txn); - if (ctx == 0) - throw qpid::broker::InvalidTransactionContextException(); - ctx->getTransaction()->prepare(); -} - -void -MSSqlClfsProvider::commit(qpid::broker::TransactionContext& txn) -{ - Transaction::shared_ptr t; - TransactionContext *ctx = dynamic_cast<TransactionContext*>(&txn); - if (ctx) - t = ctx->getTransaction(); - else { - TPCTransactionContext *tctx; - tctx = dynamic_cast<TPCTransactionContext*>(&txn); - if (tctx == 0) - throw qpid::broker::InvalidTransactionContextException(); - t = tctx->getTransaction(); - } - t->commit(messages); -} - -void -MSSqlClfsProvider::abort(qpid::broker::TransactionContext& txn) -{ - Transaction::shared_ptr t; - TransactionContext *ctx = dynamic_cast<TransactionContext*>(&txn); - if (ctx) - t = ctx->getTransaction(); - else { - TPCTransactionContext *tctx; - tctx = dynamic_cast<TPCTransactionContext*>(&txn); - if (tctx == 0) - throw qpid::broker::InvalidTransactionContextException(); - t = tctx->getTransaction(); - } - t->abort(messages); -} - -void -MSSqlClfsProvider::collectPreparedXids(std::set<std::string>& xids) -{ - std::map<std::string, TPCTransaction::shared_ptr> preparedMap; - transactions->collectPreparedXids(preparedMap); - std::map<std::string, TPCTransaction::shared_ptr>::const_iterator i; - for (i = preparedMap.begin(); i != preparedMap.end(); ++i) { - xids.insert(i->first); - } -} - -// @TODO Much of this recovery code is way too similar... refactor to -// a recover template method on BlobRecordset. - -void -MSSqlClfsProvider::recoverConfigs(qpid::broker::RecoveryManager& recoverer) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - rsConfigs.open(db, TblConfig); - _RecordsetPtr p = (_RecordsetPtr)rsConfigs; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Config instance and reset its ID. - broker::RecoverableConfig::shared_ptr config = - recoverer.recoverConfig(blob); - config->setPersistenceId(id); - p->MoveNext(); - } -} - -void -MSSqlClfsProvider::recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - rsExchanges.open(db, TblExchange); - _RecordsetPtr p = (_RecordsetPtr)rsExchanges; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Exchange instance, reset its ID, and remember the - // ones restored for matching up when recovering bindings. - broker::RecoverableExchange::shared_ptr exchange = - recoverer.recoverExchange(blob); - exchange->setPersistenceId(id); - exchangeMap[id] = exchange; - p->MoveNext(); - } -} - -void -MSSqlClfsProvider::recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - rsQueues.open(db, TblQueue); - _RecordsetPtr p = (_RecordsetPtr)rsQueues; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Queue instance and reset its ID. - broker::RecoverableQueue::shared_ptr queue = - recoverer.recoverQueue(blob); - queue->setPersistenceId(id); - queueMap[id] = queue; - p->MoveNext(); - } -} - -void -MSSqlClfsProvider::recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - rsBindings.open(db, TblBinding); - rsBindings.recover(recoverer, exchangeMap, queueMap); -} - -void -MSSqlClfsProvider::recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap) -{ - // Read the list of valid queue Ids to ensure that no broken msg->queue - // refs get restored. - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - rsQueues.open(db, TblQueue); - _RecordsetPtr p = (_RecordsetPtr)rsQueues; - std::set<uint64_t> validQueues; - if (!(p->BOF && p->EndOfFile)) { - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - validQueues.insert(id); - p->MoveNext(); - } - } - std::map<uint64_t, Transaction::shared_ptr> transMap; - transactions->recover(transMap); - messages.recover(recoverer, - validQueues, - transMap, - messageMap, - messageQueueMap); -} - -void -MSSqlClfsProvider::recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap) -{ - std::map<std::string, TPCTransaction::shared_ptr> preparedMap; - transactions->collectPreparedXids(preparedMap); - std::map<std::string, TPCTransaction::shared_ptr>::const_iterator i; - for (i = preparedMap.begin(); i != preparedMap.end(); ++i) { - std::auto_ptr<TPCTransactionContext> ctx(new TPCTransactionContext(i->second)); - std::auto_ptr<qpid::broker::TPCTransactionContext> brokerCtx(ctx); - dtxMap[i->first] = recoverer.recoverTransaction(i->first, brokerCtx); - } -} - -////////////// Internal Methods - -State * -MSSqlClfsProvider::initState() -{ - State *state = dbState.get(); // See if thread has initialized - if (!state) { - state = new State; - dbState.reset(state); - } - return state; -} - -DatabaseConnection * -MSSqlClfsProvider::initConnection(void) -{ - State *state = initState(); - if (state->dbConn != 0) - return state->dbConn; // And the DatabaseConnection is set up too - std::auto_ptr<DatabaseConnection> db(new DatabaseConnection); - db->open(options.connectString, options.catalogName); - state->dbConn = db.release(); - return state->dbConn; -} - -void -MSSqlClfsProvider::createDb(DatabaseConnection *db, const std::string &name) -{ - const std::string dbCmd = "CREATE DATABASE " + name; - const std::string useCmd = "USE " + name; - const std::string tableCmd = "CREATE TABLE "; - const std::string colSpecs = - " (persistenceId bigint PRIMARY KEY NOT NULL IDENTITY(1,1)," - " fieldTableBlob varbinary(MAX) NOT NULL)"; - const std::string bindingSpecs = - " (exchangeId bigint REFERENCES tblExchange(persistenceId) NOT NULL," - " queueId bigint REFERENCES tblQueue(persistenceId) NOT NULL," - " routingKey varchar(255)," - " fieldTableBlob varbinary(MAX))"; - - _variant_t unused; - _bstr_t dbStr = dbCmd.c_str(); - _ConnectionPtr conn(*db); - try { - conn->Execute(dbStr, &unused, adExecuteNoRecords); - _bstr_t useStr = useCmd.c_str(); - conn->Execute(useStr, &unused, adExecuteNoRecords); - std::string makeTable = tableCmd + TblQueue + colSpecs; - _bstr_t makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblExchange + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblConfig + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblBinding + bindingSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - } - catch(_com_error &e) { - throw ADOException("MSSQL can't create " + name, e, db->getErrors()); - } -} - -void -MSSqlClfsProvider::dump() -{ - // dump all db records to qpid_log - QPID_LOG(notice, "DB Dump: (not dumping anything)"); - // rsQueues.dump(); -} - - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-clfs/MessageLog.cpp b/cpp/src/qpid/store/ms-clfs/MessageLog.cpp deleted file mode 100644 index 14d63a4cd4..0000000000 --- a/cpp/src/qpid/store/ms-clfs/MessageLog.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <windows.h> -#include <clfsw32.h> -#include <exception> -#include <malloc.h> -#include <memory.h> -#include <qpid/framing/Buffer.h> -#include <qpid/log/Statement.h> -#include <qpid/sys/IntegerTypes.h> -#include <qpid/sys/windows/check.h> - -#include "MessageLog.h" -#include "Lsn.h" - -namespace { - -// Structures that hold log records. Each has a type field at the start. -enum MessageEntryType { - MessageStartEntry = 1, - MessageChunkEntry = 2, - MessageDeleteEntry = 3, - MessageEnqueueEntry = 4, - MessageDequeueEntry = 5 -}; -static const uint32_t MaxMessageContentLength = 64 * 1024; - -// Message-Start -struct MessageStart { - MessageEntryType type; - // If the complete message encoding doesn't fit, remainder is in - // MessageChunk records to follow. - // headerLength is the size of the message's header in content. It is - // part of the totalLength and the segmentLength. - uint32_t headerLength; - uint32_t totalLength; - uint32_t segmentLength; - char content[MaxMessageContentLength]; - - MessageStart() - : type(MessageStartEntry), - headerLength(0), - totalLength(0), - segmentLength(0) {} -}; -// Message-Chunk -struct MessageChunk { - MessageEntryType type; - uint32_t segmentLength; - char content[MaxMessageContentLength]; - - MessageChunk() : type(MessageChunkEntry), segmentLength(0) {} -}; -// Message-Delete -struct MessageDelete { - MessageEntryType type; - - MessageDelete() : type(MessageDeleteEntry) {} -}; -// Message-Enqueue -struct MessageEnqueue { - MessageEntryType type; - uint64_t queueId; - uint64_t transId; - - MessageEnqueue(uint64_t qId = 0, uint64_t tId = 0) - : type(MessageEnqueueEntry), queueId(qId), transId(tId) {} -}; -// Message-Dequeue -struct MessageDequeue { - MessageEntryType type; - uint64_t queueId; - uint64_t transId; - - MessageDequeue(uint64_t qId = 0, uint64_t tId = 0) - : type(MessageDequeueEntry), queueId(qId), transId(tId) {} -}; - -} // namespace - -namespace qpid { -namespace store { -namespace ms_clfs { - -void -MessageLog::initialize() -{ - // Write something to occupy the first record, preventing a real message - // from being lsn/id 0. Delete of a non-existant id is easily tossed - // during recovery if no other messages have caused the tail to be moved - // up past this dummy record by then. - deleteMessage(0, 0); -} - -uint32_t -MessageLog::marshallingBufferSize() -{ - size_t biggestNeed = std::max(sizeof(MessageStart), sizeof(MessageEnqueue)); - uint32_t defSize = static_cast<uint32_t>(biggestNeed); - uint32_t minSize = Log::marshallingBufferSize(); - if (defSize <= minSize) - return minSize; - // Round up to multiple of minSize - return (defSize + minSize) / minSize * minSize; -} - -uint64_t -MessageLog::add(const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg) -{ - // The message may be too long to fit in one record; if so, write - // Message-Chunk records to contain the rest. If it does all fit in one - // record, though, optimize the encoding by going straight to the - // Message-Start record rather than encoding then copying to the record. - // In all case - MessageStart entry; - uint32_t encodedMessageLength = msg->encodedSize(); - entry.headerLength = msg->encodedHeaderSize(); - entry.totalLength = encodedMessageLength; - CLFS_LSN location, lastChunkLsn; - std::auto_ptr<char> encodeStage; - char *encodeBuff = 0; - bool oneRecord = encodedMessageLength <= MaxMessageContentLength; - if (oneRecord) { - encodeBuff = entry.content; - entry.segmentLength = encodedMessageLength; - } - else { - encodeStage.reset(new char[encodedMessageLength]); - encodeBuff = encodeStage.get(); - entry.segmentLength = MaxMessageContentLength; - } - qpid::framing::Buffer buff(encodeBuff, encodedMessageLength); - msg->encode(buff); - if (!oneRecord) - memcpy_s(entry.content, sizeof(entry.content), - encodeBuff, entry.segmentLength); - uint32_t entryLength = static_cast<uint32_t>(sizeof(entry)); - entryLength -= (MaxMessageContentLength - entry.segmentLength); - location = write(&entry, entryLength); - // Write any Message-Chunk records before setting the message's id. - uint32_t sent = entry.segmentLength; - uint32_t remaining = encodedMessageLength - entry.segmentLength; - while (remaining > 0) { - MessageChunk chunk; - chunk.segmentLength = std::max(MaxMessageContentLength, remaining); - memcpy_s(chunk.content, sizeof(chunk.content), - encodeStage.get() + sent, chunk.segmentLength); - entryLength = static_cast<uint32_t>(sizeof(chunk)); - entryLength -= (MaxMessageContentLength - chunk.segmentLength); - lastChunkLsn = write(&chunk, entryLength, &location); - sent += chunk.segmentLength; - remaining -= chunk.segmentLength; - } - return lsnToId(location); -} - -void -MessageLog::deleteMessage(uint64_t messageId, uint64_t newFirstId) -{ - MessageDelete deleteEntry; - CLFS_LSN msgLsn = idToLsn(messageId); - write(&deleteEntry, sizeof(deleteEntry), &msgLsn); - if (newFirstId != 0) - moveTail(idToLsn(newFirstId)); -} - -// Load part or all of a message's content from previously stored -// log record(s). -void -MessageLog::loadContent(uint64_t messageId, - std::string& data, - uint64_t offset, - uint32_t length) -{ -} - -void -MessageLog::recordEnqueue (uint64_t messageId, - uint64_t queueId, - uint64_t transactionId) -{ - MessageEnqueue entry(queueId, transactionId); - CLFS_LSN msgLsn = idToLsn(messageId); - write(&entry, sizeof(entry), &msgLsn); -} - -void -MessageLog::recordDequeue (uint64_t messageId, - uint64_t queueId, - uint64_t transactionId) -{ - MessageDequeue entry(queueId, transactionId); - CLFS_LSN msgLsn = idToLsn(messageId); - write(&entry, sizeof(entry), &msgLsn); -} - -void -MessageLog::recover(qpid::broker::RecoveryManager& recoverer, - qpid::store::MessageMap& messageMap, - std::map<uint64_t, std::vector<RecoveredMsgOp> >& messageOps) -{ - // If context and content needs to be saved while reassembling messages - // split across log records, save the info and reassembly buffer. - struct MessageBlocks { - uint32_t totalLength; - uint32_t soFarLength; - boost::shared_ptr<char> content; - - MessageBlocks() : totalLength(0), soFarLength(0), content((char*)0) {} - }; - std::map<uint64_t, MessageBlocks> reassemblies; - std::map<uint64_t, MessageBlocks>::iterator at; - - QPID_LOG(debug, "Recovering message log"); - - // Note that there may be message refs in the log which are deleted, so - // be sure to only add msgs at message-start record, and ignore those - // that don't have an existing message record. - // Get the base LSN - that's how to say "start reading at the beginning" - CLFS_INFORMATION info; - ULONG infoLength = sizeof (info); - BOOL ok = ::GetLogFileInformation(handle, &info, &infoLength); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - // Pointers for the various record types that can be assigned in the - // reading loop below. - MessageStart *start; - MessageChunk *chunk; - MessageEnqueue *enqueue; - MessageDequeue *dequeue; - - qpid::store::MessageMap::iterator messageMapSpot; - qpid::store::MessageQueueMap::iterator queueMapSpot; - PVOID recordPointer; - ULONG recordLength; - CLFS_RECORD_TYPE recordType = ClfsDataRecord; - CLFS_LSN messageLsn, current, undoNext; - PVOID readContext; - uint64_t msgId; - // Note 'current' in case it's needed below; ReadNextLogRecord returns it - // via a parameter. - current = info.BaseLsn; - ok = ::ReadLogRecord(marshal, - &info.BaseLsn, - ClfsContextForward, - &recordPointer, - &recordLength, - &recordType, - &undoNext, - &messageLsn, - &readContext, - 0); - while (ok) { - // All the record types this class writes have a MessageEntryType in the - // beginning. Based on that, do what's needed. - MessageEntryType *t = - reinterpret_cast<MessageEntryType *>(recordPointer); - switch(*t) { - case MessageStartEntry: - start = reinterpret_cast<MessageStart *>(recordPointer); - msgId = lsnToId(current); - QPID_LOG(debug, "Message Start, id " << msgId); - // If the message content is split across multiple log records, save - // this content off to the side until the remaining record(s) are - // located. - if (start->totalLength == start->segmentLength) { // Whole thing - // Start by recovering the header then see if the rest of - // the content is desired. - qpid::framing::Buffer buff(start->content, start->headerLength); - qpid::broker::RecoverableMessage::shared_ptr m = - recoverer.recoverMessage(buff); - m->setPersistenceId(msgId); - messageMap[msgId] = m; - uint32_t contentLength = - start->totalLength - start->headerLength; - if (m->loadContent(contentLength)) { - qpid::framing::Buffer content(&(start->content[start->headerLength]), - contentLength); - m->decodeContent(content); - } - } - else { - // Save it in a block big enough. - MessageBlocks b; - b.totalLength = start->totalLength; - b.soFarLength = start->segmentLength; - b.content.reset(new char[b.totalLength]); - memcpy_s(b.content.get(), b.totalLength, - start->content, start->segmentLength); - reassemblies[msgId] = b; - } - break; - case MessageChunkEntry: - chunk = reinterpret_cast<MessageChunk *>(recordPointer); - // Remember, all entries chained to MessageStart via previous. - msgId = lsnToId(messageLsn); - QPID_LOG(debug, "Message Chunk for id " << msgId); - at = reassemblies.find(msgId); - if (at == reassemblies.end()) { - QPID_LOG(debug, "Message frag for " << msgId << - " but no start; discarded"); - } - else { - MessageBlocks *b = &(at->second); - if (b->soFarLength + chunk->segmentLength > b->totalLength) - throw std::runtime_error("Invalid message chunk length"); - memcpy_s(b->content.get() + b->soFarLength, - b->totalLength - b->soFarLength, - chunk->content, - chunk->segmentLength); - b->soFarLength += chunk->segmentLength; - if (b->totalLength == b->soFarLength) { - qpid::framing::Buffer buff(b->content.get(), - b->totalLength); - qpid::broker::RecoverableMessage::shared_ptr m = - recoverer.recoverMessage(buff); - m->setPersistenceId(msgId); - messageMap[msgId] = m; - reassemblies.erase(at); - } - } - break; - case MessageDeleteEntry: - msgId = lsnToId(messageLsn); - QPID_LOG(debug, "Message Delete, id " << msgId); - messageMap.erase(msgId); - messageOps.erase(msgId); - break; - case MessageEnqueueEntry: - enqueue = reinterpret_cast<MessageEnqueue *>(recordPointer); - msgId = lsnToId(messageLsn); - QPID_LOG(debug, "Message " << msgId << " Enqueue on queue " << - enqueue->queueId << ", txn " << enqueue->transId); - if (messageMap.find(msgId) == messageMap.end()) { - QPID_LOG(debug, - "Message " << msgId << " doesn't exist; discarded"); - } - else { - std::vector<RecoveredMsgOp>& ops = messageOps[msgId]; - RecoveredMsgOp op(RECOVERED_ENQUEUE, - enqueue->queueId, - enqueue->transId); - ops.push_back(op); - } - break; - case MessageDequeueEntry: - dequeue = reinterpret_cast<MessageDequeue *>(recordPointer); - msgId = lsnToId(messageLsn); - QPID_LOG(debug, "Message " << msgId << " Dequeue from queue " << - dequeue->queueId); - if (messageMap.find(msgId) == messageMap.end()) { - QPID_LOG(debug, - "Message " << msgId << " doesn't exist; discarded"); - } - else { - std::vector<RecoveredMsgOp>& ops = messageOps[msgId]; - RecoveredMsgOp op(RECOVERED_DEQUEUE, - dequeue->queueId, - dequeue->transId); - ops.push_back(op); - } - break; - default: - throw std::runtime_error("Bad message log entry type"); - } - - recordType = ClfsDataRecord; - ok = ::ReadNextLogRecord(readContext, - &recordPointer, - &recordLength, - &recordType, - 0, // No userLsn - &undoNext, - &messageLsn, - ¤t, - 0); - } - DWORD status = ::GetLastError(); - ::TerminateReadLog(readContext); - if (status == ERROR_HANDLE_EOF) { // No more records - QPID_LOG(debug, "Message log recovered"); - return; - } - throw QPID_WINDOWS_ERROR(status); -} - -}}} // namespace qpid::store::ms_clfs diff --git a/cpp/src/qpid/store/ms-clfs/MessageLog.h b/cpp/src/qpid/store/ms-clfs/MessageLog.h deleted file mode 100644 index b3705287a6..0000000000 --- a/cpp/src/qpid/store/ms-clfs/MessageLog.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_MESSAGELOG_H -#define QPID_STORE_MSCLFS_MESSAGELOG_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/intrusive_ptr.hpp> -#include <qpid/broker/PersistableMessage.h> -#include <qpid/broker/RecoveryManager.h> -#include <qpid/sys/IntegerTypes.h> -#include <qpid/store/StorageProvider.h> - -#include "Log.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -/** - * @class MessageLog - * - * Represents a CLFS-housed message log. - */ -class MessageLog : public Log { - -protected: - // Message log needs to have a no-op first record written in the log - // to ensure that no real message gets an ID 0. - virtual void initialize(); - -public: - // Inherited and reimplemented from Log. Figure the minimum marshalling - // buffer size needed for the records this class writes. - virtual uint32_t marshallingBufferSize(); - - // Add the specified message to the log; Return the persistence Id. - uint64_t add(const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg); - - // Write a Delete entry for messageId. If newFirstId is not 0, it is now - // the earliest valid message in the log, so move the tail up to it. - void deleteMessage(uint64_t messageId, uint64_t newFirstId); - - // Load part or all of a message's content from previously stored - // log record(s). - void loadContent(uint64_t messageId, - std::string& data, - uint64_t offset, - uint32_t length); - - // Enqueue and dequeue operations track messages' transit across - // queues; each operation may be associated with a transaction. If - // the transactionId is 0 the operation is not associated with a - // transaction. - void recordEnqueue (uint64_t messageId, - uint64_t queueId, - uint64_t transactionId); - void recordDequeue (uint64_t messageId, - uint64_t queueId, - uint64_t transactionId); - - // Recover the messages and their queueing records from the log. - // @param recoverer Recovery manager used to recreate broker objects from - // encoded framing buffers recovered from the log. - // @param messageMap This method fills in the map of id -> ptr of - // recovered messages. - // @param messageOps This method fills in the map of msg id -> - // vector of operations involving the message that were - // recovered from the log. It is the caller's - // responsibility to sort the operations out and - // ascertain which operations should be acted on. The - // order of operations in the vector is as they were - // read in order from the log. - typedef enum { RECOVERED_ENQUEUE = 1, RECOVERED_DEQUEUE } RecoveredOpType; - struct RecoveredMsgOp { - RecoveredOpType op; - uint64_t queueId; - uint64_t txnId; - - RecoveredMsgOp(RecoveredOpType o, const uint64_t& q, const uint64_t& t) - : op(o), queueId(q), txnId(t) {} - }; - void recover(qpid::broker::RecoveryManager& recoverer, - qpid::store::MessageMap& messageMap, - std::map<uint64_t, std::vector<RecoveredMsgOp> >& messageOps); -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_MESSAGELOG_H */ diff --git a/cpp/src/qpid/store/ms-clfs/Messages.cpp b/cpp/src/qpid/store/ms-clfs/Messages.cpp deleted file mode 100644 index db5d2ebf4c..0000000000 --- a/cpp/src/qpid/store/ms-clfs/Messages.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/log/Statement.h> - -#include "Messages.h" -#include "Lsn.h" -#include "qpid/store/StoreException.h" -#include <boost/foreach.hpp> - -namespace qpid { -namespace store { -namespace ms_clfs { - -void -Messages::openLog(const std::string& path, const Log::TuningParameters& params) -{ - log.open (path, params); -} - -void -Messages::add(const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg) -{ - uint64_t id = log.add(msg); - msg->setPersistenceId(id); - std::auto_ptr<MessageInfo> autom(new MessageInfo); - MessageInfo::shared_ptr m(autom); - std::pair<uint64_t, MessageInfo::shared_ptr> p(id, m); - { - qpid::sys::ScopedWlock<qpid::sys::RWlock> l(lock); - messages.insert(p); - // If there's only this one message there, move the tail to it. - // This prevents the log from continually growing when messages - // are added and removed one at a time. - if (messages.size() == 1) { - CLFS_LSN newTail = idToLsn(id); - log.moveTail(newTail); - } - } -} - -void -Messages::enqueue(uint64_t msgId, uint64_t queueId, Transaction::shared_ptr& t) -{ - MessageInfo::shared_ptr p; - { - qpid::sys::ScopedRlock<qpid::sys::RWlock> l(lock); - MessageMap::const_iterator i = messages.find(msgId); - if (i == messages.end()) - THROW_STORE_EXCEPTION("Message does not exist"); - p = i->second; - } - MessageInfo::Location loc(queueId, t, MessageInfo::TRANSACTION_ENQUEUE); - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(p->whereLock); - p->where.push_back(loc); - uint64_t transactionId = 0; - if (t.get() != 0) { - transactionId = t->getId(); - t->enroll(msgId); - } - try { - log.recordEnqueue(msgId, queueId, transactionId); - } - catch (...) { - // Undo the record-keeping if the log wasn't written correctly. - if (transactionId != 0) - t->unenroll(msgId); - p->where.pop_back(); - throw; - } - } -} - -void -Messages::dequeue(uint64_t msgId, uint64_t queueId, Transaction::shared_ptr& t) -{ - MessageInfo::shared_ptr p; - { - qpid::sys::ScopedRlock<qpid::sys::RWlock> l(lock); - MessageMap::const_iterator i = messages.find(msgId); - if (i == messages.end()) - THROW_STORE_EXCEPTION("Message does not exist"); - p = i->second; - } - { - // Locate the 'where' entry for the specified queue. Once this operation - // is recorded in the log, update the 'where' entry to reflect it. - // Note that an existing entry in 'where' that refers to a transaction - // is not eligible for this operation. - qpid::sys::ScopedLock<qpid::sys::Mutex> l(p->whereLock); - std::list<MessageInfo::Location>::iterator i; - for (i = p->where.begin(); i != p->where.end(); ++i) { - if (i->queueId == queueId && i->transaction.get() == 0) - break; - } - if (i == p->where.end()) - THROW_STORE_EXCEPTION("Message not on queue"); - uint64_t transactionId = 0; - if (t.get() != 0) { - transactionId = t->getId(); - t->enroll(msgId); - } - try { - log.recordDequeue(msgId, queueId, transactionId); - } - catch (...) { - // Undo the record-keeping if the log wasn't written correctly. - if (transactionId != 0) - t->unenroll(msgId); - throw; - } - // Ok, logged successfully. If this is a transactional op, note - // the transaction. If non-transactional, remove the 'where' entry. - if (transactionId != 0) { - i->transaction = t; - i->disposition = MessageInfo::TRANSACTION_DEQUEUE; - } - else { - p->where.erase(i); - // If the message doesn't exist on any other queues, remove it. - if (p->where.empty()) - remove(msgId); - } - } -} - -// Commit a previous provisional enqueue or dequeue of a particular message -// actions under a specified transaction. If this results in the message's -// being removed from all queues, it is deleted. -void -Messages::commit(uint64_t msgId, Transaction::shared_ptr& t) -{ - MessageInfo::shared_ptr p; - { - qpid::sys::ScopedRlock<qpid::sys::RWlock> l(lock); - MessageMap::const_iterator i = messages.find(msgId); - if (i == messages.end()) - THROW_STORE_EXCEPTION("Message does not exist"); - p = i->second; - } - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(p->whereLock); - std::list<MessageInfo::Location>::iterator i; - for (i = p->where.begin(); i != p->where.end(); ++i) { - if (i->transaction != t) - continue; - // Transactional dequeues can now remove the item from the - // where list; enqueues just clear the transaction reference. - if (i->disposition == MessageInfo::TRANSACTION_DEQUEUE) - i = p->where.erase(i); - else - i->transaction.reset(); - } - } - // If committing results in this message having no further enqueue - // references, delete it. If the delete fails, swallow the exception - // and let recovery take care of removing it later. - if (p->where.empty()) { - try { - remove(msgId); - } - catch(...) {} - } -} - -// Abort a previous provisional enqueue or dequeue of a particular message -// actions under a specified transaction. If this results in the message's -// being removed from all queues, it is deleted. -void -Messages::abort(uint64_t msgId, Transaction::shared_ptr& t) -{ - MessageInfo::shared_ptr p; - { - qpid::sys::ScopedRlock<qpid::sys::RWlock> l(lock); - MessageMap::const_iterator i = messages.find(msgId); - if (i == messages.end()) - THROW_STORE_EXCEPTION("Message does not exist"); - p = i->second; - } - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(p->whereLock); - std::list<MessageInfo::Location>::iterator i = p->where.begin(); - while (i != p->where.end()) { - if (i->transaction != t) { - ++i; - continue; - } - // Aborted transactional dequeues result in the message remaining - // enqueued like before the operation; enqueues clear the - // message from the where list - like the enqueue never happened. - if (i->disposition == MessageInfo::TRANSACTION_ENQUEUE) - i = p->where.erase(i); - else { - i->transaction.reset(); - ++i; - } - } - } - // If aborting results in this message having no further enqueue - // references, delete it. If the delete fails, swallow the exception - // and let recovery take care of removing it later. - if (p->where.empty()) { - try { - remove(msgId); - } - catch(...) {} - } -} - -// Load part or all of a message's content from previously stored -// log record(s). -void -Messages::loadContent(uint64_t msgId, - std::string& data, - uint64_t offset, - uint32_t length) -{ - log.loadContent(msgId, data, offset, length); -} - -// Recover the current set of messages and where they're queued from -// the log. -void -Messages::recover(qpid::broker::RecoveryManager& recoverer, - const std::set<uint64_t> &validQueues, - const std::map<uint64_t, Transaction::shared_ptr>& transMap, - qpid::store::MessageMap& messageMap, - qpid::store::MessageQueueMap& messageQueueMap) -{ - std::map<uint64_t, std::vector<MessageLog::RecoveredMsgOp> > messageOps; - log.recover(recoverer, messageMap, messageOps); - // Now read through the messageOps replaying the operations with the - // knowledge of which transactions committed, aborted, etc. A transaction - // should not be deleted until there are no messages referencing it so - // a message operation with a transaction id not found in transMap is - // a serious problem. - QPID_LOG(debug, "Beginning CLFS-recovered message operation replay"); - // Keep track of any messages that are recovered from the log but don't - // have any place to be. This can happen, for example, if the broker - // crashes while logging a message deletion. After all the recovery is - // done, delete all the homeless messages. - std::vector<uint64_t> homeless; - std::map<uint64_t, std::vector<MessageLog::RecoveredMsgOp> >::const_iterator msg; - for (msg = messageOps.begin(); msg != messageOps.end(); ++msg) { - uint64_t msgId = msg->first; - const std::vector<MessageLog::RecoveredMsgOp>& ops = msg->second; - QPID_LOG(debug, "Message " << msgId << "; " << ops.size() << " op(s)"); - MessageInfo::shared_ptr m(new MessageInfo); - std::vector<QueueEntry>& entries = messageQueueMap[msgId]; - std::vector<MessageLog::RecoveredMsgOp>::const_iterator op; - for (op = ops.begin(); op != ops.end(); ++op) { - QueueEntry entry(op->queueId); - MessageInfo::Location loc(op->queueId); - std::string dir = - op->op == MessageLog::RECOVERED_ENQUEUE ? "enqueue" - : "dequeue"; - if (validQueues.find(op->queueId) == validQueues.end()) { - QPID_LOG(info, - "Message " << msgId << dir << " on non-existant queue " - << op->queueId << "; dropped"); - continue; - } - if (op->txnId != 0) { - // Be sure to enroll this message in the transaction even if - // it has committed or aborted. This ensures that the - // transaction isn't removed from the log while finalizing the - // recovery. If it were to be removed and the broker failed - // again before removing this message during normal operation, - // it couldn't be recovered again. - // - // Recall what is being reconstructed; 2 things: - // 1. This class's 'messages' list which keeps track - // of the queues each message is on and the transactions - // each message is enrolled in. For this, aborted - // transactions cause the result of the operation to be - // ignored, but the message does need to be enrolled in - // the transaction to properly maintain the transaction - // references until the message is deleted. - // 2. The StorageProvider's MessageQueueMap, which also - // has an entry for each queue each message is on and - // its TPL status and associated xid. - const Transaction::shared_ptr &t = - transMap.find(op->txnId)->second; - // Prepared transactions cause the operation to be - // provisionally acted on, and the message to be enrolled in - // the transaction for when it commits/aborts. This is - // noted in the QueueEntry for the StorageProvider's map. - if (t->getState() == Transaction::TRANS_PREPARED) { - QPID_LOG(debug, dir << " for queue " << op->queueId << - ", prepared txn " << op->txnId); - TPCTransaction::shared_ptr tpct(boost::dynamic_pointer_cast<TPCTransaction>(t)); - if (tpct.get() == 0) - THROW_STORE_EXCEPTION("Invalid transaction state"); - t->enroll(msgId); - entry.xid = tpct->getXid(); - loc.transaction = t; - if (op->op == MessageLog::RECOVERED_ENQUEUE) { - entry.tplStatus = QueueEntry::ADDING; - loc.disposition = MessageInfo::TRANSACTION_ENQUEUE; - } - else { - entry.tplStatus = QueueEntry::REMOVING; - loc.disposition = MessageInfo::TRANSACTION_DEQUEUE; - } - } - else if (t->getState() != Transaction::TRANS_COMMITTED) { - QPID_LOG(debug, dir << " for queue " << op->queueId << - ", txn " << op->txnId << ", rolling back"); - continue; - } - } - // Here for non-transactional and prepared transactional operations - // to set up the messageQueueMap entries. Note that at this point - // a committed transactional operation looks like a - // non-transactional one as far as the QueueEntry is - // concerned - just do it. If this is an entry enqueuing a - // message, just add it to the entries list. If it's a dequeue - // operation, locate the matching entry for the queue and delete - // it if the current op is non-transactional; if it's a prepared - // transaction then replace the existing entry with the current - // one that notes the message is enqueued but being removed under - // a prepared transaction. - QPID_LOG(debug, dir + " at queue " << entry.queueId); - if (op->op == MessageLog::RECOVERED_ENQUEUE) { - entries.push_back(entry); - m->where.push_back(loc); - } - else { - std::vector<QueueEntry>::iterator i = entries.begin(); - while (i != entries.end()) { - if (i->queueId == entry.queueId) { - if (entry.tplStatus != QueueEntry::NONE) - *i = entry; - else - entries.erase(i); - break; - } - ++i; - } - std::list<MessageInfo::Location>::iterator w = m->where.begin(); - while (w != m->where.end()) { - if (w->queueId == loc.queueId) { - if (loc.transaction.get() != 0) { - *w = loc; - ++w; - } - else { - w = m->where.erase(w); - } - } - } - } - } - // Now that all the queue entries have been set correctly, see if - // there are any entries; they may have all been removed during - // recovery. If there are none, add this message to the homeless - // list to be deleted from the log after the recovery is done. - if (m->where.size() == 0) { - homeless.push_back(msgId); - messageMap.erase(msgId); - messageQueueMap.erase(msgId); - } - else { - std::pair<uint64_t, MessageInfo::shared_ptr> p(msgId, m); - messages.insert(p); - } - } - - QPID_LOG(debug, "Message log recovery done."); - // Done! Ok, go back and delete all the homeless messages. - BOOST_FOREACH(uint64_t msg, homeless) { - QPID_LOG(debug, "Deleting homeless message " << msg); - remove(msg); - } -} - -// Expunge is called when a queue is deleted. All references to that -// queue must be expunged from all messages. 'Dequeue' log records are -// written for each queue entry removed, but any errors are swallowed. -// On recovery there's a list of valid queues passed in. The deleted -// queue will not be on that list so if any references to it are -// recovered they'll get weeded out then. -void -Messages::expunge(uint64_t queueId) -{ - std::vector<uint64_t> toBeDeleted; // Messages to be deleted later. - - { - // Lock everybody out since all messages are possibly in play. - // There also may be other threads already working on particular - // messages so individual message mutex still must be acquired. - qpid::sys::ScopedWlock<qpid::sys::RWlock> l(lock); - MessageMap::iterator m; - for (m = messages.begin(); m != messages.end(); ++m) { - MessageInfo::shared_ptr p = m->second; - { - qpid::sys::ScopedLock<qpid::sys::Mutex> ml(p->whereLock); - std::list<MessageInfo::Location>::iterator i = p->where.begin(); - while (i != p->where.end()) { - if (i->queueId != queueId) { - ++i; - continue; - } - // If this entry is involved in a transaction, unenroll it. - // Then remove the entry. - if (i->transaction.get() != 0) - i->transaction->unenroll(m->first); - i = p->where.erase(i); - try { - log.recordDequeue(m->first, queueId, 0); - } - catch(...) { - } - } - if (p->where.size() == 0) - toBeDeleted.push_back(m->first); - } - } - } - // Swallow any exceptions during this; don't care. Recover it later - // if needed. - try { - BOOST_FOREACH(uint64_t msg, toBeDeleted) - remove(msg); - } - catch(...) { - } -} - -// Remove a specified message from those controlled by this object. -void -Messages::remove(uint64_t messageId) -{ - uint64_t newFirstId = 0; - { - qpid::sys::ScopedWlock<qpid::sys::RWlock> l(lock); - messages.erase(messageId); - // May have deleted the first entry; if so the log can release that. - // If this message being deleted results in an empty list of - // messages, move the tail up to this message's LSN. This may - // result in one or more messages being stranded in the log - // until there's more activity. If a restart happens while these - // unneeded log records are there, the presence of the MessageDelete - // entry will cause the message(s) to be ignored anyway. - if (messages.empty()) - newFirstId = messageId; - else if (messages.begin()->first > messageId) - newFirstId = messages.begin()->first; - } - log.deleteMessage(messageId, newFirstId); -} - -}}} // namespace qpid::store::ms_clfs diff --git a/cpp/src/qpid/store/ms-clfs/Messages.h b/cpp/src/qpid/store/ms-clfs/Messages.h deleted file mode 100644 index 93cc8bfe62..0000000000 --- a/cpp/src/qpid/store/ms-clfs/Messages.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_MESSAGES_H -#define QPID_STORE_MSCLFS_MESSAGES_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <windows.h> -#include <map> -#include <set> -#include <vector> -#include <boost/intrusive_ptr.hpp> -#include <qpid/broker/PersistableMessage.h> -#include <qpid/sys/Mutex.h> - -#include "MessageLog.h" -#include "Transaction.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -class Messages { - - struct MessageInfo { - // How many queues this message is on, whether actually (non-transacted) - // or provisionally (included in a non-yet-committed transaction). - volatile LONG enqueuedCount; - - // Keep a list of transactional operations this message is - // referenced in. When the transaction changes/finalizes these all - // need to be acted on. - typedef enum { TRANSACTION_NONE = 0, - TRANSACTION_ENQUEUE, - TRANSACTION_DEQUEUE } TransType; -#if 0 - std::map<Transaction::shared_ptr, std::vector<TransType> > transOps; - qpid::sys::Mutex transOpsLock; -#endif - // Think what I need is a list of "where is this message" - queue id, - // transaction ref, what kind of trans op (enq/deq). Then "remove all - // queue refs" can search through all messages looking for queue ids - // and undo them. Write "remove from queue" record to log. Also need to - // add "remove from queue" to recovery. - struct Location { - uint64_t queueId; - Transaction::shared_ptr transaction; - TransType disposition; - - Location(uint64_t q) - : queueId(q), transaction(), disposition(TRANSACTION_NONE) {} - Location(uint64_t q, Transaction::shared_ptr& t, TransType d) - : queueId(q), transaction(t), disposition(d) {} - }; - qpid::sys::Mutex whereLock; - std::list<Location> where; - // The transactions vector just keeps a shared_ptr to each - // Transaction this message was involved in, regardless of the - // disposition or transaction state. Keeping a valid shared_ptr - // prevents the Transaction from being deleted. As long as there - // are any messages that referred to a transaction, that - // transaction's state needs to be known so the message disposition - // can be correctly recovered if needed. - std::vector<Transaction::shared_ptr> transactions; - - typedef boost::shared_ptr<MessageInfo> shared_ptr; - - MessageInfo() : enqueuedCount(0) {} - }; - - qpid::sys::RWlock lock; - typedef std::map<uint64_t, MessageInfo::shared_ptr> MessageMap; - MessageMap messages; - MessageLog log; - - // Remove a specified message from those controlled by this object. - void remove(uint64_t messageId); - -public: - void openLog(const std::string& path, const Log::TuningParameters& params); - - // Add the specified message to the log and list of known messages. - // Upon successful return the message's persistenceId is set. - void add(const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg); - - // Add the specified queue to the message's list of places it is - // enqueued. - void enqueue(uint64_t msgId, uint64_t queueId, Transaction::shared_ptr& t); - - // Remove the specified queue from the message's list of places it is - // enqueued. If there are no other queues holding the message, it is - // deleted. - void dequeue(uint64_t msgId, uint64_t queueId, Transaction::shared_ptr& t); - - // Commit a previous provisional enqueue or dequeue of a particular message - // actions under a specified transaction. If this results in the message's - // being removed from all queues, it is deleted. - void commit(uint64_t msgId, Transaction::shared_ptr& transaction); - - // Abort a previous provisional enqueue or dequeue of a particular message - // actions under a specified transaction. If this results in the message's - // being removed from all queues, it is deleted. - void abort(uint64_t msgId, Transaction::shared_ptr& transaction); - - // Load part or all of a message's content from previously stored - // log record(s). - void loadContent(uint64_t msgId, - std::string& data, - uint64_t offset, - uint32_t length); - - // Expunge is called when a queue is deleted. All references to that - // queue must be expunged from all messages. - void expunge(uint64_t queueId); - - // Recover the current set of messages and where they're queued from - // the log. - void recover(qpid::broker::RecoveryManager& recoverer, - const std::set<uint64_t> &validQueues, - const std::map<uint64_t, Transaction::shared_ptr>& transMap, - qpid::store::MessageMap& messageMap, - qpid::store::MessageQueueMap& messageQueueMap); -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_MESSAGES_H */ diff --git a/cpp/src/qpid/store/ms-clfs/Transaction.cpp b/cpp/src/qpid/store/ms-clfs/Transaction.cpp deleted file mode 100644 index f94fef6f84..0000000000 --- a/cpp/src/qpid/store/ms-clfs/Transaction.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "Transaction.h" -#include "Messages.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -Transaction::~Transaction() -{ - // Transactions that are recovered then found to be deleted get destroyed - // but need not be logged. - if (state != TRANS_DELETED) - log->deleteTransaction(id); -} - -void -Transaction::enroll(uint64_t msgId) -{ - qpid::sys::ScopedWlock<qpid::sys::RWlock> l(enrollLock); - enrolledMessages.push_back(msgId); -} - -void -Transaction::unenroll(uint64_t msgId) -{ - qpid::sys::ScopedWlock<qpid::sys::RWlock> l(enrollLock); - for (std::vector<uint64_t>::iterator i = enrolledMessages.begin(); - i < enrolledMessages.end(); - ++i) { - if (*i == msgId) { - enrolledMessages.erase(i); - break; - } - } -} - -void -Transaction::abort(Messages& messages) -{ - log->recordAbort(id); - for (size_t i = 0; i < enrolledMessages.size(); ++i) - messages.abort(enrolledMessages[i], shared_from_this()); - state = TRANS_ABORTED; -} - -void -Transaction::commit(Messages& messages) -{ - log->recordCommit(id); - for (size_t i = 0; i < enrolledMessages.size(); ++i) - messages.commit(enrolledMessages[i], shared_from_this()); - state = TRANS_COMMITTED; -} - -void -TPCTransaction::prepare(void) -{ - log->recordPrepare(id); - state = TRANS_PREPARED; -} - -}}} // namespace qpid::store::ms_clfs diff --git a/cpp/src/qpid/store/ms-clfs/Transaction.h b/cpp/src/qpid/store/ms-clfs/Transaction.h deleted file mode 100644 index fd07f2fb2e..0000000000 --- a/cpp/src/qpid/store/ms-clfs/Transaction.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_TRANSACTION_H -#define QPID_STORE_MSCLFS_TRANSACTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/broker/TransactionalStore.h> -#include <qpid/sys/Mutex.h> -#include <boost/enable_shared_from_this.hpp> -#include <boost/shared_ptr.hpp> -#include <string> - -#include "TransactionLog.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -class Messages; - -/** - * @class Transaction - * - * Class representing an AMQP transaction. This is used around a set of - * enqueue and dequeue operations that occur when the broker is acting - * on a transaction commit/abort from the client. - * This class is what the store uses internally to implement things a - * transaction needs; the broker knows about TransactionContext, which - * holds a pointer to Transaction. - * - * NOTE: All references to Transactions (and TPCTransactions, below) are - * through Boost shared_ptr instances. All messages enrolled in a transaction - * hold a shared_ptr. Thus, a Transaction object will not be deleted until all - * messages holding a reference to it are deleted. This fact is also used - * during recovery to automatically clean up and delete any Transaction without - * messages left referring to it. - */ -class Transaction : public boost::enable_shared_from_this<Transaction> { -private: - // TransactionLog has to create all Transaction instances. - Transaction() {} - -public: - - typedef boost::shared_ptr<Transaction> shared_ptr; - typedef enum { TRANS_OPEN = 1, - TRANS_PREPARED, - TRANS_ABORTED, - TRANS_COMMITTED, - TRANS_DELETED } State; - - virtual ~Transaction(); - - uint64_t getId() { return id; } - State getState() { return state; } - - void enroll(uint64_t msgId); - void unenroll(uint64_t msgId); // For failed ops, not normal end-of-trans - - void abort(Messages& messages); - void commit(Messages& messages); - -protected: - friend class TransactionLog; - Transaction(uint64_t _id, const TransactionLog::shared_ptr& _log) - : id(_id), state(TRANS_OPEN), log(_log) {} - - uint64_t id; - State state; - TransactionLog::shared_ptr log; - std::vector<uint64_t> enrolledMessages; - qpid::sys::RWlock enrollLock; -}; - -class TransactionContext : public qpid::broker::TransactionContext { - Transaction::shared_ptr transaction; - -public: - TransactionContext(const Transaction::shared_ptr& _transaction) - : transaction(_transaction) {} - - virtual Transaction::shared_ptr& getTransaction() { return transaction; } -}; - -/** - * @class TPCTransaction - * - * Class representing a Two-Phase-Commit (TPC) AMQP transaction. This is - * used around a set of enqueue and dequeue operations that occur when the - * broker is acting on a transaction prepare/commit/abort from the client. - * This class is what the store uses internally to implement things a - * transaction needs; the broker knows about TPCTransactionContext, which - * holds a pointer to TPCTransaction. - */ -class TPCTransaction : public Transaction { - - friend class TransactionLog; - TPCTransaction(uint64_t _id, - const TransactionLog::shared_ptr& _log, - const std::string& _xid) - : Transaction(_id, _log), xid(_xid) {} - - std::string xid; - -public: - typedef boost::shared_ptr<TPCTransaction> shared_ptr; - - virtual ~TPCTransaction() {} - - void prepare(); - bool isPrepared() const { return state == TRANS_PREPARED; } - - const std::string& getXid(void) const { return xid; } -}; - -class TPCTransactionContext : public qpid::broker::TPCTransactionContext { - TPCTransaction::shared_ptr transaction; - -public: - TPCTransactionContext(const TPCTransaction::shared_ptr& _transaction) - : transaction(_transaction) {} - - virtual TPCTransaction::shared_ptr& getTransaction() { return transaction; } -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_TRANSACTION_H */ diff --git a/cpp/src/qpid/store/ms-clfs/TransactionLog.cpp b/cpp/src/qpid/store/ms-clfs/TransactionLog.cpp deleted file mode 100644 index 04780e83e8..0000000000 --- a/cpp/src/qpid/store/ms-clfs/TransactionLog.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <windows.h> -#include <clfsw32.h> -#include <exception> -#include <malloc.h> -#include <memory.h> -#include <qpid/framing/Buffer.h> -#include <qpid/log/Statement.h> -#include <qpid/sys/IntegerTypes.h> -#include <qpid/sys/windows/check.h> - -#include "TransactionLog.h" -#include "Transaction.h" -#include "Lsn.h" - -namespace { - -// Structures that hold log records. Each has a type field at the start. -enum TransactionEntryType { - TransactionStartDtxEntry = 1, - TransactionStartTxEntry = 2, - TransactionPrepareEntry = 3, - TransactionCommitEntry = 4, - TransactionAbortEntry = 5, - TransactionDeleteEntry = 6 -}; -// The only thing that really takes up space in transaction records is the -// xid. Max xid length is in the neighborhood of 600 bytes. Leave some room. -static const uint32_t MaxTransactionContentLength = 1024; - -// Dtx-Start -struct TransactionStartDtx { - TransactionEntryType type; - uint32_t length; - char content[MaxTransactionContentLength]; - - TransactionStartDtx() - : type(TransactionStartDtxEntry), length(0) {} -}; -// Tx-Start -struct TransactionStartTx { - TransactionEntryType type; - - TransactionStartTx() - : type(TransactionStartTxEntry) {} -}; -// Prepare -struct TransactionPrepare { - TransactionEntryType type; - - TransactionPrepare() - : type(TransactionPrepareEntry) {} -}; -// Commit -struct TransactionCommit { - TransactionEntryType type; - - TransactionCommit() - : type(TransactionCommitEntry) {} -}; -// Abort -struct TransactionAbort { - TransactionEntryType type; - - TransactionAbort() - : type(TransactionAbortEntry) {} -}; -// Delete -struct TransactionDelete { - TransactionEntryType type; - - TransactionDelete() - : type(TransactionDeleteEntry) {} -}; - -} // namespace - -namespace qpid { -namespace store { -namespace ms_clfs { - -void -TransactionLog::initialize() -{ - // Write something to occupy the first record, preventing a real - // transaction from being lsn/id 0. Delete of a non-existant id is easily - // tossed during recovery if no other transactions have caused the tail - // to be moved up past this dummy record by then. - deleteTransaction(0); -} - -uint32_t -TransactionLog::marshallingBufferSize() -{ - size_t biggestNeed = sizeof(TransactionStartDtx); - uint32_t defSize = static_cast<uint32_t>(biggestNeed); - uint32_t minSize = Log::marshallingBufferSize(); - if (defSize <= minSize) - return minSize; - // Round up to multiple of minSize - return (defSize + minSize) / minSize * minSize; -} - -// Get a new Transaction -boost::shared_ptr<Transaction> -TransactionLog::begin() -{ - TransactionStartTx entry; - CLFS_LSN location; - uint64_t id; - uint32_t entryLength = static_cast<uint32_t>(sizeof(entry)); - location = write(&entry, entryLength); - try { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(idsLock); - id = lsnToId(location); - std::auto_ptr<Transaction> t(new Transaction(id, shared_from_this())); - boost::shared_ptr<Transaction> t2(t); - boost::weak_ptr<Transaction> weak_t2(t2); - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(idsLock); - validIds[id] = weak_t2; - } - return t2; - } - catch(...) { - deleteTransaction(id); - throw; - } -} - -// Get a new TPCTransaction -boost::shared_ptr<TPCTransaction> -TransactionLog::begin(const std::string& xid) -{ - TransactionStartDtx entry; - CLFS_LSN location; - uint64_t id; - uint32_t entryLength = static_cast<uint32_t>(sizeof(entry)); - entry.length = static_cast<uint32_t>(xid.length()); - memcpy_s(entry.content, sizeof(entry.content), - xid.c_str(), xid.length()); - entryLength -= (sizeof(entry.content) - entry.length); - location = write(&entry, entryLength); - try { - id = lsnToId(location); - std::auto_ptr<TPCTransaction> t(new TPCTransaction(id, - shared_from_this(), - xid)); - boost::shared_ptr<TPCTransaction> t2(t); - boost::weak_ptr<Transaction> weak_t2(t2); - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(idsLock); - validIds[id] = weak_t2; - } - return t2; - } - catch(...) { - deleteTransaction(id); - throw; - } -} - -void -TransactionLog::recordPrepare(uint64_t transId) -{ - TransactionPrepare entry; - CLFS_LSN transLsn = idToLsn(transId); - write(&entry, sizeof(entry), &transLsn); -} - -void -TransactionLog::recordCommit(uint64_t transId) -{ - TransactionCommit entry; - CLFS_LSN transLsn = idToLsn(transId); - write(&entry, sizeof(entry), &transLsn); - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(idsLock); - validIds[transId].reset(); - } -} - -void -TransactionLog::recordAbort(uint64_t transId) -{ - TransactionAbort entry; - CLFS_LSN transLsn = idToLsn(transId); - write(&entry, sizeof(entry), &transLsn); - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(idsLock); - validIds[transId].reset(); - } -} - -void -TransactionLog::deleteTransaction(uint64_t transId) -{ - uint64_t newFirstId = 0; - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(idsLock); - validIds.erase(transId); - // May have deleted the first entry; if so the log can release that. - // If this deletion results in an empty list of transactions, - // move the tail up to this transaction's LSN. This may result in - // one or more transactions being stranded in the log until there's - // more activity. If a restart happens while these unneeded log - // records are there, the presence of the TransactionDelete - // entry will cause them to be ignored anyway. - if (validIds.empty()) - newFirstId = transId; - else if (validIds.begin()->first > transId) - newFirstId = validIds.begin()->first; - } - TransactionDelete deleteEntry; - CLFS_LSN transLsn = idToLsn(transId); - write(&deleteEntry, sizeof(deleteEntry), &transLsn); - if (newFirstId != 0) - moveTail(idToLsn(newFirstId)); -} - -void -TransactionLog::collectPreparedXids(std::map<std::string, TPCTransaction::shared_ptr>& preparedMap) -{ - // Go through all the known transactions; if the transaction is still - // valid (open or prepared) it will have weak_ptr to the Transaction. - // If it can be downcast and has a state of TRANS_PREPARED, add to the map. - qpid::sys::ScopedLock<qpid::sys::Mutex> l(idsLock); - std::map<uint64_t, boost::weak_ptr<Transaction> >::const_iterator i; - for (i = validIds.begin(); i != validIds.end(); ++i) { - Transaction::shared_ptr t = i->second.lock(); - if (t.get() == 0) - continue; - TPCTransaction::shared_ptr tpct(boost::dynamic_pointer_cast<TPCTransaction>(t)); - if (tpct.get() == 0) - continue; - if (tpct->state == Transaction::TRANS_PREPARED) - preparedMap[tpct->getXid()] = tpct; - } -} - -void -TransactionLog::recover(std::map<uint64_t, Transaction::shared_ptr>& transMap) -{ - QPID_LOG(debug, "Recovering transaction log"); - - // Note that there may be transaction refs in the log which are deleted, - // so be sure to only add transactions at Start records, and ignore those - // that don't have an existing message record. - // Get the base LSN - that's how to say "start reading at the beginning" - CLFS_INFORMATION info; - ULONG infoLength = sizeof (info); - BOOL ok = ::GetLogFileInformation(handle, &info, &infoLength); - QPID_WINDOWS_CHECK_NOT(ok, 0); - - // Pointers for the various record types that can be assigned in the - // reading loop below. - TransactionStartDtx *startDtxEntry; - TransactionStartTx *startTxEntry; - - PVOID recordPointer; - ULONG recordLength; - CLFS_RECORD_TYPE recordType = ClfsDataRecord; - CLFS_LSN transLsn, current, undoNext; - PVOID readContext; - uint64_t transId; - // Note 'current' in case it's needed below; ReadNextLogRecord returns it - // via a parameter. - current = info.BaseLsn; - ok = ::ReadLogRecord(marshal, - &info.BaseLsn, - ClfsContextForward, - &recordPointer, - &recordLength, - &recordType, - &undoNext, - &transLsn, - &readContext, - 0); - - std::auto_ptr<Transaction> tPtr; - std::auto_ptr<TPCTransaction> tpcPtr; - while (ok) { - std::string xid; - - // All the record types this class writes have a TransactionEntryType - // in the beginning. Based on that, do what's needed. - TransactionEntryType *t = - reinterpret_cast<TransactionEntryType *>(recordPointer); - switch(*t) { - case TransactionStartDtxEntry: - startDtxEntry = - reinterpret_cast<TransactionStartDtx *>(recordPointer); - transId = lsnToId(current); - QPID_LOG(debug, "Dtx start, id " << transId); - xid.assign(startDtxEntry->content, startDtxEntry->length); - tpcPtr.reset(new TPCTransaction(transId, shared_from_this(), xid)); - transMap[transId] = boost::shared_ptr<TPCTransaction>(tpcPtr); - break; - case TransactionStartTxEntry: - startTxEntry = - reinterpret_cast<TransactionStartTx *>(recordPointer); - transId = lsnToId(current); - QPID_LOG(debug, "Tx start, id " << transId); - tPtr.reset(new Transaction(transId, shared_from_this())); - transMap[transId] = boost::shared_ptr<Transaction>(tPtr); - break; - case TransactionPrepareEntry: - transId = lsnToId(transLsn); - QPID_LOG(debug, "Dtx prepare, id " << transId); - if (transMap.find(transId) == transMap.end()) { - QPID_LOG(debug, - "Dtx " << transId << " doesn't exist; discarded"); - } - else { - transMap[transId]->state = Transaction::TRANS_PREPARED; - } - break; - case TransactionCommitEntry: - transId = lsnToId(transLsn); - QPID_LOG(debug, "Txn commit, id " << transId); - if (transMap.find(transId) == transMap.end()) { - QPID_LOG(debug, - "Txn " << transId << " doesn't exist; discarded"); - } - else { - transMap[transId]->state = Transaction::TRANS_COMMITTED; - } - break; - case TransactionAbortEntry: - transId = lsnToId(transLsn); - QPID_LOG(debug, "Txn abort, id " << transId); - if (transMap.find(transId) == transMap.end()) { - QPID_LOG(debug, - "Txn " << transId << " doesn't exist; discarded"); - } - else { - transMap[transId]->state = Transaction::TRANS_ABORTED; - } - break; - case TransactionDeleteEntry: - transId = lsnToId(transLsn); - QPID_LOG(debug, "Txn delete, id " << transId); - if (transMap.find(transId) == transMap.end()) { - QPID_LOG(debug, - "Txn " << transId << " doesn't exist; discarded"); - } - else { - transMap[transId]->state = Transaction::TRANS_DELETED; - transMap.erase(transId); - } - break; - default: - throw std::runtime_error("Bad transaction log entry type"); - } - - recordType = ClfsDataRecord; - ok = ::ReadNextLogRecord(readContext, - &recordPointer, - &recordLength, - &recordType, - 0, // No userLsn - &undoNext, - &transLsn, - ¤t, - 0); - } - DWORD status = ::GetLastError(); - ::TerminateReadLog(readContext); - if (status != ERROR_HANDLE_EOF) // No more records - throw QPID_WINDOWS_ERROR(status); - - QPID_LOG(debug, "Transaction log recovered"); - - // At this point we have a list of all the not-deleted transactions that - // were in existence when the broker last ran. All transactions of both - // Dtx and Tx types that haven't prepared or committed will be aborted. - // This will give the proper background against which to decide each - // message's disposition when recovering messages that were involved in - // transactions. - // In addition to recovering and aborting transactions, rebuild the - // validIds map now that we know which ids are really valid. - std::map<uint64_t, Transaction::shared_ptr>::const_iterator i; - for (i = transMap.begin(); i != transMap.end(); ++i) { - switch(i->second->state) { - case Transaction::TRANS_OPEN: - QPID_LOG(debug, "Txn " << i->first << " was open; aborted"); - i->second->state = Transaction::TRANS_ABORTED; - break; - case Transaction::TRANS_ABORTED: - QPID_LOG(debug, "Txn " << i->first << " was aborted"); - break; - case Transaction::TRANS_COMMITTED: - QPID_LOG(debug, "Txn " << i->first << " was committed"); - break; - case Transaction::TRANS_PREPARED: - QPID_LOG(debug, "Txn " << i->first << " was prepared"); - break; - case Transaction::TRANS_DELETED: - QPID_LOG(error, - "Txn " << i->first << " was deleted; shouldn't be here"); - break; - } - boost::weak_ptr<Transaction> weak_txn(i->second); - validIds[i->first] = weak_txn; - } -} - -}}} // namespace qpid::store::ms_clfs diff --git a/cpp/src/qpid/store/ms-clfs/TransactionLog.h b/cpp/src/qpid/store/ms-clfs/TransactionLog.h deleted file mode 100644 index 7ca27c229e..0000000000 --- a/cpp/src/qpid/store/ms-clfs/TransactionLog.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef QPID_STORE_MSCLFS_TRANSACTIONLOG_H -#define QPID_STORE_MSCLFS_TRANSACTIONLOG_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <set> - -#include <boost/enable_shared_from_this.hpp> -#include <boost/shared_ptr.hpp> - -#include <qpid/broker/RecoveryManager.h> -#include <qpid/sys/IntegerTypes.h> -#include <qpid/sys/Mutex.h> - -#include "Log.h" - -namespace qpid { -namespace store { -namespace ms_clfs { - -class Transaction; -class TPCTransaction; - -/** - * @class TransactionLog - * - * Represents a CLFS-housed transaction log. - */ -class TransactionLog : public Log, - public boost::enable_shared_from_this<TransactionLog> { - - // To know when it's ok to move the log tail the lowest valid Id must - // always be known. Keep track of valid Ids here. These are transactions - // which have not yet been Deleted in the log. They may be new, in progress, - // prepared, committed, or aborted - but not deleted. - // Entries corresponding to not-yet-finalized transactions (i.e., open or - // prepared) also have a weak_ptr so the Transaction can be accessed. - // This is primarily to check its state and get a list of prepared Xids. - std::map<uint64_t, boost::weak_ptr<Transaction> > validIds; - qpid::sys::Mutex idsLock; - -protected: - // Transaction log needs to have a no-op first record written in the log - // to ensure that no real transaction gets an ID 0; messages think trans - // id 0 means "no transaction." - virtual void initialize(); - -public: - // Inherited and reimplemented from Log. Figure the minimum marshalling - // buffer size needed for the records this class writes. - virtual uint32_t marshallingBufferSize(); - - typedef boost::shared_ptr<TransactionLog> shared_ptr; - - // Get a new Transaction - boost::shared_ptr<Transaction> begin(); - - // Get a new TPCTransaction - boost::shared_ptr<TPCTransaction> begin(const std::string& xid); - - void recordPrepare(uint64_t transId); - void recordCommit(uint64_t transId); - void recordAbort(uint64_t transId); - void deleteTransaction(uint64_t transId); - - // Fill @arg preparedMap with Xid->TPCTransaction::shared_ptr for all - // currently prepared transactions. - void collectPreparedXids(std::map<std::string, boost::shared_ptr<TPCTransaction> >& preparedMap); - - // Recover the transactions and their state from the log. - // Every non-deleted transaction recovered from the log will be - // represented in @arg transMap. The recovering messages can use this - // information to tell if a transaction referred to in an enqueue/dequeue - // operation should be recovered or dropped by examining transaction state. - // - // @param recoverer Recovery manager used to recreate broker objects from - // entries recovered from the log. - // @param transMap This method fills in the map of id -> shared_ptr of - // recovered transactions. - void recover(std::map<uint64_t, boost::shared_ptr<Transaction> >& transMap); -}; - -}}} // namespace qpid::store::ms_clfs - -#endif /* QPID_STORE_MSCLFS_TRANSACTIONLOG_H */ diff --git a/cpp/src/qpid/store/ms-sql/AmqpTransaction.cpp b/cpp/src/qpid/store/ms-sql/AmqpTransaction.cpp deleted file mode 100644 index 095d1bf331..0000000000 --- a/cpp/src/qpid/store/ms-sql/AmqpTransaction.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "AmqpTransaction.h" -#include "DatabaseConnection.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -AmqpTransaction::AmqpTransaction(const boost::shared_ptr<DatabaseConnection>& _db) - : db(_db), sqlTrans(_db) -{ -} - -AmqpTransaction::~AmqpTransaction() -{ -} - -void -AmqpTransaction::sqlBegin() -{ - sqlTrans.begin(); -} - -void -AmqpTransaction::sqlCommit() -{ - sqlTrans.commit(); -} - -void -AmqpTransaction::sqlAbort() -{ - sqlTrans.abort(); -} - - -AmqpTPCTransaction::AmqpTPCTransaction(const boost::shared_ptr<DatabaseConnection>& db, - const std::string& _xid) - : AmqpTransaction(db), prepared(false), xid(_xid) -{ -} - -AmqpTPCTransaction::~AmqpTPCTransaction() -{ -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/AmqpTransaction.h b/cpp/src/qpid/store/ms-sql/AmqpTransaction.h deleted file mode 100644 index 625fab5595..0000000000 --- a/cpp/src/qpid/store/ms-sql/AmqpTransaction.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef QPID_STORE_MSSQL_AMQPTRANSACTION_H -#define QPID_STORE_MSSQL_AMQPTRANSACTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/broker/TransactionalStore.h> -#include <boost/shared_ptr.hpp> -#include <string> - -#include "SqlTransaction.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -class DatabaseConnection; - -/** - * @class AmqpTransaction - * - * Class representing an AMQP transaction. This is used around a set of - * enqueue and dequeue operations that occur when the broker is acting - * on a transaction commit/abort from the client. - */ -class AmqpTransaction : public qpid::broker::TransactionContext { - - boost::shared_ptr<DatabaseConnection> db; - SqlTransaction sqlTrans; - -public: - AmqpTransaction(const boost::shared_ptr<DatabaseConnection>& _db); - virtual ~AmqpTransaction(); - - DatabaseConnection *dbConn() { return db.get(); } - - void sqlBegin(); - void sqlCommit(); - void sqlAbort(); -}; - -/** - * @class AmqpTPCTransaction - * - * Class representing a Two-Phase-Commit (TPC) AMQP transaction. This is - * used around a set of enqueue and dequeue operations that occur when the - * broker is acting on a transaction prepare/commit/abort from the client. - */ -class AmqpTPCTransaction : public AmqpTransaction, - public qpid::broker::TPCTransactionContext { - bool prepared; - std::string xid; - -public: - AmqpTPCTransaction(const boost::shared_ptr<DatabaseConnection>& db, - const std::string& _xid); - virtual ~AmqpTPCTransaction(); - - void setPrepared(void) { prepared = true; } - bool isPrepared(void) const { return prepared; } - - const std::string& getXid(void) const { return xid; } -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_AMQPTRANSACTION_H */ diff --git a/cpp/src/qpid/store/ms-sql/BindingRecordset.cpp b/cpp/src/qpid/store/ms-sql/BindingRecordset.cpp deleted file mode 100644 index 1dc4370312..0000000000 --- a/cpp/src/qpid/store/ms-sql/BindingRecordset.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/Exception.h> -#include <qpid/log/Statement.h> - -#include "BindingRecordset.h" -#include "BlobAdapter.h" -#include "BlobEncoder.h" -#include "VariantHelper.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -void -BindingRecordset::removeFilter(const std::string& filter) -{ - rs->PutFilter (VariantHelper<std::string>(filter)); - long recs = rs->GetRecordCount(); - if (recs == 0) - return; // Nothing to do - while (recs > 0) { - // Deleting adAffectAll doesn't work as documented; go one by one. - rs->Delete(adAffectCurrent); - if (--recs > 0) - rs->MoveNext(); - } - rs->Update(); -} - -void -BindingRecordset::add(uint64_t exchangeId, - uint64_t queueId, - const std::string& routingKey, - const qpid::framing::FieldTable& args) -{ - VariantHelper<std::string> routingKeyStr(routingKey); - BlobEncoder blob (args); // Marshall field table to a blob - rs->AddNew(); - rs->Fields->GetItem("exchangeId")->Value = exchangeId; - rs->Fields->GetItem("queueId")->Value = queueId; - rs->Fields->GetItem("routingKey")->Value = routingKeyStr; - rs->Fields->GetItem("fieldTableBlob")->AppendChunk(blob); - rs->Update(); -} - -void -BindingRecordset::remove(uint64_t exchangeId, - uint64_t queueId, - const std::string& routingKey, - const qpid::framing::FieldTable& /*args*/) -{ - // Look up the affected binding. - std::ostringstream filter; - filter << "exchangeId = " << exchangeId - << " AND queueId = " << queueId - << " AND routingKey = '" << routingKey << "'" << std::ends; - removeFilter(filter.str()); -} - -void -BindingRecordset::removeForExchange(uint64_t exchangeId) -{ - // Look up the affected bindings by the exchange ID - std::ostringstream filter; - filter << "exchangeId = " << exchangeId << std::ends; - removeFilter(filter.str()); -} - -void -BindingRecordset::removeForQueue(uint64_t queueId) -{ - // Look up the affected bindings by the queue ID - std::ostringstream filter; - filter << "queueId = " << queueId << std::ends; - removeFilter(filter.str()); -} - -void -BindingRecordset::recover(broker::RecoveryManager& recoverer, - const store::ExchangeMap& exchMap, - const store::QueueMap& queueMap) -{ - if (rs->BOF && rs->EndOfFile) - return; // Nothing to do - rs->MoveFirst(); - Binding b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - while (!rs->EndOfFile) { - long blobSize = rs->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = rs->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - store::ExchangeMap::const_iterator exch = exchMap.find(b.exchangeId); - if (exch == exchMap.end()) { - std::ostringstream msg; - msg << "Error recovering bindings; exchange ID " << b.exchangeId - << " not found in exchange map"; - throw qpid::Exception(msg.str()); - } - broker::RecoverableExchange::shared_ptr exchPtr = exch->second; - store::QueueMap::const_iterator q = queueMap.find(b.queueId); - if (q == queueMap.end()) { - std::ostringstream msg; - msg << "Error recovering bindings; queue ID " << b.queueId - << " not found in queue map"; - throw qpid::Exception(msg.str()); - } - broker::RecoverableQueue::shared_ptr qPtr = q->second; - // The recovery manager wants the queue name, so get it from the - // RecoverableQueue. - std::string key(b.routingKey); - exchPtr->bind(qPtr->getName(), key, blob); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -void -BindingRecordset::dump() -{ - Recordset::dump(); - if (rs->EndOfFile && rs->BOF) // No records - return; - rs->MoveFirst(); - - Binding b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - - while (VARIANT_FALSE == rs->EndOfFile) { - QPID_LOG(notice, "exch Id " << b.exchangeId - << ", q Id " << b.queueId - << ", k: " << b.routingKey); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/BindingRecordset.h b/cpp/src/qpid/store/ms-sql/BindingRecordset.h deleted file mode 100644 index 3cb732de75..0000000000 --- a/cpp/src/qpid/store/ms-sql/BindingRecordset.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef QPID_STORE_MSSQL_BINDINGRECORDSET_H -#define QPID_STORE_MSSQL_BINDINGRECORDSET_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <icrsint.h> -#include "Recordset.h" -#include <qpid/store/StorageProvider.h> -#include <qpid/broker/RecoveryManager.h> - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class BindingRecordset - * - * Class for the binding records. - */ -class BindingRecordset : public Recordset { - - class Binding : public CADORecordBinding { - BEGIN_ADO_BINDING(Binding) - ADO_FIXED_LENGTH_ENTRY2(1, adBigInt, exchangeId, FALSE) - ADO_FIXED_LENGTH_ENTRY2(2, adBigInt, queueId, FALSE) - ADO_VARIABLE_LENGTH_ENTRY4(3, adVarChar, routingKey, - sizeof(routingKey), FALSE) - END_ADO_BINDING() - - public: - uint64_t exchangeId; - uint64_t queueId; - char routingKey[256]; - }; - - // Remove all records matching the specified filter/query. - void removeFilter(const std::string& filter); - -public: - // Add a new binding - void add(uint64_t exchangeId, - uint64_t queueId, - const std::string& routingKey, - const qpid::framing::FieldTable& args); - - // Remove a specific binding - void remove(uint64_t exchangeId, - uint64_t queueId, - const std::string& routingKey, - const qpid::framing::FieldTable& args); - - // Remove all bindings for the specified exchange - void removeForExchange(uint64_t exchangeId); - - // Remove all bindings for the specified queue - void removeForQueue(uint64_t queueId); - - // Recover bindings set using exchMap to get from Id to RecoverableExchange. - void recover(qpid::broker::RecoveryManager& recoverer, - const qpid::store::ExchangeMap& exchMap, - const qpid::store::QueueMap& queueMap); - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_BINDINGRECORDSET_H */ diff --git a/cpp/src/qpid/store/ms-sql/BlobAdapter.cpp b/cpp/src/qpid/store/ms-sql/BlobAdapter.cpp deleted file mode 100644 index 1889f34e41..0000000000 --- a/cpp/src/qpid/store/ms-sql/BlobAdapter.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "BlobAdapter.h" -#include <qpid/Exception.h> - -namespace qpid { -namespace store { -namespace ms_sql { - -void -BlobAdapter::extractBuff() -{ - // To give a valid Buffer back, lock the safearray, obtaining a pointer to - // the actual data. Record the pointer in the Buffer so the destructor - // knows to unlock the safearray. - if (buff.getPointer() == 0) { - char *blob; - SafeArrayAccessData(this->parray, (void **)&blob); - qpid::framing::Buffer lockedBuff(blob, buff.getSize()); - buff = lockedBuff; - } -} - - -BlobAdapter::~BlobAdapter() -{ - // If buff's pointer is set, the safearray is locked, so unlock it - if (buff.getPointer() != 0) - SafeArrayUnaccessData(this->parray); -} - -BlobAdapter::operator qpid::framing::Buffer& () -{ - extractBuff(); - return buff; -} - -BlobAdapter::operator qpid::framing::FieldTable& () -{ - extractBuff(); - fields.decode(buff); - return fields; -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/BlobAdapter.h b/cpp/src/qpid/store/ms-sql/BlobAdapter.h deleted file mode 100644 index 1c666392bc..0000000000 --- a/cpp/src/qpid/store/ms-sql/BlobAdapter.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_STORE_MSSQL_BLOBADAPTER_H -#define QPID_STORE_MSSQL_BLOBADAPTER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <comutil.h> -#include <qpid/framing/Buffer.h> -#include <qpid/framing/FieldTable.h> - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class BlobAdapter - * - * Adapter for accessing a blob (varbinary SQL field) as a qpid::framing::Buffer - * in an exception-safe way. - */ -class BlobAdapter : public _variant_t { -private: - // This Buffer's pointer indicates whether or not a safearray has - // been locked; if it's 0, no locking was done. - qpid::framing::Buffer buff; - qpid::framing::FieldTable fields; - - void extractBuff(); - -public: - // Initialize with the known length of the data that will come. - // Assigning a _variant_t to this object will set up the array to be - // accessed with the operator Buffer&() - BlobAdapter(long blobSize) : _variant_t(), buff(0, blobSize) {} - ~BlobAdapter(); - BlobAdapter& operator=(_variant_t& var_t_Src) - { _variant_t::operator=(var_t_Src); return *this; } - operator qpid::framing::Buffer& (); - operator qpid::framing::FieldTable& (); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_BLOBADAPTER_H */ diff --git a/cpp/src/qpid/store/ms-sql/BlobEncoder.cpp b/cpp/src/qpid/store/ms-sql/BlobEncoder.cpp deleted file mode 100644 index 75d3dc2d86..0000000000 --- a/cpp/src/qpid/store/ms-sql/BlobEncoder.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "BlobEncoder.h" -#include <qpid/Exception.h> -#include <qpid/broker/Persistable.h> -#include <qpid/broker/PersistableMessage.h> -#include <boost/intrusive_ptr.hpp> -#include <memory.h> - -namespace qpid { -namespace store { -namespace ms_sql { - -template <class ITEM> void -BlobEncoder::encode(const ITEM &item) -{ - SAFEARRAYBOUND bound[1] = {0, 0}; - bound[0].cElements = item.encodedSize(); - blob = SafeArrayCreate(VT_UI1, 1, bound); - if (S_OK != SafeArrayLock(blob)) { - SafeArrayDestroy(blob); - blob = 0; - throw qpid::Exception("Error locking blob area for persistable item"); - } - try { - qpid::framing::Buffer buff((char *)blob->pvData, bound[0].cElements); - item.encode(buff); - } - catch(...) { - SafeArrayUnlock(blob); - SafeArrayDestroy(blob); - blob = 0; - throw; - } - this->vt = VT_ARRAY | VT_UI1; - this->parray = blob; - SafeArrayUnlock(blob); -} - -template <> void -BlobEncoder::encode(const boost::intrusive_ptr<qpid::broker::PersistableMessage> &item) -{ - // NOTE! If this code changes, verify the recovery code in MessageRecordset - SAFEARRAYBOUND bound[1] = {0, 0}; - bound[0].cElements = item->encodedSize() + sizeof(uint32_t); - blob = SafeArrayCreate(VT_UI1, 1, bound); - if (S_OK != SafeArrayLock(blob)) { - SafeArrayDestroy(blob); - blob = 0; - throw qpid::Exception("Error locking blob area for message"); - } - try { - uint32_t headerSize = item->encodedHeaderSize(); - qpid::framing::Buffer buff((char *)blob->pvData, bound[0].cElements); - buff.putLong(headerSize); - item->encode(buff); - } - catch(...) { - SafeArrayUnlock(blob); - SafeArrayDestroy(blob); - blob = 0; - throw; - } - this->vt = VT_ARRAY | VT_UI1; - this->parray = blob; - SafeArrayUnlock(blob); -} - -template <> void -BlobEncoder::encode(const std::string &item) -{ - SAFEARRAYBOUND bound[1] = {0, 0}; - bound[0].cElements = item.size(); - blob = SafeArrayCreate(VT_UI1, 1, bound); - if (S_OK != SafeArrayLock(blob)) { - SafeArrayDestroy(blob); - blob = 0; - throw qpid::Exception("Error locking blob area for string"); - } - memcpy_s(blob->pvData, item.size(), item.data(), item.size()); - this->vt = VT_ARRAY | VT_UI1; - this->parray = blob; - SafeArrayUnlock(blob); -} - -BlobEncoder::BlobEncoder(const qpid::broker::Persistable &item) : blob(0) -{ - encode(item); -} - -BlobEncoder::BlobEncoder(const boost::intrusive_ptr<qpid::broker::PersistableMessage> &msg) : blob(0) -{ - encode(msg); -} - -BlobEncoder::BlobEncoder(const qpid::framing::FieldTable &fields) : blob(0) -{ - encode(fields); -} - -BlobEncoder::BlobEncoder(const std::string &data) : blob(0) -{ - encode(data); -} - -BlobEncoder::~BlobEncoder() -{ - if (blob) - SafeArrayDestroy(blob); - blob = 0; - this->parray = 0; -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/BlobEncoder.h b/cpp/src/qpid/store/ms-sql/BlobEncoder.h deleted file mode 100644 index d2b56223c1..0000000000 --- a/cpp/src/qpid/store/ms-sql/BlobEncoder.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_STORE_MSSQL_BLOBENCODER_H -#define QPID_STORE_MSSQL_BLOBENCODER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <comutil.h> -#include <string> -#include <boost/intrusive_ptr.hpp> -#include <qpid/broker/Persistable.h> -#include <qpid/broker/PersistableMessage.h> -#include <qpid/framing/Buffer.h> -#include <qpid/framing/FieldTable.h> - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class BlobEncoder - * - * Encodes a blob (varbinary) field from a qpid::broker::Persistable or a - * qpid::framing::FieldTable (both of which can be encoded to - * qpid::framing::Buffer) so it can be passed to ADO methods for writing - * to the database. - */ -class BlobEncoder : public _variant_t { -private: - SAFEARRAY *blob; - - template <class ITEM> void encode(const ITEM &item); - -public: - BlobEncoder(const qpid::broker::Persistable &item); - BlobEncoder(const boost::intrusive_ptr<qpid::broker::PersistableMessage> &msg); - BlobEncoder(const qpid::framing::FieldTable &fields); - BlobEncoder(const std::string& data); - ~BlobEncoder(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_BLOBENCODER_H */ diff --git a/cpp/src/qpid/store/ms-sql/BlobRecordset.cpp b/cpp/src/qpid/store/ms-sql/BlobRecordset.cpp deleted file mode 100644 index ef1757dbad..0000000000 --- a/cpp/src/qpid/store/ms-sql/BlobRecordset.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/Exception.h> -#include <qpid/log/Statement.h> - -#include "BlobRecordset.h" -#include "BlobEncoder.h" -#include "VariantHelper.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -void -BlobRecordset::add(const qpid::broker::Persistable& item) -{ - BlobEncoder blob (item); // Marshall item info to a blob - rs->AddNew(); - rs->Fields->GetItem("fieldTableBlob")->AppendChunk(blob); - rs->Update(); - uint64_t id = rs->Fields->Item["persistenceId"]->Value; - item.setPersistenceId(id); -} - -void -BlobRecordset::remove(uint64_t id) -{ - // Look up the item by its persistenceId - std::ostringstream filter; - filter << "persistenceId = " << id << std::ends; - rs->PutFilter (VariantHelper<std::string>(filter.str())); - if (!rs->EndOfFile) { - // Delete the record - rs->Delete(adAffectCurrent); - rs->Update(); - } -} - -void -BlobRecordset::remove(const qpid::broker::Persistable& item) -{ - remove(item.getPersistenceId()); -} - -void -BlobRecordset::dump() -{ - Recordset::dump(); -#if 1 - if (rs->EndOfFile && rs->BOF) // No records - return; - - rs->MoveFirst(); - while (!rs->EndOfFile) { - uint64_t id = rs->Fields->Item["persistenceId"]->Value; - QPID_LOG(notice, " -> " << id); - rs->MoveNext(); - } -#else - for (Iterator iter = begin(); iter != end(); ++iter) { - uint64_t id = *iter.first; - QPID_LOG(notice, " -> " << id); - } -#endif -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/BlobRecordset.h b/cpp/src/qpid/store/ms-sql/BlobRecordset.h deleted file mode 100644 index 4d1c338746..0000000000 --- a/cpp/src/qpid/store/ms-sql/BlobRecordset.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_STORE_MSSQL_BLOBRECORDSET_H -#define QPID_STORE_MSSQL_BLOBRECORDSET_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "Recordset.h" -#include <qpid/broker/Persistable.h> -#include <string> - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class BlobRecordset - * - * Class for the "blob" records that record an id, varbinary(max) pair. - */ -class BlobRecordset : public Recordset { -protected: - -public: - void add(const qpid::broker::Persistable& item); - - // Remove a record given its Id. - void remove(uint64_t id); - void remove(const qpid::broker::Persistable& item); - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_BLOBRECORDSET_H */ diff --git a/cpp/src/qpid/store/ms-sql/DatabaseConnection.cpp b/cpp/src/qpid/store/ms-sql/DatabaseConnection.cpp deleted file mode 100644 index 3219ea526a..0000000000 --- a/cpp/src/qpid/store/ms-sql/DatabaseConnection.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "DatabaseConnection.h" -#include "Exception.h" -#include <comdef.h> -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; -} - -namespace qpid { -namespace store { -namespace ms_sql { - -DatabaseConnection::DatabaseConnection() : conn(0) -{ -} - -DatabaseConnection::~DatabaseConnection() -{ - close(); -} - -void -DatabaseConnection::open(const std::string& connectString, - const std::string& dbName) -{ - if (conn && conn->State == adStateOpen) - return; - std::string adoConnect = "Provider=SQLOLEDB;" + connectString; - try { - TESTHR(conn.CreateInstance(__uuidof(Connection))); - conn->ConnectionString = adoConnect.c_str(); - conn->Open("", "", "", adConnectUnspecified); - if (dbName.length() > 0) - conn->DefaultDatabase = dbName.c_str(); - } - catch(_com_error &e) { - close(); - throw ADOException("MSSQL can't open " + dbName + " at " + adoConnect, e); - } -} - -void -DatabaseConnection::close() -{ - if (conn && conn->State == adStateOpen) - conn->Close(); - conn = 0; -} - -std::string -DatabaseConnection::getErrors() -{ - long errCount = conn->Errors->Count; - if (errCount <= 0) - return ""; - // Collection ranges from 0 to nCount -1. - std::ostringstream messages; - ErrorPtr pErr = NULL; - for (long i = 0 ; i < errCount ; i++ ) { - if (i > 0) - messages << "\n"; - messages << "[" << i << "] "; - pErr = conn->Errors->GetItem(i); - messages << "Error " << pErr->Number << ": " - << (LPCSTR)pErr->Description; - } - messages << std::ends; - return messages.str(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/DatabaseConnection.h b/cpp/src/qpid/store/ms-sql/DatabaseConnection.h deleted file mode 100644 index 785d1587c5..0000000000 --- a/cpp/src/qpid/store/ms-sql/DatabaseConnection.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_STORE_MSSQL_DATABASECONNECTION_H -#define QPID_STORE_MSSQL_DATABASECONNECTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// Bring in ADO 2.8 (yes, I know it says "15", but that's it...) -#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ - no_namespace rename("EOF", "EndOfFile") - -#include <string> - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class DatabaseConnection - * - * Represents a connection to the SQL database. This class wraps the - * needed _ConnectionPtr for ADO as well as the needed COM initialization - * and cleanup that each thread requires. It is expected that this class - * will be maintained in thread-specific storage so it has no locks. - */ -class DatabaseConnection { -protected: - _ConnectionPtr conn; - -public: - DatabaseConnection(); - ~DatabaseConnection(); - void open(const std::string& connectString, - const std::string& dbName = ""); - void close(); - operator _ConnectionPtr () { return conn; } - - void beginTransaction() { conn->BeginTrans(); } - void commitTransaction() {conn->CommitTrans(); } - void rollbackTransaction() { conn->RollbackTrans(); } - - std::string getErrors(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_DATABASECONNECTION_H */ diff --git a/cpp/src/qpid/store/ms-sql/Exception.h b/cpp/src/qpid/store/ms-sql/Exception.h deleted file mode 100644 index 65ec3388ff..0000000000 --- a/cpp/src/qpid/store/ms-sql/Exception.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef QPID_STORE_MSSQL_EXCEPTION_H -#define QPID_STORE_MSSQL_EXCEPTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include <comdef.h> -#include <qpid/store/StorageProvider.h> - -namespace qpid { -namespace store { -namespace ms_sql { - -class Exception : public qpid::store::StorageProvider::Exception -{ -protected: - std::string text; -public: - Exception(const std::string& _text) : text(_text) {} - virtual ~Exception() {} - virtual const char* what() const throw() { return text.c_str(); } -}; - -class ADOException : public Exception -{ -public: - ADOException(const std::string& _text, - _com_error &e, - const std::string& providerErrors = "") - : Exception(_text) { - text += ": "; - text += e.ErrorMessage(); - IErrorInfo *i = e.ErrorInfo(); - if (i != 0) { - text += ": "; - _bstr_t wmsg = e.Description(); - text += (const char *)wmsg; - i->Release(); - } - if (providerErrors.length() > 0) - text += providerErrors; - } -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_EXCEPTION_H */ diff --git a/cpp/src/qpid/store/ms-sql/MSSqlProvider.cpp b/cpp/src/qpid/store/ms-sql/MSSqlProvider.cpp deleted file mode 100644 index 7f22db3d02..0000000000 --- a/cpp/src/qpid/store/ms-sql/MSSqlProvider.cpp +++ /dev/null @@ -1,1305 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <stdlib.h> -#include <string> -#include <windows.h> -#include <qpid/broker/RecoverableQueue.h> -#include <qpid/log/Statement.h> -#include <qpid/store/MessageStorePlugin.h> -#include <qpid/store/StorageProvider.h> -#include "AmqpTransaction.h" -#include "BlobAdapter.h" -#include "BlobRecordset.h" -#include "BindingRecordset.h" -#include "MessageMapRecordset.h" -#include "MessageRecordset.h" -#include "TplRecordset.h" -#include "DatabaseConnection.h" -#include "Exception.h" -#include "State.h" -#include "VariantHelper.h" - -// Bring in ADO 2.8 (yes, I know it says "15", but that's it...) -#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ - no_namespace rename("EOF", "EndOfFile") -#include <comdef.h> -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; - -// Table names -const std::string TblBinding("tblBinding"); -const std::string TblConfig("tblConfig"); -const std::string TblExchange("tblExchange"); -const std::string TblMessage("tblMessage"); -const std::string TblMessageMap("tblMessageMap"); -const std::string TblQueue("tblQueue"); -const std::string TblTpl("tblTPL"); -} - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class MSSqlProvider - * - * Implements a qpid::store::StorageProvider that uses Microsoft SQL Server as - * the backend data store for Qpid. - */ -class MSSqlProvider : public qpid::store::StorageProvider -{ -protected: - void finalizeMe(); - - void dump(); - -public: - MSSqlProvider(); - ~MSSqlProvider(); - - virtual qpid::Options* getOptions() { return &options; } - - virtual void earlyInitialize (Plugin::Target& target); - virtual void initialize(Plugin::Target& target); - - /** - * Receive notification that this provider is the one that will actively - * handle provider storage for the target. If the provider is to be used, - * this method will be called after earlyInitialize() and before any - * recovery operations (recovery, in turn, precedes call to initialize()). - */ - virtual void activate(MessageStorePlugin &store); - - /** - * @name Methods inherited from qpid::broker::MessageStore - */ - //@{ - /** - * If called after init() but before recovery, will discard the database - * and reinitialize using an empty store dir. If @a pushDownStoreFiles - * is true, the content of the store dir will be moved to a backup dir - * inside the store dir. This is used when cluster nodes recover and must - * get thier content from a cluster sync rather than directly fromt the - * store. - * - * @param pushDownStoreFiles If true, will move content of the store dir - * into a subdir, leaving the store dir - * otherwise empty. - */ - virtual void truncateInit(const bool pushDownStoreFiles = false); - - /** - * Record the existence of a durable queue - */ - virtual void create(PersistableQueue& queue, - const qpid::framing::FieldTable& args); - /** - * Destroy a durable queue - */ - virtual void destroy(PersistableQueue& queue); - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args); - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange); - - /** - * Record a binding - */ - virtual void bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - /** - * Forget a binding - */ - virtual void unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args); - - /** - * Record generic durable configuration - */ - virtual void create(const PersistableConfig& config); - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const PersistableConfig& config); - - /** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr<PersistableMessage>& msg); - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(PersistableMessage& msg); - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const std::string& data); - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr<const PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - - /** - * Flushes all async messages to disk for the specified queue - * - * Note: this is a no-op for this provider. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const PersistableQueue& queue) {}; - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue) - {return 0;} - //@} - - /** - * @name Methods inherited from qpid::broker::TransactionalStore - */ - //@{ - virtual std::auto_ptr<qpid::broker::TransactionContext> begin(); - virtual std::auto_ptr<qpid::broker::TPCTransactionContext> begin(const std::string& xid); - virtual void prepare(qpid::broker::TPCTransactionContext& txn); - virtual void commit(qpid::broker::TransactionContext& txn); - virtual void abort(qpid::broker::TransactionContext& txn); - virtual void collectPreparedXids(std::set<std::string>& xids); - //@} - - virtual void recoverConfigs(qpid::broker::RecoveryManager& recoverer); - virtual void recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap); - virtual void recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap); - virtual void recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap); - virtual void recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap); - virtual void recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap); - -private: - struct ProviderOptions : public qpid::Options - { - std::string connectString; - std::string catalogName; - - ProviderOptions(const std::string &name) - : qpid::Options(name), - catalogName("QpidStore") - { - const enum { NAMELEN = MAX_COMPUTERNAME_LENGTH + 1 }; - TCHAR myName[NAMELEN]; - DWORD myNameLen = NAMELEN; - GetComputerName(myName, &myNameLen); - connectString = "Data Source="; - connectString += myName; - connectString += "\\SQLEXPRESS;Integrated Security=SSPI"; - addOptions() - ("connect", - qpid::optValue(connectString, "STRING"), - "Connection string for the database to use. Will prepend " - "Provider=SQLOLEDB;") - ("catalog", - qpid::optValue(catalogName, "DB NAME"), - "Catalog (database) name") - ; - } - }; - ProviderOptions options; - - // Each thread has a separate connection to the database and also needs - // to manage its COM initialize/finalize individually. This is done by - // keeping a thread-specific State. - boost::thread_specific_ptr<State> dbState; - - State *initState(); - DatabaseConnection *initConnection(void); - void createDb(DatabaseConnection *db, const std::string &name); -}; - -static MSSqlProvider static_instance_registers_plugin; - -void -MSSqlProvider::finalizeMe() -{ - dbState.reset(); -} - -MSSqlProvider::MSSqlProvider() - : options("MS SQL Provider options") -{ -} - -MSSqlProvider::~MSSqlProvider() -{ -} - -void -MSSqlProvider::earlyInitialize(Plugin::Target &target) -{ - MessageStorePlugin *store = dynamic_cast<MessageStorePlugin *>(&target); - if (store) { - // If the database init fails, report it and don't register; give - // the rest of the broker a chance to run. - // - // Don't try to initConnection() since that will fail if the - // database doesn't exist. Instead, try to open a connection without - // a database name, then search for the database. There's still a - // chance this provider won't be selected for the store too, so be - // be sure to close the database connection before return to avoid - // leaving a connection up that will not be used. - try { - initState(); // This initializes COM - std::auto_ptr<DatabaseConnection> db(new DatabaseConnection()); - db->open(options.connectString, ""); - _ConnectionPtr conn(*db); - _RecordsetPtr pCatalogs = NULL; - VariantHelper<std::string> catalogName(options.catalogName); - pCatalogs = conn->OpenSchema(adSchemaCatalogs, catalogName); - if (pCatalogs->EndOfFile) { - // Database doesn't exist; create it - QPID_LOG(notice, - "MSSQL: Creating database " + options.catalogName); - createDb(db.get(), options.catalogName); - } - else { - QPID_LOG(notice, - "MSSQL: Database located: " + options.catalogName); - } - if (pCatalogs) { - if (pCatalogs->State == adStateOpen) - pCatalogs->Close(); - pCatalogs = 0; - } - db->close(); - store->providerAvailable("MSSQL", this); - } - catch (qpid::Exception &e) { - QPID_LOG(error, e.what()); - return; - } - store->addFinalizer(boost::bind(&MSSqlProvider::finalizeMe, this)); - } -} - -void -MSSqlProvider::initialize(Plugin::Target& target) -{ -} - -void -MSSqlProvider::activate(MessageStorePlugin &store) -{ - QPID_LOG(info, "MS SQL Provider is up"); -} - -void -MSSqlProvider::truncateInit(const bool pushDownStoreFiles) -{ -} - -void -MSSqlProvider::create(PersistableQueue& queue, - const qpid::framing::FieldTable& /*args needed for jrnl*/) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - try { - db->beginTransaction(); - rsQueues.open(db, TblQueue); - rsQueues.add(queue); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating queue " + queue.getName(), e, errs); - } -} - -/** - * Destroy a durable queue - */ -void -MSSqlProvider::destroy(PersistableQueue& queue) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsQueues; - BindingRecordset rsBindings; - MessageRecordset rsMessages; - MessageMapRecordset rsMessageMaps; - try { - db->beginTransaction(); - rsQueues.open(db, TblQueue); - rsBindings.open(db, TblBinding); - rsMessages.open(db, TblMessage); - rsMessageMaps.open(db, TblMessageMap); - // Remove bindings first; the queue IDs can't be ripped out from - // under the references in the bindings table. Then remove the - // message->queue entries for the queue, also because the queue can't - // be deleted while there are references to it. If there are messages - // orphaned by removing the queue references, they're deleted by - // a trigger on the tblMessageMap table. Lastly, the queue record - // can be removed. - rsBindings.removeForQueue(queue.getPersistenceId()); - rsMessageMaps.removeForQueue(queue.getPersistenceId()); - rsQueues.remove(queue); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting queue " + queue.getName(), e, errs); - } -} - -/** - * Record the existence of a durable exchange - */ -void -MSSqlProvider::create(const PersistableExchange& exchange, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - try { - db->beginTransaction(); - rsExchanges.open(db, TblExchange); - rsExchanges.add(exchange); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating exchange " + exchange.getName(), - e, - errs); - } -} - -/** - * Destroy a durable exchange - */ -void -MSSqlProvider::destroy(const PersistableExchange& exchange) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsExchanges; - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsExchanges.open(db, TblExchange); - rsBindings.open(db, TblBinding); - // Remove bindings first; the exchange IDs can't be ripped out from - // under the references in the bindings table. - rsBindings.removeForExchange(exchange.getPersistenceId()); - rsExchanges.remove(exchange); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting exchange " + exchange.getName(), - e, - errs); - } -} - -/** - * Record a binding - */ -void -MSSqlProvider::bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsBindings.open(db, TblBinding); - rsBindings.add(exchange.getPersistenceId(), - queue.getPersistenceId(), - key, - args); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error binding exchange " + exchange.getName() + - " to queue " + queue.getName(), - e, - errs); - } -} - -/** - * Forget a binding - */ -void -MSSqlProvider::unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const qpid::framing::FieldTable& args) -{ - DatabaseConnection *db = initConnection(); - BindingRecordset rsBindings; - try { - db->beginTransaction(); - rsBindings.open(db, TblBinding); - rsBindings.remove(exchange.getPersistenceId(), - queue.getPersistenceId(), - key, - args); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error unbinding exchange " + exchange.getName() + - " from queue " + queue.getName(), - e, - errs); - } -} - -/** - * Record generic durable configuration - */ -void -MSSqlProvider::create(const PersistableConfig& config) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - try { - db->beginTransaction(); - rsConfigs.open(db, TblConfig); - rsConfigs.add(config); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error creating config " + config.getName(), e, errs); - } -} - -/** - * Destroy generic durable configuration - */ -void -MSSqlProvider::destroy(const PersistableConfig& config) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsConfigs; - try { - db->beginTransaction(); - rsConfigs.open(db, TblConfig); - rsConfigs.remove(config); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting config " + config.getName(), e, errs); - } -} - -/** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ -void -MSSqlProvider::stage(const boost::intrusive_ptr<PersistableMessage>& msg) -{ - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.add(msg); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error staging message", e, errs); - } -} - -/** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ -void -MSSqlProvider::destroy(PersistableMessage& msg) -{ - DatabaseConnection *db = initConnection(); - BlobRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.remove(msg); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error deleting message", e, errs); - } -} - -/** - * Appends content to a previously staged message - */ -void -MSSqlProvider::appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const std::string& data) -{ - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - db->beginTransaction(); - rsMessages.open(db, TblMessage); - rsMessages.append(msg, data); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error appending to message", e, errs); - } -} - -/** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ -void -MSSqlProvider::loadContent(const qpid::broker::PersistableQueue& /*queue*/, - const boost::intrusive_ptr<const PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length) -{ - // SQL store keeps all messages in one table, so we don't need the - // queue reference. - DatabaseConnection *db = initConnection(); - MessageRecordset rsMessages; - try { - rsMessages.open(db, TblMessage); - rsMessages.loadContent(msg, data, offset, length); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - throw ADOException("Error loading message content", e, errs); - } -} - -/** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * @param ctxt The transaction context under which this enqueue happens. - * @param msg The message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - */ -void -MSSqlProvider::enqueue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) -{ - // If this enqueue is in the context of a transaction, use the specified - // transaction to nest a new transaction for this operation. However, if - // this is not in the context of a transaction, then just use the thread's - // DatabaseConnection with a ADO transaction. - DatabaseConnection *db = 0; - std::string xid; - AmqpTransaction *atxn = dynamic_cast<AmqpTransaction*> (ctxt); - if (atxn == 0) { - db = initConnection(); - db->beginTransaction(); - } - else { - (void)initState(); // Ensure this thread is initialized - // It's a transactional enqueue; if it's TPC, grab the xid. - AmqpTPCTransaction *tpcTxn = dynamic_cast<AmqpTPCTransaction*> (ctxt); - if (tpcTxn) - xid = tpcTxn->getXid(); - db = atxn->dbConn(); - try { - atxn->sqlBegin(); - } - catch(_com_error &e) { - throw ADOException("Error queuing message", e, db->getErrors()); - } - } - - MessageRecordset rsMessages; - MessageMapRecordset rsMap; - try { - if (msg->getPersistenceId() == 0) { // Message itself not yet saved - rsMessages.open(db, TblMessage); - rsMessages.add(msg); - } - rsMap.open(db, TblMessageMap); - rsMap.add(msg->getPersistenceId(), queue.getPersistenceId(), xid); - if (atxn) - atxn->sqlCommit(); - else - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - if (atxn) - atxn->sqlAbort(); - else - db->rollbackTransaction(); - throw ADOException("Error queuing message", e, errs); - } - msg->enqueueComplete(); -} - -/** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * @param ctxt The transaction context under which this dequeue happens. - * @param msg The message to dequeue - * @param queue The queue from which it is to be dequeued - */ -void -MSSqlProvider::dequeue(qpid::broker::TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) -{ - // If this dequeue is in the context of a transaction, use the specified - // transaction to nest a new transaction for this operation. However, if - // this is not in the context of a transaction, then just use the thread's - // DatabaseConnection with a ADO transaction. - DatabaseConnection *db = 0; - std::string xid; - AmqpTransaction *atxn = dynamic_cast<AmqpTransaction*> (ctxt); - if (atxn == 0) { - db = initConnection(); - db->beginTransaction(); - } - else { - (void)initState(); // Ensure this thread is initialized - // It's a transactional dequeue; if it's TPC, grab the xid. - AmqpTPCTransaction *tpcTxn = dynamic_cast<AmqpTPCTransaction*> (ctxt); - if (tpcTxn) - xid = tpcTxn->getXid(); - db = atxn->dbConn(); - try { - atxn->sqlBegin(); - } - catch(_com_error &e) { - throw ADOException("Error queuing message", e, db->getErrors()); - } - } - - MessageMapRecordset rsMap; - try { - rsMap.open(db, TblMessageMap); - // TPC dequeues are just marked pending and will actually be removed - // when the transaction commits; Single-phase dequeues are removed - // now, relying on the SQL transaction to put it back if the - // transaction doesn't commit. - if (!xid.empty()) { - rsMap.pendingRemove(msg->getPersistenceId(), - queue.getPersistenceId(), - xid); - } - else { - rsMap.remove(msg->getPersistenceId(), - queue.getPersistenceId()); - } - if (atxn) - atxn->sqlCommit(); - else - db->commitTransaction(); - } - catch(ms_sql::Exception&) { - if (atxn) - atxn->sqlAbort(); - else - db->rollbackTransaction(); - throw; - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - if (atxn) - atxn->sqlAbort(); - else - db->rollbackTransaction(); - throw ADOException("Error dequeuing message", e, errs); - } - msg->dequeueComplete(); -} - -std::auto_ptr<qpid::broker::TransactionContext> -MSSqlProvider::begin() -{ - (void)initState(); // Ensure this thread is initialized - - // Transactions are associated with the Connection, so this transaction - // context needs its own connection. At the time of writing, single-phase - // transactions are dealt with completely on one thread, so we really - // could just use the thread-specific DatabaseConnection for this. - // However, that would introduce an ugly, hidden coupling, so play - // it safe and handle this just like a TPC transaction, which actually - // can be prepared and committed/aborted from different threads, - // making it a bad idea to try using the thread-local DatabaseConnection. - boost::shared_ptr<DatabaseConnection> db(new DatabaseConnection); - db->open(options.connectString, options.catalogName); - std::auto_ptr<AmqpTransaction> tx(new AmqpTransaction(db)); - tx->sqlBegin(); - std::auto_ptr<qpid::broker::TransactionContext> tc(tx); - return tc; -} - -std::auto_ptr<qpid::broker::TPCTransactionContext> -MSSqlProvider::begin(const std::string& xid) -{ - (void)initState(); // Ensure this thread is initialized - boost::shared_ptr<DatabaseConnection> db(new DatabaseConnection); - db->open(options.connectString, options.catalogName); - std::auto_ptr<AmqpTPCTransaction> tx(new AmqpTPCTransaction(db, xid)); - tx->sqlBegin(); - - TplRecordset rsTpl; - try { - tx->sqlBegin(); - rsTpl.open(db.get(), TblTpl); - rsTpl.add(xid); - tx->sqlCommit(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - tx->sqlAbort(); - throw ADOException("Error adding TPL record", e, errs); - } - - std::auto_ptr<qpid::broker::TPCTransactionContext> tc(tx); - return tc; -} - -void -MSSqlProvider::prepare(qpid::broker::TPCTransactionContext& txn) -{ - // Commit all the marked-up enqueue/dequeue ops and the TPL record. - // On commit/rollback the TPL will be removed and the TPL markups - // on the message map will be cleaned up as well. - (void)initState(); // Ensure this thread is initialized - AmqpTPCTransaction *atxn = dynamic_cast<AmqpTPCTransaction*> (&txn); - if (atxn == 0) - throw qpid::broker::InvalidTransactionContextException(); - try { - atxn->sqlCommit(); - } - catch(_com_error &e) { - throw ADOException("Error preparing", e, atxn->dbConn()->getErrors()); - } - atxn->setPrepared(); -} - -void -MSSqlProvider::commit(qpid::broker::TransactionContext& txn) -{ - (void)initState(); // Ensure this thread is initialized - /* - * One-phase transactions simply commit the outer SQL transaction - * that was begun on begin(). Two-phase transactions are different - - * the SQL transaction started on begin() was committed on prepare() - * so all the SQL records reflecting the enqueue/dequeue actions for - * the transaction are recorded but with xid markups on them to reflect - * that they are prepared but not committed. Now go back and remove - * the markups, deleting those marked for removal. - */ - AmqpTPCTransaction *p2txn = dynamic_cast<AmqpTPCTransaction*> (&txn); - if (p2txn == 0) { - AmqpTransaction *p1txn = dynamic_cast<AmqpTransaction*> (&txn); - if (p1txn == 0) - throw qpid::broker::InvalidTransactionContextException(); - p1txn->sqlCommit(); - return; - } - - DatabaseConnection *db(p2txn->dbConn()); - TplRecordset rsTpl; - MessageMapRecordset rsMessageMap; - try { - db->beginTransaction(); - rsTpl.open(db, TblTpl); - rsMessageMap.open(db, TblMessageMap); - rsMessageMap.commitPrepared(p2txn->getXid()); - rsTpl.remove(p2txn->getXid()); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error committing transaction", e, errs); - } -} - -void -MSSqlProvider::abort(qpid::broker::TransactionContext& txn) -{ - (void)initState(); // Ensure this thread is initialized - /* - * One-phase and non-prepared two-phase transactions simply abort - * the outer SQL transaction that was begun on begin(). However, prepared - * two-phase transactions are different - the SQL transaction started - * on begin() was committed on prepare() so all the SQL records - * reflecting the enqueue/dequeue actions for the transaction are - * recorded but with xid markups on them to reflect that they are - * prepared but not committed. Now go back and remove the markups, - * deleting those marked for addition. - */ - AmqpTPCTransaction *p2txn = dynamic_cast<AmqpTPCTransaction*> (&txn); - if (p2txn == 0 || !p2txn->isPrepared()) { - AmqpTransaction *p1txn = dynamic_cast<AmqpTransaction*> (&txn); - if (p1txn == 0) - throw qpid::broker::InvalidTransactionContextException(); - p1txn->sqlAbort(); - return; - } - - DatabaseConnection *db(p2txn->dbConn()); - TplRecordset rsTpl; - MessageMapRecordset rsMessageMap; - try { - db->beginTransaction(); - rsTpl.open(db, TblTpl); - rsMessageMap.open(db, TblMessageMap); - rsMessageMap.abortPrepared(p2txn->getXid()); - rsTpl.remove(p2txn->getXid()); - db->commitTransaction(); - } - catch(_com_error &e) { - std::string errs = db->getErrors(); - db->rollbackTransaction(); - throw ADOException("Error committing transaction", e, errs); - } - - - (void)initState(); // Ensure this thread is initialized - AmqpTransaction *atxn = dynamic_cast<AmqpTransaction*> (&txn); - if (atxn == 0) - throw qpid::broker::InvalidTransactionContextException(); - atxn->sqlAbort(); -} - -void -MSSqlProvider::collectPreparedXids(std::set<std::string>& xids) -{ - DatabaseConnection *db = initConnection(); - try { - TplRecordset rsTpl; - rsTpl.open(db, TblTpl); - rsTpl.recover(xids); - } - catch(_com_error &e) { - throw ADOException("Error reading TPL", e, db->getErrors()); - } -} - -// @TODO Much of this recovery code is way too similar... refactor to -// a recover template method on BlobRecordset. - -void -MSSqlProvider::recoverConfigs(qpid::broker::RecoveryManager& recoverer) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - BlobRecordset rsConfigs; - rsConfigs.open(db, TblConfig); - _RecordsetPtr p = (_RecordsetPtr)rsConfigs; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Config instance and reset its ID. - broker::RecoverableConfig::shared_ptr config = - recoverer.recoverConfig(blob); - config->setPersistenceId(id); - p->MoveNext(); - } - } - catch(_com_error &e) { - throw ADOException("Error recovering configs", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverExchanges(qpid::broker::RecoveryManager& recoverer, - ExchangeMap& exchangeMap) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - BlobRecordset rsExchanges; - rsExchanges.open(db, TblExchange); - _RecordsetPtr p = (_RecordsetPtr)rsExchanges; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Exchange instance, reset its ID, and remember the - // ones restored for matching up when recovering bindings. - broker::RecoverableExchange::shared_ptr exchange = - recoverer.recoverExchange(blob); - exchange->setPersistenceId(id); - exchangeMap[id] = exchange; - p->MoveNext(); - } - } - catch(_com_error &e) { - throw ADOException("Error recovering exchanges", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverQueues(qpid::broker::RecoveryManager& recoverer, - QueueMap& queueMap) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - BlobRecordset rsQueues; - rsQueues.open(db, TblQueue); - _RecordsetPtr p = (_RecordsetPtr)rsQueues; - if (p->BOF && p->EndOfFile) - return; // Nothing to do - p->MoveFirst(); - while (!p->EndOfFile) { - uint64_t id = p->Fields->Item["persistenceId"]->Value; - long blobSize = p->Fields->Item["fieldTableBlob"]->ActualSize; - BlobAdapter blob(blobSize); - blob = p->Fields->Item["fieldTableBlob"]->GetChunk(blobSize); - // Recreate the Queue instance and reset its ID. - broker::RecoverableQueue::shared_ptr queue = - recoverer.recoverQueue(blob); - queue->setPersistenceId(id); - queueMap[id] = queue; - p->MoveNext(); - } - } - catch(_com_error &e) { - throw ADOException("Error recovering queues", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverBindings(qpid::broker::RecoveryManager& recoverer, - const ExchangeMap& exchangeMap, - const QueueMap& queueMap) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - BindingRecordset rsBindings; - rsBindings.open(db, TblBinding); - rsBindings.recover(recoverer, exchangeMap, queueMap); - } - catch(_com_error &e) { - throw ADOException("Error recovering bindings", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverMessages(qpid::broker::RecoveryManager& recoverer, - MessageMap& messageMap, - MessageQueueMap& messageQueueMap) -{ - DatabaseConnection *db = 0; - try { - db = initConnection(); - MessageRecordset rsMessages; - rsMessages.open(db, TblMessage); - rsMessages.recover(recoverer, messageMap); - - MessageMapRecordset rsMessageMaps; - rsMessageMaps.open(db, TblMessageMap); - rsMessageMaps.recover(messageQueueMap); - } - catch(_com_error &e) { - throw ADOException("Error recovering messages", - e, - db ? db->getErrors() : ""); - } -} - -void -MSSqlProvider::recoverTransactions(qpid::broker::RecoveryManager& recoverer, - PreparedTransactionMap& dtxMap) -{ - DatabaseConnection *db = initConnection(); - std::set<std::string> xids; - try { - TplRecordset rsTpl; - rsTpl.open(db, TblTpl); - rsTpl.recover(xids); - } - catch(_com_error &e) { - throw ADOException("Error recovering TPL records", e, db->getErrors()); - } - - try { - // Rebuild the needed RecoverableTransactions. - for (std::set<std::string>::const_iterator iXid = xids.begin(); - iXid != xids.end(); - ++iXid) { - boost::shared_ptr<DatabaseConnection> dbX(new DatabaseConnection); - dbX->open(options.connectString, options.catalogName); - std::auto_ptr<AmqpTPCTransaction> tx(new AmqpTPCTransaction(dbX, - *iXid)); - tx->setPrepared(); - std::auto_ptr<qpid::broker::TPCTransactionContext> tc(tx); - dtxMap[*iXid] = recoverer.recoverTransaction(*iXid, tc); - } - } - catch(_com_error &e) { - throw ADOException("Error recreating dtx connection", e); - } -} - -////////////// Internal Methods - -State * -MSSqlProvider::initState() -{ - State *state = dbState.get(); // See if thread has initialized - if (!state) { - state = new State; - dbState.reset(state); - } - return state; -} - -DatabaseConnection * -MSSqlProvider::initConnection(void) -{ - State *state = initState(); - if (state->dbConn != 0) - return state->dbConn; // And the DatabaseConnection is set up too - std::auto_ptr<DatabaseConnection> db(new DatabaseConnection); - db->open(options.connectString, options.catalogName); - state->dbConn = db.release(); - return state->dbConn; -} - -void -MSSqlProvider::createDb(DatabaseConnection *db, const std::string &name) -{ - const std::string dbCmd = "CREATE DATABASE " + name; - const std::string useCmd = "USE " + name; - const std::string tableCmd = "CREATE TABLE "; - const std::string colSpecs = - " (persistenceId bigint PRIMARY KEY NOT NULL IDENTITY(1,1)," - " fieldTableBlob varbinary(MAX) NOT NULL)"; - const std::string bindingSpecs = - " (exchangeId bigint REFERENCES tblExchange(persistenceId) NOT NULL," - " queueId bigint REFERENCES tblQueue(persistenceId) NOT NULL," - " routingKey varchar(255)," - " fieldTableBlob varbinary(MAX))"; - const std::string messageMapSpecs = - " (messageId bigint REFERENCES tblMessage(persistenceId) NOT NULL," - " queueId bigint REFERENCES tblQueue(persistenceId) NOT NULL," - " prepareStatus tinyint CHECK (prepareStatus IS NULL OR " - " prepareStatus IN (1, 2))," - " xid varbinary(512) REFERENCES tblTPL(xid)" - " CONSTRAINT CK_NoDups UNIQUE NONCLUSTERED (messageId, queueId) )"; - const std::string tplSpecs = " (xid varbinary(512) PRIMARY KEY NOT NULL)"; - // SET NOCOUNT ON added to prevent extra result sets from - // interfering with SELECT statements. (Added by SQL Management) - const std::string removeUnrefMsgsTrigger = - "CREATE TRIGGER dbo.RemoveUnreferencedMessages " - "ON tblMessageMap AFTER DELETE AS BEGIN " - "SET NOCOUNT ON; " - "DELETE FROM tblMessage " - "WHERE tblMessage.persistenceId IN " - " (SELECT messageId FROM deleted) AND" - " NOT EXISTS(SELECT * FROM tblMessageMap" - " WHERE tblMessageMap.messageId IN" - " (SELECT messageId FROM deleted)) " - "END"; - - _variant_t unused; - _bstr_t dbStr = dbCmd.c_str(); - _ConnectionPtr conn(*db); - try { - conn->Execute(dbStr, &unused, adExecuteNoRecords); - _bstr_t useStr = useCmd.c_str(); - conn->Execute(useStr, &unused, adExecuteNoRecords); - std::string makeTable = tableCmd + TblQueue + colSpecs; - _bstr_t makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblExchange + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblConfig + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblMessage + colSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblBinding + bindingSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblTpl + tplSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - makeTable = tableCmd + TblMessageMap + messageMapSpecs; - makeTableStr = makeTable.c_str(); - conn->Execute(makeTableStr, &unused, adExecuteNoRecords); - _bstr_t addTriggerStr = removeUnrefMsgsTrigger.c_str(); - conn->Execute(addTriggerStr, &unused, adExecuteNoRecords); - } - catch(_com_error &e) { - throw ADOException("MSSQL can't create " + name, e, db->getErrors()); - } -} - -void -MSSqlProvider::dump() -{ - // dump all db records to qpid_log - QPID_LOG(notice, "DB Dump: (not dumping anything)"); - // rsQueues.dump(); -} - - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/MessageMapRecordset.cpp b/cpp/src/qpid/store/ms-sql/MessageMapRecordset.cpp deleted file mode 100644 index ce9fa61010..0000000000 --- a/cpp/src/qpid/store/ms-sql/MessageMapRecordset.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/Exception.h> -#include <qpid/log/Statement.h> -#include <qpid/store/StorageProvider.h> - -#include "MessageMapRecordset.h" -#include "BlobEncoder.h" -#include "DatabaseConnection.h" -#include "Exception.h" -#include "VariantHelper.h" - -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; -} - -namespace qpid { -namespace store { -namespace ms_sql { - -void -MessageMapRecordset::open(DatabaseConnection* conn, const std::string& table) -{ - init(conn, table); -} - -void -MessageMapRecordset::add(uint64_t messageId, - uint64_t queueId, - const std::string& xid) -{ - std::ostringstream command; - command << "INSERT INTO " << tableName - << " (messageId, queueId"; - if (!xid.empty()) - command << ", prepareStatus, xid"; - command << ") VALUES (" << messageId << "," << queueId; - if (!xid.empty()) - command << "," << PREPARE_ADD << ",?"; - command << ")" << std::ends; - - _CommandPtr cmd = NULL; - _ParameterPtr xidVal = NULL; - TESTHR(cmd.CreateInstance(__uuidof(Command))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.str().c_str(); - cmd->CommandType = adCmdText; - if (!xid.empty()) { - TESTHR(xidVal.CreateInstance(__uuidof(Parameter))); - xidVal->Name = "@xid"; - xidVal->Type = adVarBinary; - xidVal->Size = xid.length(); - xidVal->Direction = adParamInput; - xidVal->Value = BlobEncoder(xid); - cmd->Parameters->Append(xidVal); - } - cmd->Execute(NULL, NULL, adCmdText | adExecuteNoRecords); -} - -void -MessageMapRecordset::remove(uint64_t messageId, uint64_t queueId) -{ - std::ostringstream command; - command << "DELETE FROM " << tableName - << " WHERE queueId = " << queueId - << " AND messageId = " << messageId << std::ends; - _CommandPtr cmd = NULL; - TESTHR(cmd.CreateInstance(__uuidof(Command))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.str().c_str(); - cmd->CommandType = adCmdText; - _variant_t deletedRecords; - cmd->Execute(&deletedRecords, NULL, adCmdText | adExecuteNoRecords); - if ((long)deletedRecords == 0) - throw ms_sql::Exception("Message does not exist in queue mapping"); - // Trigger on deleting the mapping takes care of deleting orphaned - // message record from tblMessage. -} - -void -MessageMapRecordset::pendingRemove(uint64_t messageId, - uint64_t queueId, - const std::string& xid) -{ - // Look up the mapping for the specified message and queue. There - // should be only one because of the uniqueness constraint in the - // SQL table. Update it to reflect it's pending delete with - // the specified xid. - std::ostringstream command; - command << "UPDATE " << tableName - << " SET prepareStatus=" << PREPARE_REMOVE - << " , xid=?" - << " WHERE queueId = " << queueId - << " AND messageId = " << messageId << std::ends; - - _CommandPtr cmd = NULL; - _ParameterPtr xidVal = NULL; - TESTHR(cmd.CreateInstance(__uuidof(Command))); - TESTHR(xidVal.CreateInstance(__uuidof(Parameter))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.str().c_str(); - cmd->CommandType = adCmdText; - xidVal->Name = "@xid"; - xidVal->Type = adVarBinary; - xidVal->Size = xid.length(); - xidVal->Direction = adParamInput; - xidVal->Value = BlobEncoder(xid); - cmd->Parameters->Append(xidVal); - cmd->Execute(NULL, NULL, adCmdText | adExecuteNoRecords); -} - -void -MessageMapRecordset::removeForQueue(uint64_t queueId) -{ - std::ostringstream command; - command << "DELETE FROM " << tableName - << " WHERE queueId = " << queueId << std::ends; - _CommandPtr cmd = NULL; - - TESTHR(cmd.CreateInstance(__uuidof(Command))); - _ConnectionPtr p = *dbConn; - cmd->ActiveConnection = p; - cmd->CommandText = command.str().c_str(); - cmd->CommandType = adCmdText; - cmd->Execute(NULL, NULL, adCmdText | adExecuteNoRecords); -} - -void -MessageMapRecordset::commitPrepared(const std::string& xid) -{ - // Find all the records for the specified xid. Records marked as adding - // are now permanent so remove the xid and prepareStatus. Records marked - // as removing are removed entirely. - openRs(); - MessageMap m; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&m); - for (; !rs->EndOfFile; rs->MoveNext()) { - if (m.xidStatus != adFldOK) - continue; - const std::string x(m.xid, m.xidLength); - if (x != xid) - continue; - if (m.prepareStatus == PREPARE_REMOVE) { - rs->Delete(adAffectCurrent); - } - else { - _variant_t dbNull; - dbNull.ChangeType(VT_NULL); - rs->Fields->GetItem("prepareStatus")->Value = dbNull; - rs->Fields->GetItem("xid")->Value = dbNull; - } - rs->Update(); - } - piAdoRecordBinding->Release(); -} - -void -MessageMapRecordset::abortPrepared(const std::string& xid) -{ - // Find all the records for the specified xid. Records marked as adding - // need to be removed while records marked as removing are put back to - // no xid and no prepareStatus. - openRs(); - MessageMap m; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&m); - for (; !rs->EndOfFile; rs->MoveNext()) { - if (m.xidStatus != adFldOK) - continue; - const std::string x(m.xid, m.xidLength); - if (x != xid) - continue; - if (m.prepareStatus == PREPARE_ADD) { - rs->Delete(adAffectCurrent); - } - else { - _variant_t dbNull; - dbNull.ChangeType(VT_NULL); - rs->Fields->GetItem("prepareStatus")->Value = dbNull; - rs->Fields->GetItem("xid")->Value = dbNull; - } - rs->Update(); - } - piAdoRecordBinding->Release(); -} - -void -MessageMapRecordset::recover(MessageQueueMap& msgMap) -{ - openRs(); - if (rs->BOF && rs->EndOfFile) - return; // Nothing to do - rs->MoveFirst(); - MessageMap b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - while (!rs->EndOfFile) { - qpid::store::QueueEntry entry(b.queueId); - if (b.xidStatus == adFldOK && b.xidLength > 0) { - entry.xid.assign(b.xid, b.xidLength); - entry.tplStatus = - b.prepareStatus == PREPARE_ADD ? QueueEntry::ADDING - : QueueEntry::REMOVING; - } - else { - entry.tplStatus = QueueEntry::NONE; - } - msgMap[b.messageId].push_back(entry); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -void -MessageMapRecordset::dump() -{ - openRs(); - Recordset::dump(); - if (rs->EndOfFile && rs->BOF) // No records - return; - rs->MoveFirst(); - - MessageMap m; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&m); - - while (!rs->EndOfFile) { - QPID_LOG(notice, "msg " << m.messageId << " on queue " << m.queueId); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/MessageMapRecordset.h b/cpp/src/qpid/store/ms-sql/MessageMapRecordset.h deleted file mode 100644 index 1b0c2f073e..0000000000 --- a/cpp/src/qpid/store/ms-sql/MessageMapRecordset.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef QPID_STORE_MSSQL_MESSAGEMAPRECORDSET_H -#define QPID_STORE_MSSQL_MESSAGEMAPRECORDSET_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <icrsint.h> -#include "Recordset.h" -#include <qpid/broker/RecoveryManager.h> - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class MessageMapRecordset - * - * Class for the message map (message -> queue) records. - */ -class MessageMapRecordset : public Recordset { - - // These values are defined in a constraint on the tblMessageMap table. - // the prepareStatus column can only be null, 1, or 2. - enum { PREPARE_ADD=1, PREPARE_REMOVE=2 }; - - class MessageMap : public CADORecordBinding { - BEGIN_ADO_BINDING(MessageMap) - ADO_FIXED_LENGTH_ENTRY2(1, adBigInt, messageId, FALSE) - ADO_FIXED_LENGTH_ENTRY2(2, adBigInt, queueId, FALSE) - ADO_FIXED_LENGTH_ENTRY2(3, adTinyInt, prepareStatus, FALSE) - ADO_VARIABLE_LENGTH_ENTRY(4, adVarBinary, xid, sizeof(xid), - xidStatus, xidLength, FALSE) - END_ADO_BINDING() - - public: - uint64_t messageId; - uint64_t queueId; - uint8_t prepareStatus; - char xid[512]; - int xidStatus; - uint32_t xidLength; - }; - - void selectOnXid(const std::string& xid); - -public: - virtual void open(DatabaseConnection* conn, const std::string& table); - - // Add a new mapping - void add(uint64_t messageId, - uint64_t queueId, - const std::string& xid = ""); - - // Remove a specific mapping. - void remove(uint64_t messageId, uint64_t queueId); - - // Mark the indicated message->queue entry pending removal. The entry - // for the mapping is updated to indicate pending removal with the - // specified xid. - void pendingRemove(uint64_t messageId, - uint64_t queueId, - const std::string& xid); - - // Remove mappings for all messages on a specified queue. - void removeForQueue(uint64_t queueId); - - // Commit records recorded as prepared. - void commitPrepared(const std::string& xid); - - // Abort prepared changes. - void abortPrepared(const std::string& xid); - - // Recover the mappings of message ID -> vector<queue ID>. - void recover(MessageQueueMap& msgMap); - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_MESSAGEMAPRECORDSET_H */ diff --git a/cpp/src/qpid/store/ms-sql/MessageRecordset.cpp b/cpp/src/qpid/store/ms-sql/MessageRecordset.cpp deleted file mode 100644 index b62a333df6..0000000000 --- a/cpp/src/qpid/store/ms-sql/MessageRecordset.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/Exception.h> -#include <qpid/log/Statement.h> - -#include "MessageRecordset.h" -#include "BlobAdapter.h" -#include "BlobEncoder.h" -#include "VariantHelper.h" - -#include <boost/intrusive_ptr.hpp> - -class qpid::broker::PersistableMessage; - -namespace qpid { -namespace store { -namespace ms_sql { - -void -MessageRecordset::add(const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg) -{ - BlobEncoder blob (msg); // Marshall headers and content to a blob - rs->AddNew(); - rs->Fields->GetItem("fieldTableBlob")->AppendChunk(blob); - rs->Update(); - uint64_t id = rs->Fields->Item["persistenceId"]->Value; - msg->setPersistenceId(id); -} - -void -MessageRecordset::append(const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg, - const std::string& data) -{ - // Look up the message by its Id - std::ostringstream filter; - filter << "persistenceId = " << msg->getPersistenceId() << std::ends; - rs->PutFilter (VariantHelper<std::string>(filter.str())); - if (rs->RecordCount == 0) { - throw Exception("Can't append to message not stored in database"); - } - BlobEncoder blob (data); // Marshall string data to a blob - rs->Fields->GetItem("fieldTableBlob")->AppendChunk(blob); - rs->Update(); -} - -void -MessageRecordset::remove(const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg) -{ - BlobRecordset::remove(msg->getPersistenceId()); -} - -void -MessageRecordset::loadContent(const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length) -{ - // Look up the message by its Id - std::ostringstream filter; - filter << "persistenceId = " << msg->getPersistenceId() << std::ends; - rs->PutFilter (VariantHelper<std::string>(filter.str())); - if (rs->RecordCount == 0) { - throw Exception("Can't load message not stored in database"); - } - - // NOTE! If this code needs to change, please verify the encoding - // code in BlobEncoder. - long blobSize = rs->Fields->Item["fieldTableBlob"]->ActualSize; - uint32_t headerSize; - const size_t headerFieldLength = sizeof(headerSize); - BlobAdapter blob(headerFieldLength); - blob = - rs->Fields->Item["fieldTableBlob"]->GetChunk((long)headerFieldLength); - headerSize = ((qpid::framing::Buffer&)blob).getLong(); - - // GetChunk always begins reading where the previous GetChunk left off, - // so we can't just tell it to ignore the header and read the data. - // So, read the header plus the offset, plus the desired data, then - // copy the desired data to the supplied string. If this ends up asking - // for more than is available in the field, reduce it to what's there. - long getSize = headerSize + offset + length; - if (getSize + (long)headerFieldLength > blobSize) { - size_t reduce = (getSize + headerFieldLength) - blobSize; - getSize -= reduce; - length -= reduce; - } - BlobAdapter header_plus(getSize); - header_plus = rs->Fields->Item["fieldTableBlob"]->GetChunk(getSize); - uint8_t *throw_away = new uint8_t[headerSize + offset]; - ((qpid::framing::Buffer&)header_plus).getRawData(throw_away, headerSize + offset); - delete throw_away; - ((qpid::framing::Buffer&)header_plus).getRawData(data, length); -} - -void -MessageRecordset::recover(qpid::broker::RecoveryManager& recoverer, - std::map<uint64_t, broker::RecoverableMessage::shared_ptr>& messageMap) -{ - if (rs->BOF && rs->EndOfFile) - return; // Nothing to do - rs->MoveFirst(); - Binding b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - while (!rs->EndOfFile) { - // The blob was written as normal, but with the header length - // prepended in a uint32_t. Due to message staging threshold - // limits, the header may be all that's read in; get it first, - // recover that message header, then see if the rest is needed. - // - // NOTE! If this code needs to change, please verify the encoding - // code in BlobEncoder. - long blobSize = rs->Fields->Item["fieldTableBlob"]->ActualSize; - uint32_t headerSize; - const size_t headerFieldLength = sizeof(headerSize); - BlobAdapter blob(headerFieldLength); - blob = - rs->Fields->Item["fieldTableBlob"]->GetChunk((long)headerFieldLength); - headerSize = ((qpid::framing::Buffer&)blob).getLong(); - BlobAdapter header(headerSize); - header = rs->Fields->Item["fieldTableBlob"]->GetChunk(headerSize); - broker::RecoverableMessage::shared_ptr msg; - msg = recoverer.recoverMessage(header); - msg->setPersistenceId(b.messageId); - messageMap[b.messageId] = msg; - - // Now, do we need the rest of the content? - long contentLength = blobSize - headerFieldLength - headerSize; - if (msg->loadContent(contentLength)) { - BlobAdapter content(contentLength); - content = - rs->Fields->Item["fieldTableBlob"]->GetChunk(contentLength); - msg->decodeContent(content); - } - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -void -MessageRecordset::dump() -{ - Recordset::dump(); - if (rs->EndOfFile && rs->BOF) // No records - return; - rs->MoveFirst(); - - Binding b; - IADORecordBinding *piAdoRecordBinding; - rs->QueryInterface(__uuidof(IADORecordBinding), - (LPVOID *)&piAdoRecordBinding); - piAdoRecordBinding->BindToRecordset(&b); - - while (VARIANT_FALSE == rs->EndOfFile) { - QPID_LOG(notice, "Msg " << b.messageId); - rs->MoveNext(); - } - - piAdoRecordBinding->Release(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/MessageRecordset.h b/cpp/src/qpid/store/ms-sql/MessageRecordset.h deleted file mode 100644 index 698b2561fe..0000000000 --- a/cpp/src/qpid/store/ms-sql/MessageRecordset.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef QPID_STORE_MSSQL_MESSAGERECORDSET_H -#define QPID_STORE_MSSQL_MESSAGERECORDSET_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <icrsint.h> -#include "BlobRecordset.h" -#include <qpid/broker/PersistableMessage.h> -#include <qpid/broker/RecoveryManager.h> -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class MessageRecordset - * - * Class for storing and recovering messages. Messages are primarily blobs - * and handled similarly. However, messages larger than the staging threshold - * are not contained completely in memory; they're left mostly in the store - * and the header is held in memory. So when the message "blob" is saved, - * an additional size-of-the-header field is prepended to the blob. - * On recovery, the size-of-the-header is used to get only what's needed - * until it's determined if the entire message is to be recovered to memory. - */ -class MessageRecordset : public BlobRecordset { - class Binding : public CADORecordBinding { - BEGIN_ADO_BINDING(Binding) - ADO_FIXED_LENGTH_ENTRY2(1, adBigInt, messageId, FALSE) - END_ADO_BINDING() - - public: - uint64_t messageId; - }; - -public: - // Store a message. Store the header size (4 bytes) then the regular - // blob comprising the message. - void add(const boost::intrusive_ptr<qpid::broker::PersistableMessage>& msg); - - // Append additional content to an existing message. - void append(const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg, - const std::string& data); - - // Remove an existing message - void remove(const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg); - - // Load all or part of a stored message. This skips the header parts and - // loads content. - void loadContent(const boost::intrusive_ptr<const qpid::broker::PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length); - - // Recover messages and save a map of those recovered. - void recover(qpid::broker::RecoveryManager& recoverer, - std::map<uint64_t, broker::RecoverableMessage::shared_ptr>& messageMap); - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_MESSAGERECORDSET_H */ diff --git a/cpp/src/qpid/store/ms-sql/Recordset.cpp b/cpp/src/qpid/store/ms-sql/Recordset.cpp deleted file mode 100644 index e706799951..0000000000 --- a/cpp/src/qpid/store/ms-sql/Recordset.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/Exception.h> -#include <qpid/log/Statement.h> - -#include "Recordset.h" -#include "BlobEncoder.h" -#include "DatabaseConnection.h" -#include "VariantHelper.h" - -namespace { -inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);}; -} - -namespace qpid { -namespace store { -namespace ms_sql { - - -void -Recordset::init(DatabaseConnection* conn, const std::string& table) -{ - dbConn = conn; - TESTHR(rs.CreateInstance(__uuidof(::Recordset))); - tableName = table; -} - -void -Recordset::openRs() -{ - // Client-side cursors needed to get access to newly added - // identity column immediately. Recordsets need this to get the - // persistence ID for the broker objects. - rs->CursorLocation = adUseClient; - _ConnectionPtr p = *dbConn; - rs->Open(tableName.c_str(), - _variant_t((IDispatch *)p, true), - adOpenStatic, - adLockOptimistic, - adCmdTable); -} - -void -Recordset::open(DatabaseConnection* conn, const std::string& table) -{ - init(conn, table); - openRs(); -} - -void -Recordset::close() -{ - if (rs && rs->State == adStateOpen) - rs->Close(); -} - -void -Recordset::requery() -{ - // Restore the recordset to reflect all current records. - rs->Filter = ""; - rs->Requery(-1); -} - -void -Recordset::dump() -{ - long count = rs->RecordCount; - QPID_LOG(notice, "DB Dump: " + tableName << - ": " << count << " records"); -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/Recordset.h b/cpp/src/qpid/store/ms-sql/Recordset.h deleted file mode 100644 index 032b2bd434..0000000000 --- a/cpp/src/qpid/store/ms-sql/Recordset.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef QPID_STORE_MSSQL_RECORDSET_H -#define QPID_STORE_MSSQL_RECORDSET_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -// Bring in ADO 2.8 (yes, I know it says "15", but that's it...) -#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ - no_namespace rename("EOF", "EndOfFile") -#include <comdef.h> -#include <comutil.h> -#include <string> -#if 0 -#include <utility> -#endif - -namespace qpid { -namespace store { -namespace ms_sql { - -class DatabaseConnection; - -/** - * @class Recordset - * - * Represents an ADO Recordset, abstracting out the common operations needed - * on the common tables used that have 2 fields, persistence ID and blob. - */ -class Recordset { -protected: - _RecordsetPtr rs; - DatabaseConnection* dbConn; - std::string tableName; - - void init(DatabaseConnection* conn, const std::string& table); - void openRs(); - -public: - Recordset() : rs(0), dbConn(0) {} - virtual ~Recordset() { close(); rs = 0; dbConn = 0; } - - /** - * Default open() reads all records into the recordset. - */ - virtual void open(DatabaseConnection* conn, const std::string& table); - void close(); - void requery(); - operator _RecordsetPtr () { return rs; } - - // Dump table contents; useful for debugging. - void dump(); -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_RECORDSET_H */ diff --git a/cpp/src/qpid/store/ms-sql/SqlTransaction.cpp b/cpp/src/qpid/store/ms-sql/SqlTransaction.cpp deleted file mode 100644 index 6ad7725570..0000000000 --- a/cpp/src/qpid/store/ms-sql/SqlTransaction.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "SqlTransaction.h"
-#include "DatabaseConnection.h"
-
-namespace qpid {
-namespace store {
-namespace ms_sql {
-
-SqlTransaction::SqlTransaction(const boost::shared_ptr<DatabaseConnection>& _db)
- : db(_db), transDepth(0)
-{
-}
-
-SqlTransaction::~SqlTransaction()
-{
- if (transDepth > 0)
- this->abort();
-}
-
-void
-SqlTransaction::begin()
-{
- _bstr_t beginCmd("BEGIN TRANSACTION");
- _ConnectionPtr c = *db;
- c->Execute(beginCmd, NULL, adExecuteNoRecords);
- ++transDepth;
-}
-
-void
-SqlTransaction::commit()
-{
- if (transDepth > 0) {
- _bstr_t commitCmd("COMMIT TRANSACTION");
- _ConnectionPtr c = *db;
- c->Execute(commitCmd, NULL, adExecuteNoRecords);
- --transDepth;
- }
-}
-
-void
-SqlTransaction::abort()
-{
- if (transDepth > 0) {
- _bstr_t rollbackCmd("ROLLBACK TRANSACTION");
- _ConnectionPtr c = *db;
- c->Execute(rollbackCmd, NULL, adExecuteNoRecords);
- transDepth = 0;
- }
-}
-
-}}} // namespace qpid::store::ms_sql
diff --git a/cpp/src/qpid/store/ms-sql/SqlTransaction.h b/cpp/src/qpid/store/ms-sql/SqlTransaction.h deleted file mode 100644 index 8b5239b786..0000000000 --- a/cpp/src/qpid/store/ms-sql/SqlTransaction.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef QPID_STORE_MSSQL_SQLTRANSACTION_H
-#define QPID_STORE_MSSQL_SQLTRANSACTION_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include <boost/shared_ptr.hpp>
-#include <string>
-
-namespace qpid {
-namespace store {
-namespace ms_sql {
-
-class DatabaseConnection;
-
-/**
- * @class SqlTransaction
- *
- * Class representing an SQL transaction.
- * Since ADO w/ SQLOLEDB can't do nested transaction via its BeginTrans(),
- * et al, nested transactions are carried out with direct SQL commands.
- * To ensure the state of this is known, keep track of how deeply the
- * transactions are nested. This is more of a safety/sanity check since
- * AMQP doesn't provide nested transactions.
- */
-class SqlTransaction {
-
- boost::shared_ptr<DatabaseConnection> db;
-
- // Since ADO w/ SQLOLEDB can't do nested transaction via its BeginTrans(),
- // et al, nested transactions are carried out with direct SQL commands.
- // To ensure the state of this is known, keep track of how deeply the
- // transactions are nested.
- unsigned int transDepth;
-
-public:
- SqlTransaction(const boost::shared_ptr<DatabaseConnection>& _db);
- ~SqlTransaction();
-
- DatabaseConnection *dbConn() { return db.get(); }
-
- void begin();
- void commit();
- void abort();
-};
-
-}}} // namespace qpid::store::ms_sql
-
-#endif /* QPID_STORE_MSSQL_SQLTRANSACTION_H */
diff --git a/cpp/src/qpid/store/ms-sql/State.cpp b/cpp/src/qpid/store/ms-sql/State.cpp deleted file mode 100644 index 720603dd11..0000000000 --- a/cpp/src/qpid/store/ms-sql/State.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "State.h" -#include "DatabaseConnection.h" -#include "Exception.h" -#include <comdef.h> - -namespace qpid { -namespace store { -namespace ms_sql { - -State::State() : dbConn(0) -{ - HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); - if (hr != S_OK && hr != S_FALSE) - throw Exception("Error initializing COM"); -} - -State::~State() -{ - if (dbConn) - delete dbConn; - ::CoUninitialize(); -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/State.h b/cpp/src/qpid/store/ms-sql/State.h deleted file mode 100644 index 6350bc5bd2..0000000000 --- a/cpp/src/qpid/store/ms-sql/State.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_STORE_MSSQL_STATE_H -#define QPID_STORE_MSSQL_STATE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -namespace qpid { -namespace store { -namespace ms_sql { - -class DatabaseConnection; - -/** - * @struct State - * - * Represents a thread's state for accessing ADO and the database. - * Creating an instance of State initializes COM for this thread, and - * destroying it uninitializes COM. There's also a DatabaseConnection - * for this thread's default access to the database. More DatabaseConnections - * can always be created, but State has one that can always be used by - * the thread whose state is represented. - * - * This class is intended to be one-per-thread, so it should be accessed - * via thread-specific storage. - */ -struct State { - State(); - ~State(); - DatabaseConnection *dbConn; -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_STATE_H */ diff --git a/cpp/src/qpid/store/ms-sql/TplRecordset.cpp b/cpp/src/qpid/store/ms-sql/TplRecordset.cpp deleted file mode 100644 index 1309d921a9..0000000000 --- a/cpp/src/qpid/store/ms-sql/TplRecordset.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include <string>
-#include <qpid/Exception.h>
-#include <qpid/log/Statement.h>
-
-#include "TplRecordset.h"
-#include "BlobEncoder.h"
-#include "DatabaseConnection.h"
-#include "VariantHelper.h"
-
-namespace {
-inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};
-}
-
-namespace qpid {
-namespace store {
-namespace ms_sql {
-
-void
-TplRecordset::open(DatabaseConnection* conn, const std::string& table)
-{
- init(conn, table);
- // Don't actually open until we know what to do. It's far easier and more
- // efficient to simply do most of these TPL/xid ops in a single statement.
-}
-
-void
-TplRecordset::add(const std::string& xid)
-{
- const std::string command =
- "INSERT INTO " + tableName + " ( xid ) VALUES ( ? )";
- _CommandPtr cmd = NULL;
- _ParameterPtr xidVal = NULL;
-
- TESTHR(cmd.CreateInstance(__uuidof(Command)));
- TESTHR(xidVal.CreateInstance(__uuidof(Parameter)));
- _ConnectionPtr p = *dbConn;
- cmd->ActiveConnection = p;
- cmd->CommandText = command.c_str();
- cmd->CommandType = adCmdText;
- xidVal->Name = "@xid";
- xidVal->Type = adVarBinary;
- xidVal->Size = xid.length();
- xidVal->Direction = adParamInput;
- xidVal->Value = BlobEncoder(xid);
- cmd->Parameters->Append(xidVal);
- cmd->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
-}
-
-void
-TplRecordset::remove(const std::string& xid)
-{
- // Look up the item by its xid
- const std::string command =
- "DELETE FROM " + tableName + " WHERE xid = ?";
- _CommandPtr cmd = NULL;
- _ParameterPtr xidVal = NULL;
-
- TESTHR(cmd.CreateInstance(__uuidof(Command)));
- TESTHR(xidVal.CreateInstance(__uuidof(Parameter)));
- _ConnectionPtr p = *dbConn;
- cmd->ActiveConnection = p;
- cmd->CommandText = command.c_str();
- cmd->CommandType = adCmdText;
- xidVal->Name = "@xid";
- xidVal->Type = adVarBinary;
- xidVal->Size = xid.length();
- xidVal->Direction = adParamInput;
- xidVal->Value = BlobEncoder(xid);
- cmd->Parameters->Append(xidVal);
- _variant_t deletedRecords;
- cmd->Execute(&deletedRecords, NULL, adCmdText | adExecuteNoRecords);
-}
-
-void
-TplRecordset::recover(std::set<std::string>& xids)
-{
- openRs();
- if (rs->BOF && rs->EndOfFile)
- return; // Nothing to do
- rs->MoveFirst();
- while (!rs->EndOfFile) {
- _variant_t wxid = rs->Fields->Item["xid"]->Value;
- char *xidBytes;
- SafeArrayAccessData(wxid.parray, (void **)&xidBytes);
- std::string xid(xidBytes, rs->Fields->Item["xid"]->ActualSize);
- xids.insert(xid);
- SafeArrayUnaccessData(wxid.parray);
- rs->MoveNext();
- }
-}
-
-void
-TplRecordset::dump()
-{
- Recordset::dump();
- if (rs->EndOfFile && rs->BOF) // No records
- return;
-
- rs->MoveFirst();
- while (!rs->EndOfFile) {
- _bstr_t wxid = rs->Fields->Item["xid"]->Value;
- QPID_LOG(notice, " -> " << (const char *)wxid);
- rs->MoveNext();
- }
-}
-
-}}} // namespace qpid::store::ms_sql
diff --git a/cpp/src/qpid/store/ms-sql/TplRecordset.h b/cpp/src/qpid/store/ms-sql/TplRecordset.h deleted file mode 100644 index fbde51738c..0000000000 --- a/cpp/src/qpid/store/ms-sql/TplRecordset.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef QPID_STORE_MSSQL_TPLRECORDSET_H
-#define QPID_STORE_MSSQL_TPLRECORDSET_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "Recordset.h"
-#include <string>
-#include <set>
-
-namespace qpid {
-namespace store {
-namespace ms_sql {
-
-/**
- * @class TplRecordset
- *
- * Class for the TPL (Transaction Prepared List) records.
- */
-class TplRecordset : public Recordset {
-protected:
-
-public:
- virtual void open(DatabaseConnection* conn, const std::string& table);
-
- void add(const std::string& xid);
-
- // Remove a record given its xid.
- void remove(const std::string& xid);
-
- // Recover prepared transaction XIDs.
- void recover(std::set<std::string>& xids);
-
- // Dump table contents; useful for debugging.
- void dump();
-};
-
-}}} // namespace qpid::store::ms_sql
-
-#endif /* QPID_STORE_MSSQL_TPLRECORDSET_H */
diff --git a/cpp/src/qpid/store/ms-sql/VariantHelper.cpp b/cpp/src/qpid/store/ms-sql/VariantHelper.cpp deleted file mode 100644 index acec95c1f9..0000000000 --- a/cpp/src/qpid/store/ms-sql/VariantHelper.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include "VariantHelper.h" - -namespace qpid { -namespace store { -namespace ms_sql { - -template <class Wrapped> -VariantHelper<Wrapped>::VariantHelper() -{ - var.vt = VT_EMPTY; -} - -template <class Wrapped> -VariantHelper<Wrapped>::operator const _variant_t& () const -{ - return var; -} - -// Specialization for using _variant_t to wrap a std::string -VariantHelper<std::string>::VariantHelper(const std::string &init) -{ - if (init.empty() || init.length() == 0) { - var.vt = VT_BSTR; - var.bstrVal = NULL; - } - else { - var.SetString(init.c_str()); - } -} - -VariantHelper<std::string>& -VariantHelper<std::string>::operator=(const std::string &rhs) -{ - if (rhs.empty() || rhs.length() == 0) { - var.vt = VT_BSTR; - var.bstrVal = NULL; - } - else { - var.SetString(rhs.c_str()); - } - return *this; -} - -VariantHelper<std::string>::operator const _variant_t& () const -{ - return var; -} - -}}} // namespace qpid::store::ms_sql diff --git a/cpp/src/qpid/store/ms-sql/VariantHelper.h b/cpp/src/qpid/store/ms-sql/VariantHelper.h deleted file mode 100644 index 723dbc3b76..0000000000 --- a/cpp/src/qpid/store/ms-sql/VariantHelper.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_STORE_MSSQL_VARIANTHELPER_H -#define QPID_STORE_MSSQL_VARIANTHELPER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <comutil.h> - -namespace qpid { -namespace store { -namespace ms_sql { - -/** - * @class VariantHelper - * - * Class template to wrap the details of working with _variant_t objects. - */ -template <class Wrapped> class VariantHelper { -private: - _variant_t var; - -public: - VariantHelper(); - VariantHelper(const Wrapped &init); - - VariantHelper& operator =(const Wrapped& rhs); - operator const _variant_t& () const; -}; - -// Specialization for using _variant_t to wrap a std::string -template<> class VariantHelper<std::string> { -private: - _variant_t var; - -public: - VariantHelper(const std::string &init); - VariantHelper& operator =(const std::string& rhs); - operator const _variant_t& () const; -}; - -}}} // namespace qpid::store::ms_sql - -#endif /* QPID_STORE_MSSQL_VARIANTHELPER_H */ diff --git a/cpp/src/qpid/sys/AggregateOutput.cpp b/cpp/src/qpid/sys/AggregateOutput.cpp deleted file mode 100644 index fc95f46fb9..0000000000 --- a/cpp/src/qpid/sys/AggregateOutput.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/AggregateOutput.h" -#include "qpid/log/Statement.h" -#include <algorithm> - -namespace qpid { -namespace sys { - -AggregateOutput::AggregateOutput(OutputControl& c) : busy(false), control(c) {} - -void AggregateOutput::abort() { control.abort(); } - -void AggregateOutput::activateOutput() { control.activateOutput(); } - -void AggregateOutput::giveReadCredit(int32_t credit) { control.giveReadCredit(credit); } - -namespace { -// Clear the busy flag and notify waiting threads in destructor. -struct ScopedBusy { - bool& flag; - Monitor& monitor; - ScopedBusy(bool& f, Monitor& m) : flag(f), monitor(m) { f = true; } - ~ScopedBusy() { flag = false; monitor.notifyAll(); } -}; -} - -bool AggregateOutput::doOutput() { - Mutex::ScopedLock l(lock); - ScopedBusy sb(busy, lock); - - while (!tasks.empty()) { - OutputTask* t=tasks.front(); - tasks.pop_front(); - bool didOutput; - { - // Allow concurrent call to addOutputTask. - // removeOutputTask will wait till !busy before removing a task. - Mutex::ScopedUnlock u(lock); - didOutput = t->doOutput(); - } - if (didOutput) { - tasks.push_back(t); - return true; - } - } - return false; -} - -void AggregateOutput::addOutputTask(OutputTask* task) { - Mutex::ScopedLock l(lock); - tasks.push_back(task); -} - -void AggregateOutput::removeOutputTask(OutputTask* task) { - Mutex::ScopedLock l(lock); - while (busy) lock.wait(); - tasks.erase(std::remove(tasks.begin(), tasks.end(), task), tasks.end()); -} - -void AggregateOutput::removeAll() -{ - Mutex::ScopedLock l(lock); - while (busy) lock.wait(); - tasks.clear(); -} - - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/AggregateOutput.h b/cpp/src/qpid/sys/AggregateOutput.h deleted file mode 100644 index d7c0ff29e3..0000000000 --- a/cpp/src/qpid/sys/AggregateOutput.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _AggregateOutput_ -#define _AggregateOutput_ - -#include "qpid/sys/Monitor.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/sys/OutputTask.h" -#include "qpid/CommonImportExport.h" - -#include <algorithm> -#include <deque> - -namespace qpid { -namespace sys { - -/** - * Holds a collection of output tasks, doOutput picks the next one to execute. - * - * Tasks are automatically removed if their doOutput() or hasOutput() returns false. - * - * Thread safe. addOutputTask may be called in one connection thread while - * doOutput is called in another. - */ - -class QPID_COMMON_CLASS_EXTERN AggregateOutput : public OutputTask, public OutputControl -{ - typedef std::deque<OutputTask*> TaskList; - - Monitor lock; - TaskList tasks; - bool busy; - OutputControl& control; - - public: - QPID_COMMON_EXTERN AggregateOutput(OutputControl& c); - - // These may be called concurrently with any function. - QPID_COMMON_EXTERN void abort(); - QPID_COMMON_EXTERN void activateOutput(); - QPID_COMMON_EXTERN void giveReadCredit(int32_t); - QPID_COMMON_EXTERN void addOutputTask(OutputTask* t); - - // These functions must not be called concurrently with each other. - QPID_COMMON_EXTERN bool doOutput(); - QPID_COMMON_EXTERN void removeOutputTask(OutputTask* t); - QPID_COMMON_EXTERN void removeAll(); - - /** Apply f to each OutputTask* in the tasks list */ - template <class F> void eachOutput(F f) { - Mutex::ScopedLock l(lock); - std::for_each(tasks.begin(), tasks.end(), f); - } -}; - -}} // namespace qpid::sys - - -#endif diff --git a/cpp/src/qpid/sys/AsynchIO.h b/cpp/src/qpid/sys/AsynchIO.h deleted file mode 100644 index 50da8fa4fc..0000000000 --- a/cpp/src/qpid/sys/AsynchIO.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef _sys_AsynchIO -#define _sys_AsynchIO -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" -#include "qpid/CommonImportExport.h" - -#include <string.h> - -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace sys { - -class Socket; -class Poller; - -/* - * Asynchronous acceptor: accepts connections then does a callback with the - * accepted fd - */ -class AsynchAcceptor { -public: - typedef boost::function1<void, const Socket&> Callback; - - QPID_COMMON_EXTERN static AsynchAcceptor* create(const Socket& s, Callback callback); - virtual ~AsynchAcceptor() {}; - virtual void start(boost::shared_ptr<Poller> poller) = 0; -}; - -/* - * Asynchronous connector: starts the process of initiating a connection and - * invokes a callback when completed or failed. - */ -class AsynchConnector { -public: - typedef boost::function1<void, const Socket&> ConnectedCallback; - typedef boost::function3<void, const Socket&, int, const std::string&> FailedCallback; - - // Call create() to allocate a new AsynchConnector object with the - // specified poller, addressing, and callbacks. - // This method is implemented in platform-specific code to - // create a correctly typed object. The platform code also manages - // deletes. To correctly manage heaps when needed, the allocate and - // delete should both be done from the same class/library. - QPID_COMMON_EXTERN static AsynchConnector* create(const Socket& s, - std::string hostname, - uint16_t port, - ConnectedCallback connCb, - FailedCallback failCb); - virtual void start(boost::shared_ptr<Poller> poller) = 0; - virtual void stop() {}; -protected: - AsynchConnector() {} - virtual ~AsynchConnector() {} -}; - -struct AsynchIOBufferBase { - char* const bytes; - const int32_t byteCount; - int32_t dataStart; - int32_t dataCount; - - AsynchIOBufferBase(char* const b, const int32_t s) : - bytes(b), - byteCount(s), - dataStart(0), - dataCount(0) - {} - - virtual ~AsynchIOBufferBase() - {} - - void squish() { - if (dataStart != 0) { - ::memmove(bytes, bytes + dataStart, dataCount); - dataStart = 0; - } - } -}; - -/* - * Asychronous reader/writer: - * Reader accepts buffers to read into; reads into the provided buffers - * and then does a callback with the buffer and amount read. Optionally it - * can callback when there is something to read but no buffer to read it into. - * - * Writer accepts a buffer and queues it for writing; can also be given - * a callback for when writing is "idle" (ie fd is writable, but nothing - * to write). - */ -class AsynchIO { -public: - typedef AsynchIOBufferBase BufferBase; - - typedef boost::function2<void, AsynchIO&, BufferBase*> ReadCallback; - typedef boost::function1<void, AsynchIO&> EofCallback; - typedef boost::function1<void, AsynchIO&> DisconnectCallback; - typedef boost::function2<void, AsynchIO&, const Socket&> ClosedCallback; - typedef boost::function1<void, AsynchIO&> BuffersEmptyCallback; - typedef boost::function1<void, AsynchIO&> IdleCallback; - typedef boost::function1<void, AsynchIO&> RequestCallback; - - // Call create() to allocate a new AsynchIO object with the specified - // callbacks. This method is implemented in platform-specific code to - // create a correctly typed object. The platform code also manages - // deletes. To correctly manage heaps when needed, the allocate and - // delete should both be done from the same class/library. - QPID_COMMON_EXTERN static AsynchIO* create(const Socket& s, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0); -public: - virtual void queueForDeletion() = 0; - - virtual void start(boost::shared_ptr<Poller> poller) = 0; - virtual void queueReadBuffer(BufferBase* buff) = 0; - virtual void unread(BufferBase* buff) = 0; - virtual void queueWrite(BufferBase* buff) = 0; - virtual void notifyPendingWrite() = 0; - virtual void queueWriteClose() = 0; - virtual bool writeQueueEmpty() = 0; - virtual void startReading() = 0; - virtual void stopReading() = 0; - virtual void requestCallback(RequestCallback) = 0; - virtual BufferBase* getQueuedBuffer() = 0; - -protected: - // Derived class manages lifetime; must be constructed using the - // static create() method. Deletes not allowed from outside. - AsynchIO() {} - virtual ~AsynchIO() {} -}; - -}} - -#endif // _sys_AsynchIO diff --git a/cpp/src/qpid/sys/AsynchIOHandler.cpp b/cpp/src/qpid/sys/AsynchIOHandler.cpp deleted file mode 100644 index 30a87d9d44..0000000000 --- a/cpp/src/qpid/sys/AsynchIOHandler.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/AsynchIOHandler.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/log/Statement.h" - -#include <boost/bind.hpp> - -namespace qpid { -namespace sys { - -// Buffer definition -struct Buff : public AsynchIO::BufferBase { - Buff() : - AsynchIO::BufferBase(new char[65536], 65536) - {} - ~Buff() - { delete [] bytes;} -}; - -AsynchIOHandler::AsynchIOHandler(std::string id, ConnectionCodec::Factory* f) : - identifier(id), - aio(0), - factory(f), - codec(0), - readError(false), - isClient(false), - readCredit(InfiniteCredit) -{} - -AsynchIOHandler::~AsynchIOHandler() { - if (codec) - codec->closed(); - delete codec; -} - -void AsynchIOHandler::init(AsynchIO* a, int numBuffs) { - aio = a; - - // Give connection some buffers to use - for (int i = 0; i < numBuffs; i++) { - aio->queueReadBuffer(new Buff); - } -} - -void AsynchIOHandler::write(const framing::ProtocolInitiation& data) -{ - QPID_LOG(debug, "SENT [" << identifier << "] INIT(" << data << ")"); - AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); - if (!buff) - buff = new Buff; - framing::Buffer out(buff->bytes, buff->byteCount); - data.encode(out); - buff->dataCount = data.encodedSize(); - aio->queueWrite(buff); -} - -void AsynchIOHandler::abort() { - // Don't disconnect if we're already disconnecting - if (!readError) { - aio->requestCallback(boost::bind(&AsynchIOHandler::eof, this, _1)); - } -} - -void AsynchIOHandler::activateOutput() { - aio->notifyPendingWrite(); -} - -// Input side -void AsynchIOHandler::giveReadCredit(int32_t credit) { - // Check whether we started in the don't about credit state - if (readCredit.boolCompareAndSwap(InfiniteCredit, credit)) - return; - // TODO In theory should be able to use an atomic operation before taking the lock - // but in practice there seems to be an unexplained race in that case - ScopedLock<Mutex> l(creditLock); - if (readCredit.fetchAndAdd(credit) != 0) - return; - assert(readCredit.get() >= 0); - if (readCredit.get() != 0) - aio->startReading(); -} - -void AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) { - if (readError) { - return; - } - - // Check here for read credit - if (readCredit.get() != InfiniteCredit) { - if (readCredit.get() == 0) { - // FIXME aconway 2009-10-01: Workaround to avoid "false wakeups". - // readbuff is sometimes called with no credit. - // This should be fixed somewhere else to avoid such calls. - aio->unread(buff); - return; - } - // TODO In theory should be able to use an atomic operation before taking the lock - // but in practice there seems to be an unexplained race in that case - ScopedLock<Mutex> l(creditLock); - if (--readCredit == 0) { - assert(readCredit.get() >= 0); - if (readCredit.get() == 0) { - aio->stopReading(); - } - } - } - - size_t decoded = 0; - if (codec) { // Already initiated - try { - decoded = codec->decode(buff->bytes+buff->dataStart, buff->dataCount); - }catch(const std::exception& e){ - QPID_LOG(error, e.what()); - readError = true; - aio->queueWriteClose(); - } - }else{ - framing::Buffer in(buff->bytes+buff->dataStart, buff->dataCount); - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - decoded = in.getPosition(); - QPID_LOG(debug, "RECV [" << identifier << "] INIT(" << protocolInit << ")"); - try { - codec = factory->create(protocolInit.getVersion(), *this, identifier, SecuritySettings()); - if (!codec) { - //TODO: may still want to revise this... - //send valid version header & close connection. - write(framing::ProtocolInitiation(framing::highestProtocolVersion)); - readError = true; - aio->queueWriteClose(); - } - } catch (const std::exception& e) { - QPID_LOG(error, e.what()); - readError = true; - aio->queueWriteClose(); - } - } - } - // TODO: unreading needs to go away, and when we can cope - // with multiple sub-buffers in the general buffer scheme, it will - if (decoded != size_t(buff->dataCount)) { - // Adjust buffer for used bytes and then "unread them" - buff->dataStart += decoded; - buff->dataCount -= decoded; - aio->unread(buff); - } else { - // Give whole buffer back to aio subsystem - aio->queueReadBuffer(buff); - } -} - -void AsynchIOHandler::eof(AsynchIO& a) { - disconnect(a); - readError = true; - aio->queueWriteClose(); -} - -void AsynchIOHandler::closedSocket(AsynchIO&, const Socket& s) { - // If we closed with data still to send log a warning - if (!aio->writeQueueEmpty()) { - QPID_LOG(warning, "CLOSING [" << identifier << "] unsent data (probably due to client disconnect)"); - } - delete &s; - aio->queueForDeletion(); - delete this; -} - -void AsynchIOHandler::disconnect(AsynchIO&) { - QPID_LOG(debug, "DISCONNECTED [" << identifier << "]"); - if (codec) codec->closed(); -} - -// Notifications -void AsynchIOHandler::nobuffs(AsynchIO&) { -} - -void AsynchIOHandler::idle(AsynchIO&){ - if (isClient && codec == 0) { - codec = factory->create(*this, identifier, SecuritySettings()); - write(framing::ProtocolInitiation(codec->getVersion())); - return; - } - if (codec == 0) return; - try { - if (codec->canEncode()) { - // Try and get a queued buffer if not then construct new one - AsynchIO::BufferBase* buff = aio->getQueuedBuffer(); - if (!buff) buff = new Buff; - size_t encoded=codec->encode(buff->bytes, buff->byteCount); - buff->dataCount = encoded; - aio->queueWrite(buff); - } - if (codec->isClosed()) { - readError = true; - aio->queueWriteClose(); - } - } catch (const std::exception& e) { - QPID_LOG(error, e.what()); - readError = true; - aio->queueWriteClose(); - } -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/AsynchIOHandler.h b/cpp/src/qpid/sys/AsynchIOHandler.h deleted file mode 100644 index b9867606c4..0000000000 --- a/cpp/src/qpid/sys/AsynchIOHandler.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef _sys_AsynchIOHandler_h -#define _sys_AsynchIOHandler_h -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/OutputControl.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { - -namespace framing { - class ProtocolInitiation; -} - -namespace sys { - -class AsynchIO; -struct AsynchIOBufferBase; -class Socket; - -class AsynchIOHandler : public OutputControl { - std::string identifier; - AsynchIO* aio; - ConnectionCodec::Factory* factory; - ConnectionCodec* codec; - bool readError; - bool isClient; - AtomicValue<int32_t> readCredit; - static const int32_t InfiniteCredit = -1; - Mutex creditLock; - - void write(const framing::ProtocolInitiation&); - - public: - QPID_COMMON_EXTERN AsynchIOHandler(std::string id, ConnectionCodec::Factory* f); - QPID_COMMON_EXTERN ~AsynchIOHandler(); - QPID_COMMON_EXTERN void init(AsynchIO* a, int numBuffs); - - QPID_COMMON_INLINE_EXTERN void setClient() { isClient = true; } - - // Output side - QPID_COMMON_EXTERN void abort(); - QPID_COMMON_EXTERN void activateOutput(); - QPID_COMMON_EXTERN void giveReadCredit(int32_t credit); - - // Input side - QPID_COMMON_EXTERN void readbuff(AsynchIO& aio, AsynchIOBufferBase* buff); - QPID_COMMON_EXTERN void eof(AsynchIO& aio); - QPID_COMMON_EXTERN void disconnect(AsynchIO& aio); - - // Notifications - QPID_COMMON_EXTERN void nobuffs(AsynchIO& aio); - QPID_COMMON_EXTERN void idle(AsynchIO& aio); - QPID_COMMON_EXTERN void closedSocket(AsynchIO& aio, const Socket& s); -}; - -}} // namespace qpid::sys - -#endif // _sys_AsynchIOHandler_h diff --git a/cpp/src/qpid/sys/AtomicCount.h b/cpp/src/qpid/sys/AtomicCount.h deleted file mode 100644 index 94580c61f3..0000000000 --- a/cpp/src/qpid/sys/AtomicCount.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _posix_AtomicCount_h -#define _posix_AtomicCount_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <boost/detail/atomic_count.hpp> -#include "qpid/sys/ScopedIncrement.h" - -namespace qpid { -namespace sys { - -/** - * Atomic counter. - */ -class AtomicCount { - public: - typedef ::qpid::sys::ScopedDecrement<AtomicCount> ScopedDecrement; - typedef ::qpid::sys::ScopedIncrement<AtomicCount> ScopedIncrement; - - AtomicCount(long value = 0) : count(value) {} - - void operator++() { ++count ; } - - long operator--() { return --count; } - - operator long() const { return count; } - - private: - boost::detail::atomic_count count; -}; - - -}} - - -#endif // _posix_AtomicCount_h diff --git a/cpp/src/qpid/sys/AtomicValue.h b/cpp/src/qpid/sys/AtomicValue.h deleted file mode 100644 index bf995f991e..0000000000 --- a/cpp/src/qpid/sys/AtomicValue.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef QPID_SYS_ATOMICVALUE_H -#define QPID_SYS_ATOMICVALUE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// Have to check for clang before gcc as clang pretends to be gcc too -#if defined( __clang__ ) -// Use the clang doesn't support atomic builtins for 64 bit values, so use the slow versions -#include "qpid/sys/AtomicValue_mutex.h" - -#elif defined( __GNUC__ ) && __GNUC__ >= 4 && ( defined( __i686__ ) || defined( __x86_64__ ) ) -// Use the Gnu C built-in atomic operations if compiling with gcc on a suitable platform. -#include "qpid/sys/AtomicValue_gcc.h" - -#else -// Fall-back to mutex locked operations if we don't have atomic ops. -#include "qpid/sys/AtomicValue_mutex.h" -#endif - -#endif /*!QPID_SYS_ATOMICVALUE_GCC_H*/ diff --git a/cpp/src/qpid/sys/AtomicValue_gcc.h b/cpp/src/qpid/sys/AtomicValue_gcc.h deleted file mode 100644 index d022b07c1d..0000000000 --- a/cpp/src/qpid/sys/AtomicValue_gcc.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_SYS_ATOMICVALUE_GCC_H -#define QPID_SYS_ATOMICVALUE_GCC_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#if !defined(QPID_SYS_ATOMICVALUE_H) -#error "This file should only be included via AtomicValue.h." -#endif - -namespace qpid { -namespace sys { - -/** - * Atomic value of type T. T must be an integral type of size 1,2,4 or 8 bytes. - * All operations are atomic and preform a full memory barrier unless otherwise noted. - */ -template <class T> -class AtomicValue -{ - public: - AtomicValue(T init=0) : value(init) {} - - // Update and return new value. - inline T operator+=(T n) { return __sync_add_and_fetch(&value, n); } - inline T operator-=(T n) { return __sync_sub_and_fetch(&value, n); } - inline T operator++() { return *this += 1; } - inline T operator--() { return *this -= 1; } - - // Update and return old value. - inline T fetchAndAdd(T n) { return __sync_fetch_and_add(&value, n); } - inline T fetchAndSub(T n) { return __sync_fetch_and_sub(&value, n); } - inline T operator++(int) { return fetchAndAdd(1); } - inline T operator--(int) { return fetchAndSub(1); } - - /** If current value == testval then set to newval. Returns the old value. */ - T valueCompareAndSwap(T testval, T newval) { return __sync_val_compare_and_swap(&value, testval, newval); } - - /** If current value == testval then set to newval. Returns true if the swap was performed. */ - bool boolCompareAndSwap(T testval, T newval) { return __sync_bool_compare_and_swap(&value, testval, newval); } - - T get() const { return const_cast<AtomicValue<T>*>(this)->fetchAndAdd(static_cast<T>(0)); } - - private: - T value; -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_ATOMICVALUE_GCC_H*/ diff --git a/cpp/src/qpid/sys/AtomicValue_mutex.h b/cpp/src/qpid/sys/AtomicValue_mutex.h deleted file mode 100644 index e4d433e7f5..0000000000 --- a/cpp/src/qpid/sys/AtomicValue_mutex.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef QPID_SYS_ATOMICVALUE_MUTEX_H -#define QPID_SYS_ATOMICVALUE_MUTEX_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#if !defined(QPID_SYS_ATOMICVALUE_H) -#error "This file should only be included via AtomicValue.h." -#endif - -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace sys { - -/** - * Atomic value of type T. T must be an integral type of size 1,2,4 or 8 bytes. - * All operations are atomic and preform a full memory barrier unless otherwise noted. - */ -template <class T> -class AtomicValue -{ - public: - AtomicValue(T init=0) : value(init) {} - - // Update and return new value. - inline T operator+=(T n) { Lock l(lock); return value += n; } - inline T operator-=(T n) { Lock l(lock); return value -= n; } - inline T operator++() { return *this += 1; } - inline T operator--() { return *this -= 1; } - - // Update and return old value. - inline T fetchAndAdd(T n) { Lock l(lock); T old=value; value += n; return old; } - inline T fetchAndSub(T n) { Lock l(lock); T old=value; value -= n; return old; } - inline T operator++(int) { return fetchAndAdd(1); } - inline T operator--(int) { return fetchAndSub(1); } - - AtomicValue& operator=(T newval) { Lock l(lock); value = newval; return *this; } - - /** If current value == testval then set to newval. Returns the old value. */ - T valueCompareAndSwap(T testval, T newval) { - Lock l(lock); - T old=value; - if (value == testval) value = newval; - return old; - } - - /** If current value == testval then set to newval. Returns true if the swap was performed. */ - bool boolCompareAndSwap(T testval, T newval) { - Lock l(lock); - if (value == testval) { value = newval; return true; } - return false; - } - - T get() const { Lock l(lock); return value; } - - private: - typedef Mutex::ScopedLock Lock; - T value; - mutable Mutex lock; -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_ATOMICVALUE_MUTEX_H*/ diff --git a/cpp/src/qpid/sys/BlockingQueue.h b/cpp/src/qpid/sys/BlockingQueue.h deleted file mode 100644 index ca6b529930..0000000000 --- a/cpp/src/qpid/sys/BlockingQueue.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef QPID_SYS_BLOCKINGQUEUE_H -#define QPID_SYS_BLOCKINGQUEUE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Waitable.h" - -#include <queue> - -namespace qpid { -namespace sys { - -/** - * A simple blocking queue template - */ -template <class T> -class BlockingQueue -{ - mutable sys::Waitable waitable; - std::queue<T> queue; - -public: - BlockingQueue() {} - ~BlockingQueue() { close(); } - - /** Pop from the queue, block up to timeout if empty. - *@param result Set to value popped from queue. - *@param timeout Defaults to infinite. - *@return true if result was set, false if queue empty after timeout. - */ - bool pop(T& result, Duration timeout=TIME_INFINITE) { - Mutex::ScopedLock l(waitable); - { - Waitable::ScopedWait w(waitable); - if (timeout == TIME_INFINITE) { - while (queue.empty()) waitable.wait(); - } else if (timeout) { - AbsTime deadline(now(),timeout); - while (queue.empty() && deadline > now()) waitable.wait(deadline); - } else { - //ensure zero timeout pop does not miss the fact that - //queue is closed - waitable.checkException(); - } - } - if (queue.empty()) return false; - result = queue.front(); - queue.pop(); - if (!queue.empty()) - waitable.notify(); // Notify another waiter. - return true; - } - - T pop(Duration timeout=TIME_INFINITE) { - T result; - bool ok = pop(result, timeout); - if (!ok) - throw Exception("Timed out waiting on a blocking queue"); - return result; - } - - /** Push a value onto the queue. - * Note it is not an error to push onto a closed queue. - */ - void push(const T& t) { - Mutex::ScopedLock l(waitable); - queue.push(t); - waitable.notify(); // Notify a waiter. - } - - /** - * Close the queue. - *@ex exception to throw to waiting threads. ClosedException by default. - */ - void close(const ExceptionHolder& ex=ExceptionHolder(new ClosedException())) - { - Mutex::ScopedLock l(waitable); - if (!waitable.hasException()) { - waitable.setException(ex); - waitable.notifyAll(); - waitable.waitWaiters(); // Ensure no threads are still waiting. - } - } - - /** Open a closed queue. */ - void open() { - Mutex::ScopedLock l(waitable); - waitable.resetException(); - } - - bool isClosed() const { - Mutex::ScopedLock l(waitable); - return waitable.hasException(); - } - - bool empty() const { - Mutex::ScopedLock l(waitable); - return queue.empty(); - } - size_t size() const { - Mutex::ScopedLock l(waitable); - return queue.size(); - } -}; - -}} - - - -#endif /*!QPID_SYS_BLOCKINGQUEUE_H*/ diff --git a/cpp/src/qpid/sys/ClusterSafe.cpp b/cpp/src/qpid/sys/ClusterSafe.cpp deleted file mode 100644 index dd37615145..0000000000 --- a/cpp/src/qpid/sys/ClusterSafe.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "ClusterSafe.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Thread.h" -#include <stdlib.h> - -namespace qpid { -namespace sys { - -namespace { -bool inCluster = false; -QPID_TSS bool inContext = false; -} - -bool isClusterSafe() { return !inCluster || inContext; } - -void assertClusterSafe() { - if (!isClusterSafe()) { - QPID_LOG(critical, "Modified cluster state outside of cluster context"); - ::abort(); - } -} - -ClusterSafeScope::ClusterSafeScope() { - save = inContext; - inContext = true; -} - -ClusterSafeScope::~ClusterSafeScope() { - assert(inContext); - inContext = save; -} - -ClusterUnsafeScope::ClusterUnsafeScope() { - save = inContext; - inContext = false; -} - -ClusterUnsafeScope::~ClusterUnsafeScope() { - assert(!inContext); - inContext = save; -} - -void enableClusterSafe() { inCluster = true; } - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/ClusterSafe.h b/cpp/src/qpid/sys/ClusterSafe.h deleted file mode 100644 index 27e4eb46a5..0000000000 --- a/cpp/src/qpid/sys/ClusterSafe.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef QPID_SYS_CLUSTERSAFE_H -#define QPID_SYS_CLUSTERSAFE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace sys { - -/** - * Assertion to add to code that modifies clustered state. - * - * In a non-clustered broker this is a no-op. - * - * In a clustered broker, checks that it is being called - * in a context where it is safe to modify clustered state. - * If not it aborts the process as this is a serious bug. - * - * This function is in the common library rather than the cluster - * library because it is called by code in the broker library. - */ -QPID_COMMON_EXTERN void assertClusterSafe(); - -/** - * In a non-clustered broker, returns true. - * - * In a clustered broker returns true if we are in a context where it - * is safe to modify cluster state. - * - * This function is in the common library rather than the cluster - * library because it is called by code in the broker library. - */ -QPID_COMMON_EXTERN bool isClusterSafe(); - -/** - * Mark a scope as cluster safe. Sets isClusterSafe in constructor and resets - * to previous value in destructor. - */ -class ClusterSafeScope { - public: - ClusterSafeScope(); - ~ClusterSafeScope(); - private: - bool save; -}; - -/** - * Mark a scope as cluster unsafe. Clears isClusterSafe in constructor and resets - * to previous value in destructor. - */ -class ClusterUnsafeScope { - public: - QPID_COMMON_EXTERN ClusterUnsafeScope(); - QPID_COMMON_EXTERN ~ClusterUnsafeScope(); - private: - bool save; -}; - -/** - * Enable cluster-safe assertions. By default they are no-ops. - * Called by cluster code. - */ -void enableClusterSafe(); - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_CLUSTERSAFE_H*/ diff --git a/cpp/src/qpid/sys/Codec.h b/cpp/src/qpid/sys/Codec.h deleted file mode 100644 index ace721fbcc..0000000000 --- a/cpp/src/qpid/sys/Codec.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef QPID_SYS_CODEC_H -#define QPID_SYS_CODEC_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <cstddef> - -namespace qpid { -namespace sys { - -/** - * Generic codec interface - */ -class Codec -{ - public: - virtual ~Codec() {} - - /** Decode from buffer, return number of bytes decoded. - * @return may be less than size if there was incomplete - * data at the end of the buffer. - */ - virtual std::size_t decode(const char* buffer, std::size_t size) = 0; - - - /** Encode into buffer, return number of bytes encoded */ - virtual std::size_t encode(const char* buffer, std::size_t size) = 0; - - /** Return true if we have data to encode */ - virtual bool canEncode() = 0; -}; -}} // namespace qpid::sys - -#endif /*!QPID_SYS_CODEC_H*/ diff --git a/cpp/src/qpid/sys/ConnectionCodec.h b/cpp/src/qpid/sys/ConnectionCodec.h deleted file mode 100644 index c2890f06dc..0000000000 --- a/cpp/src/qpid/sys/ConnectionCodec.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_SYS_CONNECTION_CODEC_H -#define QPID_SYS_CONNECTION_CODEC_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Codec.h" -#include "qpid/framing/ProtocolVersion.h" - -namespace qpid { - -namespace sys { - -class InputHandlerFactory; -class OutputControl; -struct SecuritySettings; - -/** - * Interface of coder/decoder for a connection of a specific protocol - * version. - */ -class ConnectionCodec : public Codec { - public: - virtual ~ConnectionCodec() {} - - /** Network connection was closed from other end. */ - virtual void closed() = 0; - - virtual bool isClosed() const = 0; - - virtual framing::ProtocolVersion getVersion() const = 0; - - struct Factory { - virtual ~Factory() {} - - /** Return 0 if version unknown */ - virtual ConnectionCodec* create( - framing::ProtocolVersion, OutputControl&, const std::string& id, - const SecuritySettings& - ) = 0; - - /** Return "preferred" codec for outbound connections. */ - virtual ConnectionCodec* create( - OutputControl&, const std::string& id, const SecuritySettings& - ) = 0; - }; -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_CONNECTION_CODEC_H*/ diff --git a/cpp/src/qpid/sys/ConnectionInputHandler.h b/cpp/src/qpid/sys/ConnectionInputHandler.h deleted file mode 100644 index 92de808308..0000000000 --- a/cpp/src/qpid/sys/ConnectionInputHandler.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionInputHandler_ -#define _ConnectionInputHandler_ - -#include "qpid/framing/InputHandler.h" -#include "qpid/sys/OutputTask.h" -#include "qpid/sys/TimeoutHandler.h" - -namespace qpid { -namespace sys { - - -/** - * ConnectionInputHandler provides methods to process incoming frames - * using InputHandler::receive() and to generate outgoing messages in - * OutputTask::doOutput() - * - */ - - class ConnectionInputHandler : - public qpid::framing::InputHandler, - public TimeoutHandler, public OutputTask - { - public: - - virtual void closed() = 0; - }; - -} -} - - -#endif diff --git a/cpp/src/qpid/sys/ConnectionInputHandlerFactory.h b/cpp/src/qpid/sys/ConnectionInputHandlerFactory.h deleted file mode 100644 index 9bb7e13686..0000000000 --- a/cpp/src/qpid/sys/ConnectionInputHandlerFactory.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionInputHandlerFactory_ -#define _ConnectionInputHandlerFactory_ - -#include <boost/noncopyable.hpp> -#include <string> - -namespace qpid { -namespace sys { - -class ConnectionOutputHandler; -class ConnectionInputHandler; - -/** - * Callback interface used by the Acceptor to - * create a ConnectionInputHandler for each new connection. - */ -class ConnectionInputHandlerFactory : private boost::noncopyable -{ - public: - /** - *@param out handler for connection output. - *@param id identify the connection for management purposes. - */ - virtual ConnectionInputHandler* create(ConnectionOutputHandler* out, - const std::string& id, - bool isClient) = 0; - - virtual ~ConnectionInputHandlerFactory(){} -}; - -}} - - -#endif diff --git a/cpp/src/qpid/sys/ConnectionOutputHandler.h b/cpp/src/qpid/sys/ConnectionOutputHandler.h deleted file mode 100644 index 421dd7c269..0000000000 --- a/cpp/src/qpid/sys/ConnectionOutputHandler.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionOutputHandler_ -#define _ConnectionOutputHandler_ - -#include "qpid/framing/OutputHandler.h" -#include "qpid/sys/OutputControl.h" - -namespace qpid { -namespace sys { - -/** - * Provides the output handler associated with a connection. - */ -class ConnectionOutputHandler : public virtual qpid::framing::OutputHandler, public OutputControl -{ - public: - virtual void close() = 0; - virtual size_t getBuffered() const { return 0; } -}; - -}} - - -#endif diff --git a/cpp/src/qpid/sys/ConnectionOutputHandlerPtr.h b/cpp/src/qpid/sys/ConnectionOutputHandlerPtr.h deleted file mode 100644 index 95a08d15ae..0000000000 --- a/cpp/src/qpid/sys/ConnectionOutputHandlerPtr.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef QPID_SYS_CONNECTIONOUTPUTHANDLERPTR_H -#define QPID_SYS_CONNECTIONOUTPUTHANDLERPTR_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ConnectionOutputHandler.h" - -namespace qpid { -namespace sys { - -/** - * A ConnectionOutputHandler that delegates to another - * ConnectionOutputHandler. Allows the "real" ConnectionOutputHandler - * to be changed without updating all the pointers/references - * using the ConnectionOutputHandlerPtr - */ -class ConnectionOutputHandlerPtr : public ConnectionOutputHandler -{ - public: - ConnectionOutputHandlerPtr(ConnectionOutputHandler* p) : next(p) { assert(next); } - void set(ConnectionOutputHandler* p) { next = p; assert(next); } - ConnectionOutputHandler* get() { return next; } - const ConnectionOutputHandler* get() const { return next; } - - void close() { next->close(); } - size_t getBuffered() const { return next->getBuffered(); } - void abort() { next->abort(); } - void activateOutput() { next->activateOutput(); } - void giveReadCredit(int32_t credit) { next->giveReadCredit(credit); } - void send(framing::AMQFrame& f) { next->send(f); } - - private: - ConnectionOutputHandler* next; -}; -}} // namespace qpid::sys - -#endif /*!QPID_SYS_CONNECTIONOUTPUTHANDLERPTR_H*/ diff --git a/cpp/src/qpid/sys/CopyOnWriteArray.h b/cpp/src/qpid/sys/CopyOnWriteArray.h deleted file mode 100644 index 45a231dfd8..0000000000 --- a/cpp/src/qpid/sys/CopyOnWriteArray.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef QPID_SYS_COPYONWRITEARRAY_H -#define QPID_SYS_COPYONWRITEARRAY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Mutex.h" -#include <algorithm> -#include <vector> -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace sys { - -/** - * An array that copies on adding/removing element allowing lock-free - * iteration. - */ -template <class T> -class CopyOnWriteArray -{ -public: - typedef boost::shared_ptr<const std::vector<T> > ConstPtr; - - CopyOnWriteArray() {} - CopyOnWriteArray(const CopyOnWriteArray& c) : array(c.array) {} - - void add(T& t) - { - Mutex::ScopedLock l(lock); - ArrayPtr copy(array ? new std::vector<T>(*array) : new std::vector<T>()); - copy->push_back(t); - array = copy; - } - - bool remove(T& t) - { - Mutex::ScopedLock l(lock); - if (array && std::find(array->begin(), array->end(), t) != array->end()) { - ArrayPtr copy(new std::vector<T>(*array)); - copy->erase(std::find(copy->begin(), copy->end(), t)); - array = copy; - return true; - } else { - return false; - } - } - - bool clear() - { - Mutex::ScopedLock l(lock); - if (array && !array->empty()) { - ArrayPtr copy; - array = copy; - return true; - } else { - return false; - } - } - - template <class F> - bool add_unless(T& t, F f) - { - Mutex::ScopedLock l(lock); - if (array && std::find_if(array->begin(), array->end(), f) != array->end()) { - return false; - } else { - ArrayPtr copy(array ? new std::vector<T>(*array) : new std::vector<T>()); - copy->push_back(t); - array = copy; - return true; - } - } - - template <class F> - bool remove_if(F f) - { - Mutex::ScopedLock l(lock); - if (array && std::find_if(array->begin(), array->end(), f) != array->end()) { - ArrayPtr copy(new std::vector<T>(*array)); - copy->erase(std::remove_if(copy->begin(), copy->end(), f), copy->end()); - array = copy; - return true; - } - return false; - } - - template <class TestFn, class ModifierFn> - bool modify_if(TestFn f, ModifierFn & m) - { - if (!array) - return false; - { - Mutex::ScopedLock l(lock); - if (std::find_if(array->begin(), array->end(), f) != array->end()) - { - ArrayPtr copy(new std::vector<T>(*array)); - m(*std::find_if(copy->begin(), copy->end(), f)); - array = copy; - return true; - } - } - return false; - } - - template <class F> - F for_each(F f) - { - ArrayPtr a; - { - Mutex::ScopedLock l(lock); - a = array; - } - if (!a) return f; - return std::for_each(a->begin(), a->end(), f); - } - - ConstPtr snapshot() - { - ConstPtr a; - { - Mutex::ScopedLock l(lock); - a = array; - } - return a; - } - -private: - typedef boost::shared_ptr< std::vector<T> > ArrayPtr; - Mutex lock; - ArrayPtr array; -}; - -}} - - - -#endif /*!QPID_SYS_COPYONWRITEARRAY_H*/ diff --git a/cpp/src/qpid/sys/DeletionManager.h b/cpp/src/qpid/sys/DeletionManager.h deleted file mode 100644 index c1fea19f30..0000000000 --- a/cpp/src/qpid/sys/DeletionManager.h +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef _sys_DeletionManager_h -#define _sys_DeletionManager_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <vector> -#include <algorithm> -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace sys { - -struct deleter -{ - template <typename T> - void operator()(T* ptr){ delete ptr;} -}; - -/** - * DeletionManager keeps track of handles that need to be deleted but may still be - * in use by one of the threads concurrently. - * - * The mode of operation is like this: - * - When we want to delete but we might still be using the handle we - * * Transfer ownership of the handle to this class - * * Mark the handle as (potentially) in use by every thread - * - Then subsequently at points where the thread code knows it isn't - * using any handles it declares that it is using no handles - * - When the last thread declares no use of a handle it automatically - * gets deleted by the shared_ptr implementation - * - * The class only has static members and data and so can only be used once for - * any particular handle type - */ -template <typename H> -class DeletionManager -{ - struct ThreadStatus; - -public: - // Mark every thread as using the handle - it will be deleted - // below after every thread marks the handle as unused - static void markForDeletion(H* handle) { - allThreadsStatuses.addHandle(shared_ptr(handle)); - } - - // Mark this thread is not using any handle - - // handles get deleted here when no one else - // is using them either - static void markAllUnusedInThisThread() { - ThreadStatus* threadStatus = getThreadStatus(); - ScopedLock<Mutex> l(threadStatus->lock); - - // The actual deletions will happen here when all the shared_ptr - // ref counts hit 0 (that is when every thread marks the handle unused) - threadStatus->handles.clear(); - } - - static void destroyThreadState() { - ThreadStatus* threadStatus = getThreadStatus(); - allThreadsStatuses.delThreadStatus(threadStatus); - delete threadStatus; - threadStatus = 0; - } - -private: - - static ThreadStatus*& getThreadStatus() { - static __thread ThreadStatus* threadStatus = 0; - - // Thread local vars can't be dynamically constructed so we need - // to check whether we've made it yet and construct it if not - // (no locking necessary for the check as it's thread local!) - if (!threadStatus) { - threadStatus = new ThreadStatus; - allThreadsStatuses.addThreadStatus(threadStatus); - } - - return threadStatus; - } - - typedef boost::shared_ptr<H> shared_ptr; - - // In theory we know that we never need more handles than the number of - // threads runnning so we could use a fixed size array. However at this point - // in the code we don't have easy access to this information. - struct ThreadStatus - { - Mutex lock; - std::vector<shared_ptr> handles; - }; - - class AllThreadsStatuses - { - Mutex lock; - std::vector<ThreadStatus*> statuses; - - struct handleAdder - { - shared_ptr handle; - - handleAdder(shared_ptr h): handle(h) {} - - void operator()(ThreadStatus* ptr) { - ScopedLock<Mutex> l(ptr->lock); - ptr->handles.push_back(handle); - } - }; - - public: - // Need this to be able to do static initialisation - explicit AllThreadsStatuses(int) {} - - ~AllThreadsStatuses() { - ScopedLock<Mutex> l(lock); - std::for_each(statuses.begin(), statuses.end(), deleter()); - } - - void addThreadStatus(ThreadStatus* t) { - ScopedLock<Mutex> l(lock); - statuses.push_back(t); - } - - void delThreadStatus(ThreadStatus* t) { - ScopedLock<Mutex> l(lock); - typename std::vector<ThreadStatus*>::iterator it = - std::find(statuses.begin(),statuses.end(), t); - if (it != statuses.end()) { - statuses.erase(it); - } - } - - void addHandle(shared_ptr h) { - ScopedLock<Mutex> l(lock); - std::for_each(statuses.begin(), statuses.end(), handleAdder(h)); - } - }; - - static AllThreadsStatuses allThreadsStatuses; -}; - -}} -#endif // _sys_DeletionManager_h diff --git a/cpp/src/qpid/sys/DispatchHandle.cpp b/cpp/src/qpid/sys/DispatchHandle.cpp deleted file mode 100644 index 5d6fc4e72f..0000000000 --- a/cpp/src/qpid/sys/DispatchHandle.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/DispatchHandle.h" -#include "qpid/log/Statement.h" - -#include <algorithm> - -#include <boost/cast.hpp> - -#include <assert.h> - -namespace qpid { -namespace sys { - -DispatchHandle::DispatchHandle(const IOHandle& h, Callback rCb, Callback wCb, Callback dCb) : - PollerHandle(h), - readableCallback(rCb), - writableCallback(wCb), - disconnectedCallback(dCb), - state(IDLE) -{ -} - - -DispatchHandle::~DispatchHandle() { -} - -void DispatchHandle::startWatch(Poller::shared_ptr poller0) { - bool r = readableCallback; - bool w = writableCallback; - - ScopedLock<Mutex> lock(stateLock); - assert(state == IDLE); - - poller = poller0; - poller->registerHandle(*this); - state = WAITING; - Poller::Direction dir = r ? - ( w ? Poller::INOUT : Poller::INPUT ) : - ( w ? Poller::OUTPUT : Poller::NONE ); - poller->monitorHandle(*this, dir); -} - -void DispatchHandle::rewatch() { - bool r = readableCallback; - bool w = writableCallback; - if (!r && !w) { - return; - } - Poller::Direction dir = r ? - ( w ? Poller::INOUT : Poller::INPUT ) : - ( w ? Poller::OUTPUT : Poller::NONE ); - - ScopedLock<Mutex> lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->monitorHandle(*this, dir); -} - -void DispatchHandle::rewatchRead() { - if (!readableCallback) { - return; - } - - ScopedLock<Mutex> lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->monitorHandle(*this, Poller::INPUT); -} - -void DispatchHandle::rewatchWrite() { - if (!writableCallback) { - return; - } - - ScopedLock<Mutex> lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->monitorHandle(*this, Poller::OUTPUT); -} - -void DispatchHandle::unwatchRead() { - if (!readableCallback) { - return; - } - - ScopedLock<Mutex> lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->unmonitorHandle(*this, Poller::INPUT); -} - -void DispatchHandle::unwatchWrite() { - if (!writableCallback) { - return; - } - - ScopedLock<Mutex> lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->unmonitorHandle(*this, Poller::OUTPUT); -} - -void DispatchHandle::unwatch() { - ScopedLock<Mutex> lock(stateLock); - switch(state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - break; - } - assert(poller); - poller->unmonitorHandle(*this, Poller::INOUT); -} - -void DispatchHandle::stopWatch() { - ScopedLock<Mutex> lock(stateLock); - switch (state) { - case IDLE: - assert(state != IDLE); - return; - case STOPPING: - assert(state != STOPPING); - return; - case CALLING: - state = STOPPING; - break; - case WAITING: - state = IDLE; - break; - case DELETING: - return; - } - assert(poller); - poller->unregisterHandle(*this); - poller.reset(); -} - -// If we are in the IDLE/STOPPING state we can't do the callback as we've -// not/no longer got the fd registered in any poller -void DispatchHandle::call(Callback iCb) { - assert(iCb); - ScopedLock<Mutex> lock(stateLock); - switch (state) { - case IDLE: - case STOPPING: - case DELETING: - return; - default: - interruptedCallbacks.push(iCb); - assert(poller); - (void) poller->interrupt(*this); - } -} - -// The slightly strange switch structure -// is to ensure that the lock is released before -// we do the delete -void DispatchHandle::doDelete() { - { - ScopedLock<Mutex> lock(stateLock); - // Ensure that we're no longer watching anything - switch (state) { - case IDLE: - state = DELETING; - break; - case STOPPING: - state = DELETING; - return; - case WAITING: - state = DELETING; - assert(poller); - (void) poller->interrupt(*this); - poller->unregisterHandle(*this); - return; - case CALLING: - state = DELETING; - assert(poller); - poller->unregisterHandle(*this); - return; - case DELETING: - return; - } - } - // If we're IDLE we can do this right away - delete this; -} - -void DispatchHandle::processEvent(Poller::EventType type) { - - // Phase I - { - ScopedLock<Mutex> lock(stateLock); - - switch(state) { - case IDLE: - // Can get here if a non connection thread stops watching - // whilst we were stuck in the above lock - return; - case WAITING: - state = CALLING; - break; - case CALLING: - assert(state!=CALLING); - return; - case STOPPING: - assert(state!=STOPPING); - return; - case DELETING: - // Need to make sure we clean up any pending callbacks in this case - std::swap(callbacks, interruptedCallbacks); - goto saybyebye; - } - - std::swap(callbacks, interruptedCallbacks); - } - - // Do callbacks - whilst we are doing the callbacks we are prevented from processing - // the same handle until we re-enable it. To avoid rentering the callbacks for a single - // handle re-enabling in the callbacks is actually deferred until they are complete. - try { - switch (type) { - case Poller::READABLE: - readableCallback(*this); - break; - case Poller::WRITABLE: - writableCallback(*this); - break; - case Poller::READ_WRITABLE: - readableCallback(*this); - writableCallback(*this); - break; - case Poller::DISCONNECTED: - if (disconnectedCallback) { - disconnectedCallback(*this); - } - break; - case Poller::INTERRUPTED: - { - // We'll actually do the interrupt below - } - break; - default: - assert(false); - } - - // If we have any callbacks do them now - - // (because we use a copy from before the previous callbacks we won't - // do anything yet that was just added) - while (callbacks.size() > 0) { - { - ScopedLock<Mutex> lock(stateLock); - switch (state) { - case DELETING: - goto finishcallbacks; - default: - break; - } - } - Callback cb = callbacks.front(); - assert(cb); - cb(*this); - callbacks.pop(); - } - } catch (std::exception& e) { - // One of the callbacks threw an exception - that's not allowed - QPID_LOG(error, "Caught exception in state: " << state << " with event: " << type << ": " << e.what()); - // It would be nice to clean up and delete ourselves here, but we can't - } - -finishcallbacks: - { - ScopedLock<Mutex> lock(stateLock); - switch (state) { - case IDLE: - assert(state!=IDLE); - return; - case STOPPING: - state = IDLE; - return; - case WAITING: - assert(state!=WAITING); - return; - case CALLING: - state = WAITING; - return; - case DELETING: - break; - } - } - -saybyebye: - delete this; -} - -}} diff --git a/cpp/src/qpid/sys/DispatchHandle.h b/cpp/src/qpid/sys/DispatchHandle.h deleted file mode 100644 index 115a3c44f7..0000000000 --- a/cpp/src/qpid/sys/DispatchHandle.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef _sys_DispatchHandle_h -#define _sys_DispatchHandle_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Poller.h" -#include "qpid/sys/Mutex.h" -#include "qpid/CommonImportExport.h" -#include <boost/function.hpp> - -#include <queue> - -namespace qpid { -namespace sys { - -class DispatchHandleRef; -/** - * In order to have your own handle (file descriptor on Unix) watched by the poller - * you need to: - * - * - Subclass IOHandle, in the constructor supply an appropriate - * IOHandlerPrivate object for the platform. - * - * - Construct a DispatchHandle passing it your IOHandle and - * callback functions for read, write and disconnect events. - * - * - Ensure the DispatchHandle is not deleted until the poller is no longer using it. - * TODO: astitcher document DispatchHandleRef to simplify this. - * - * When an event occurs on the handle, the poller calls the relevant callback and - * stops watching that handle. Your callback can call rewatch() or related functions - * to re-enable polling. - */ -class DispatchHandle : public PollerHandle { - friend class DispatchHandleRef; -public: - typedef boost::function1<void, DispatchHandle&> Callback; - typedef std::queue<Callback> CallbackQueue; - -private: - Callback readableCallback; - Callback writableCallback; - Callback disconnectedCallback; - CallbackQueue interruptedCallbacks; - CallbackQueue callbacks; // Double buffer - Poller::shared_ptr poller; - Mutex stateLock; - enum { - IDLE, - STOPPING, - WAITING, - CALLING, - DELETING - } state; - -public: - /** - * Provide a handle to poll and a set of callbacks. Note - * callbacks can be 0, meaning you are not interested in that - * event. - * - *@param h: the handle to watch. The IOHandle encapsulates a - * platfrom-specific handle to an IO object (e.g. a file descriptor - * on Unix.) - *@param rCb Callback called when the handle is readable. - *@param wCb Callback called when the handle is writable. - *@param dCb Callback called when the handle is disconnected. - */ - QPID_COMMON_EXTERN DispatchHandle(const IOHandle& h, Callback rCb, Callback wCb, Callback dCb); - QPID_COMMON_EXTERN ~DispatchHandle(); - - /** Add this DispatchHandle to the poller to be watched. */ - QPID_COMMON_EXTERN void startWatch(Poller::shared_ptr poller); - - /** Resume watching for all non-0 callbacks. */ - QPID_COMMON_EXTERN void rewatch(); - /** Resume watching for read only. */ - QPID_COMMON_EXTERN void rewatchRead(); - - /** Resume watching for write only. */ - QPID_COMMON_EXTERN void rewatchWrite(); - - /** Stop watching temporarily. The DispatchHandle remains - associated with the poller and can be re-activated using - rewatch. */ - QPID_COMMON_EXTERN void unwatch(); - /** Stop watching for read */ - QPID_COMMON_EXTERN void unwatchRead(); - /** Stop watching for write */ - QPID_COMMON_EXTERN void unwatchWrite(); - - /** Stop watching permanently. Disassociates from the poller. */ - QPID_COMMON_EXTERN void stopWatch(); - - /** Interrupt watching this handle and make a serialised callback that respects the - * same exclusivity guarantees as the other callbacks - */ - QPID_COMMON_EXTERN void call(Callback iCb); - -protected: - QPID_COMMON_EXTERN void doDelete(); - -private: - QPID_COMMON_EXTERN void processEvent(Poller::EventType dir); -}; - -class DispatchHandleRef { - DispatchHandle* ref; - -public: - typedef boost::function1<void, DispatchHandle&> Callback; - DispatchHandleRef(const IOHandle& h, Callback rCb, Callback wCb, Callback dCb) : - ref(new DispatchHandle(h, rCb, wCb, dCb)) - {} - - ~DispatchHandleRef() { ref->doDelete(); } - - void startWatch(Poller::shared_ptr poller) { ref->startWatch(poller); } - void rewatch() { ref->rewatch(); } - void rewatchRead() { ref->rewatchRead(); } - void rewatchWrite() { ref->rewatchWrite(); } - void unwatch() { ref->unwatch(); } - void unwatchRead() { ref->unwatchRead(); } - void unwatchWrite() { ref->unwatchWrite(); } - void stopWatch() { ref->stopWatch(); } - void call(Callback iCb) { ref->call(iCb); } -}; - -}} - -#endif // _sys_DispatchHandle_h diff --git a/cpp/src/qpid/sys/Dispatcher.cpp b/cpp/src/qpid/sys/Dispatcher.cpp deleted file mode 100644 index 5f52dcd990..0000000000 --- a/cpp/src/qpid/sys/Dispatcher.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Dispatcher.h" - -#include <assert.h> - -namespace qpid { -namespace sys { - -Dispatcher::Dispatcher(Poller::shared_ptr poller0) : - poller(poller0) { -} - -Dispatcher::~Dispatcher() { -} - -void Dispatcher::run() { - poller->run(); -} - -}} diff --git a/cpp/src/qpid/sys/Dispatcher.h b/cpp/src/qpid/sys/Dispatcher.h deleted file mode 100644 index e8213d0579..0000000000 --- a/cpp/src/qpid/sys/Dispatcher.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _sys_Dispatcher_h -#define _sys_Dispatcher_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Poller.h" -#include "qpid/sys/Runnable.h" -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace sys { - -class Dispatcher : public Runnable { - const Poller::shared_ptr poller; - -public: - QPID_COMMON_EXTERN Dispatcher(Poller::shared_ptr poller); - QPID_COMMON_EXTERN ~Dispatcher(); - - QPID_COMMON_EXTERN void run(); -}; - -}} - -#endif // _sys_Dispatcher_h diff --git a/cpp/src/qpid/sys/FileSysDir.h b/cpp/src/qpid/sys/FileSysDir.h deleted file mode 100755 index ffe7823f0a..0000000000 --- a/cpp/src/qpid/sys/FileSysDir.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_SYS_FILESYSDIR_H -#define QPID_SYS_FILESYSDIR_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> - -namespace qpid { -namespace sys { - -/** - * @class FileSysDir - * - * Represents a filesystem directory accessible from the local host. - * This class simply checks existence of, and creates, a directory. It could - * be added to later to list contents, etc. - */ -class FileSysDir -{ - const std::string dirPath; - - public: - - FileSysDir (std::string path) : dirPath(path) {} - ~FileSysDir () {} - - /** - * Check to see if the directory exists and is a directory. Throws an - * exception if there is an error checking existence or if the path - * exists but is not a directory. - * - * @retval true if the path exists and is a directory. - * @retval false if the path does not exist. - */ - bool exists (void) const; - - void mkdir(void); - - std::string getPath () { return dirPath; } -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_FILESYSDIR_H*/ diff --git a/cpp/src/qpid/sys/Fork.h b/cpp/src/qpid/sys/Fork.h deleted file mode 100644 index 4ec061f7bc..0000000000 --- a/cpp/src/qpid/sys/Fork.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef QPID_SYS_FORK_H -#define QPID_SYS_FORK_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "posix/Fork.h" - -#endif /*!QPID_SYS_FORK_H*/ diff --git a/cpp/src/qpid/sys/LockFile.h b/cpp/src/qpid/sys/LockFile.h deleted file mode 100644 index 14a76cbf3e..0000000000 --- a/cpp/src/qpid/sys/LockFile.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _sys_LockFile_h -#define _sys_LockFile_h - -/* - * - * Copyright (c) 2008 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <string> - -#include "qpid/CommonImportExport.h" -#include "qpid/sys/IntegerTypes.h" - -namespace qpid { -namespace sys { - -class LockFilePrivate; - -/** - * @class LockFile - * - * LockFile represents a locked file suitable for a coarse-grain system - * lock. For example, the broker uses this to ensure that only one broker - * runs. A common usage idiom is to store the current "owner" process ID - * in the lock file - if the lock file exists, but the stored process ID - * doesn't, the old owner has probably died without cleaning up the lock - * file. - */ -class LockFile : private boost::noncopyable -{ - std::string path; - bool created; - boost::shared_ptr<LockFilePrivate> impl; - -protected: - int read(void*, size_t) const; - int write(void*, size_t) const; - -public: - QPID_COMMON_EXTERN LockFile(const std::string& path_, bool create); - QPID_COMMON_EXTERN ~LockFile(); -}; - -}} /* namespace qpid::sys */ - -#endif /*!_sys_LockFile_h*/ - - - diff --git a/cpp/src/qpid/sys/LockPtr.h b/cpp/src/qpid/sys/LockPtr.h deleted file mode 100644 index 738a864317..0000000000 --- a/cpp/src/qpid/sys/LockPtr.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef QPID_SYS_LOCKPTR_H -#define QPID_SYS_LOCKPTR_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Mutex.h" -#include <boost/noncopyable.hpp> - -namespace qpid { -namespace sys { - -class Mutex; - -/** - * LockPtr is a smart pointer to T. It is constructed from a volatile - * T* and a Lock (by default a Mutex). It const_casts away the - * volatile qualifier and locks the Lock for the duration of its - * - * Used in conjuntion with the "volatile" keyword to get the compiler - * to help enforce correct concurrent use of mutli-threaded objects. - * See ochttp://www.ddj.com/cpp/184403766 for a detailed discussion. - * - * To summarize the convention: - * - Declare thread-safe member functions as volatile. - * - Declare instances of the class that may be called concurrently as volatile. - * - Use LockPtr to cast away the volatile qualifier while taking a lock. - * - * This means that code calling on a concurrently-used object - * (declared volatile) can only call thread-safe (volatile) member - * functions. Code that needs to use thread-unsafe members must use a - * LockPtr, thereby acquiring the lock and making it safe to do so. - * - * A good type-safe pattern is the internally-locked object: - * - It has it's own private lock member. - * - All public functions are thread safe and declared volatile. - * - Any thread-unsafe, non-volatile functions are private. - * - Only member function implementations use LockPtr to access private functions. - * - * This encapsulates all the locking logic inside the class. - * - * One nice feature of this convention is the common case where you - * need a public, locked version of some function foo() and also a - * private unlocked version to avoid recursive locks. They can be declared as - * volatile and non-volatile overloads of the same function: - * - * // public - * void Thing::foo() volatile { LockPtr<Thing>(this, myLock)->foo(); } - * // private - * void Thing::foo() { ... do stuff ...} - */ - -template <class T, class Lock> class LockPtr : public boost::noncopyable { - public: - LockPtr(volatile T* p, Lock& l) : ptr(const_cast<T*>(p)), lock(l) { lock.lock(); } - LockPtr(volatile T* p, volatile Lock& l) : ptr(const_cast<T*>(p)), lock(const_cast<Lock&>(l)) { lock.lock(); } - ~LockPtr() { lock.unlock(); } - - T& operator*() { return *ptr; } - T* operator->() { return ptr; } - - private: - T* ptr; - Lock& lock; -}; - - -}} // namespace qpid::sys - - -#endif /*!QPID_SYS_LOCKPTR_H*/ diff --git a/cpp/src/qpid/sys/OutputControl.h b/cpp/src/qpid/sys/OutputControl.h deleted file mode 100644 index eae99beb0f..0000000000 --- a/cpp/src/qpid/sys/OutputControl.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" - -#ifndef _OutputControl_ -#define _OutputControl_ - -namespace qpid { -namespace sys { - - class OutputControl - { - public: - virtual ~OutputControl() {} - virtual void abort() = 0; - virtual void activateOutput() = 0; - virtual void giveReadCredit(int32_t credit) = 0; - }; - -} -} - - -#endif diff --git a/cpp/src/qpid/sys/OutputTask.h b/cpp/src/qpid/sys/OutputTask.h deleted file mode 100644 index fb08a63cd0..0000000000 --- a/cpp/src/qpid/sys/OutputTask.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _OutputTask_ -#define _OutputTask_ - -namespace qpid { -namespace sys { - - class OutputTask - { - public: - virtual ~OutputTask() {} - /** Generate some output. - *@return true if output was generated, false if there is no work to do. - */ - virtual bool doOutput() = 0; - }; - -} -} - - -#endif diff --git a/cpp/src/qpid/sys/PipeHandle.h b/cpp/src/qpid/sys/PipeHandle.h deleted file mode 100755 index 8aac76996b..0000000000 --- a/cpp/src/qpid/sys/PipeHandle.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _sys_PipeHandle_h -#define _sys_PipeHandle_h - -/* -* -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you under the Apache License, Version 2.0 (the -* "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, -* software distributed under the License is distributed on an -* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -* KIND, either express or implied. See the License for the -* specific language governing permissions and limitations -* under the License. -* -*/ - -#include "qpid/sys/IntegerTypes.h" -#include "qpid/CommonImportExport.h" -#include <string> - -// This class is a portability wrapper around pipe fds. -// It currently exists primarily and solely for the purpose of -// integration with single-threaded components that require QMF -// integration through a signalling fd. - -namespace qpid { -namespace sys { - - class PipeHandle { - private: - int writeFd; - int readFd; - public: - QPID_COMMON_EXTERN PipeHandle(bool nonBlocking=true); - QPID_COMMON_EXTERN ~PipeHandle(); - QPID_COMMON_EXTERN int read(void* buf, size_t bufSize); - QPID_COMMON_EXTERN int write(const void* buf, size_t bufSize); - QPID_COMMON_EXTERN int getReadHandle(); - }; - -}} - -#endif /*!_sys_PipeHandle_h*/ diff --git a/cpp/src/qpid/sys/PollableCondition.h b/cpp/src/qpid/sys/PollableCondition.h deleted file mode 100644 index 2eb6f2d947..0000000000 --- a/cpp/src/qpid/sys/PollableCondition.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef QPID_SYS_POLLABLECONDITION_H -#define QPID_SYS_POLLABLECONDITION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Poller.h" -#include "qpid/CommonImportExport.h" -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> - - -namespace qpid { -namespace sys { - -class PollableConditionPrivate; - -class PollableCondition { -public: - typedef boost::function1<void, PollableCondition&> Callback; - - QPID_COMMON_EXTERN PollableCondition(const Callback& cb, - const boost::shared_ptr<sys::Poller>& poller); - - QPID_COMMON_EXTERN ~PollableCondition(); - - /** - * Set the condition. Triggers callback to Callback from Poller. - */ - QPID_COMMON_EXTERN void set(); - - /** - * Clear the condition. Stops callbacks from Poller. - */ - QPID_COMMON_EXTERN void clear(); - - private: - PollableConditionPrivate *impl; - - Callback callback; - boost::shared_ptr<sys::Poller> poller; -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_POLLABLECONDITION_H*/ diff --git a/cpp/src/qpid/sys/PollableQueue.h b/cpp/src/qpid/sys/PollableQueue.h deleted file mode 100644 index 81c2301c1e..0000000000 --- a/cpp/src/qpid/sys/PollableQueue.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef QPID_SYS_POLLABLEQUEUE_H -#define QPID_SYS_POLLABLEQUEUE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/PollableCondition.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Thread.h" -#include <boost/function.hpp> -#include <boost/bind.hpp> -#include <algorithm> -#include <vector> - -namespace qpid { -namespace sys { - -class Poller; - -/** - * A queue whose item processing is dispatched by sys::Poller. - * Any thread can push to the queue; items pushed trigger an event the Poller - * recognizes. When a Poller I/O thread dispatches the event, a - * user-specified callback is invoked with all items on the queue. - */ -template <class T> -class PollableQueue { - public: - typedef std::vector<T> Batch; - typedef T value_type; - - /** - * Callback to process a batch of items from the queue. - * - * @param batch Queue of values to process. Any items remaining - * on return from Callback are put back on the queue. - * @return iterator pointing to the first un-processed item in batch. - * Items from this point up to batch.end() are put back on the queue. - */ - typedef boost::function<typename Batch::const_iterator (const Batch& batch)> Callback; - - /** - * Constructor; sets necessary parameters. - * - * @param cb Callback that will be called to process items on the - * queue. Will be called from a Poller I/O thread. - * @param poller Poller to use for dispatching queue events. - */ - PollableQueue(const Callback& cb, - const boost::shared_ptr<sys::Poller>& poller); - - ~PollableQueue(); - - /** Push a value onto the queue. Thread safe */ - void push(const T& t); - - /** Start polling. */ - void start(); - - /** Stop polling and wait for the current callback, if any, to complete. */ - void stop(); - - /** Are we currently stopped?*/ - bool isStopped() const { ScopedLock l(lock); return stopped; } - - size_t size() { ScopedLock l(lock); return queue.size(); } - bool empty() { ScopedLock l(lock); return queue.empty(); } - - /** - * Allow any queued events to be processed; intended for calling - * after all dispatch threads exit the Poller loop in order to - * ensure clean shutdown with no events left on the queue. - */ - void shutdown(); - - private: - typedef sys::Monitor::ScopedLock ScopedLock; - typedef sys::Monitor::ScopedUnlock ScopedUnlock; - - void dispatch(PollableCondition& cond); - void process(); - - mutable sys::Monitor lock; - Callback callback; - PollableCondition condition; - Batch queue, batch; - Thread dispatcher; - bool stopped; -}; - -template <class T> PollableQueue<T>::PollableQueue( - const Callback& cb, const boost::shared_ptr<sys::Poller>& p) - : callback(cb), - condition(boost::bind(&PollableQueue<T>::dispatch, this, _1), p), - stopped(true) -{ -} - -template <class T> void PollableQueue<T>::start() { - ScopedLock l(lock); - if (!stopped) return; - stopped = false; - if (!queue.empty()) condition.set(); -} - -template <class T> PollableQueue<T>::~PollableQueue() { -} - -template <class T> void PollableQueue<T>::push(const T& t) { - ScopedLock l(lock); - if (queue.empty() && !stopped) condition.set(); - queue.push_back(t); -} - -template <class T> void PollableQueue<T>::dispatch(PollableCondition& cond) { - ScopedLock l(lock); - assert(!dispatcher); - dispatcher = Thread::current(); - process(); - dispatcher = Thread(); - if (queue.empty()) cond.clear(); - if (stopped) lock.notifyAll(); -} - -template <class T> void PollableQueue<T>::process() { - // Called with lock held - while (!stopped && !queue.empty()) { - assert(batch.empty()); - batch.swap(queue); - typename Batch::const_iterator putBack; - { - ScopedUnlock u(lock); // Allow concurrent push to queue. - putBack = callback(batch); - } - // put back unprocessed items. - queue.insert(queue.begin(), putBack, typename Batch::const_iterator(batch.end())); - batch.clear(); - } -} - -template <class T> void PollableQueue<T>::shutdown() { - ScopedLock l(lock); - process(); -} - -template <class T> void PollableQueue<T>::stop() { - ScopedLock l(lock); - if (stopped) return; - condition.clear(); - stopped = true; - // Avoid deadlock if stop is called from the dispatch thread - if (dispatcher && dispatcher != Thread::current()) - while (dispatcher) lock.wait(); -} - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_POLLABLEQUEUE_H*/ diff --git a/cpp/src/qpid/sys/Poller.h b/cpp/src/qpid/sys/Poller.h deleted file mode 100644 index 01ee139ee6..0000000000 --- a/cpp/src/qpid/sys/Poller.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef _sys_Poller_h -#define _sys_Poller_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Time.h" -#include "qpid/sys/Runnable.h" -#include "qpid/CommonImportExport.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace sys { - -/** - * Poller is an abstract base class that registers callbacks to be - * called when there is IO activity. Concrete derived classes - * implement polling APIs such as epoll or equivalents on other - * operating systems. - * - * On the broker, Connection::received() is called with incoming - * frames from clients, and Connection::doOutput() is called when a - * connection is writeable. - * - * @see DispatchHandler for more details of normal use. - */ -class PollerHandle; -class PollerPrivate; -class Poller : public Runnable { - PollerPrivate* const impl; - -public: - typedef boost::shared_ptr<Poller> shared_ptr; - - enum Direction { - NONE = 0, - INPUT, - OUTPUT, - INOUT - }; - - enum EventType { - INVALID = 0, - READABLE, - WRITABLE, - READ_WRITABLE, - DISCONNECTED, - SHUTDOWN, - TIMEOUT, - INTERRUPTED - }; - - struct Event { - PollerHandle* handle; - EventType type; - - Event(PollerHandle* handle0, EventType type0) : - handle(handle0), - type(type0) { - } - - void process(); - }; - - QPID_COMMON_EXTERN Poller(); - QPID_COMMON_EXTERN ~Poller(); - /** Note: this function is async-signal safe */ - QPID_COMMON_EXTERN void shutdown(); - - // Interrupt waiting for a specific poller handle - // returns true if we could interrupt the handle - // - in this case on return the handle is no longer being monitored, - // but we will receive an event from some invocation of poller::wait - // with the handle and the INTERRUPTED event type - // if it returns false then the handle is not being monitored by the poller - // - This can either be because it has just received an event which has been - // reported and has not been reenabled since. - // - Because it was removed from the monitoring set - // - Or because it is already being interrupted - QPID_COMMON_EXTERN bool interrupt(PollerHandle& handle); - - // Poller run loop - QPID_COMMON_EXTERN void run(); - - QPID_COMMON_EXTERN void registerHandle(PollerHandle& handle); - QPID_COMMON_EXTERN void unregisterHandle(PollerHandle& handle); - QPID_COMMON_EXTERN void monitorHandle(PollerHandle& handle, Direction dir); - QPID_COMMON_EXTERN void unmonitorHandle(PollerHandle& handle, Direction dir); - QPID_COMMON_EXTERN Event wait(Duration timeout = TIME_INFINITE); - - QPID_COMMON_EXTERN bool hasShutdown(); -}; - -/** - * Handle class to use for polling - */ -class IOHandle; -class PollerHandlePrivate; -class PollerHandle { - friend class Poller; - friend class PollerPrivate; - friend struct Poller::Event; - - PollerHandlePrivate* const impl; - QPID_COMMON_INLINE_EXTERN virtual void processEvent(Poller::EventType) {}; - -public: - QPID_COMMON_EXTERN PollerHandle(const IOHandle& h); - QPID_COMMON_EXTERN virtual ~PollerHandle(); -}; - -inline void Poller::Event::process() { - handle->processEvent(type); -} - -}} -#endif // _sys_Poller_h diff --git a/cpp/src/qpid/sys/ProtocolFactory.h b/cpp/src/qpid/sys/ProtocolFactory.h deleted file mode 100644 index b233b2da1a..0000000000 --- a/cpp/src/qpid/sys/ProtocolFactory.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _sys_ProtocolFactory_h -#define _sys_ProtocolFactory_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" -#include "qpid/SharedObject.h" -#include "qpid/sys/ConnectionCodec.h" -#include <boost/function.hpp> - -namespace qpid { -namespace sys { - -class Poller; - -class ProtocolFactory : public qpid::SharedObject<ProtocolFactory> -{ - public: - typedef boost::function2<void, int, std::string> ConnectFailedCallback; - - virtual ~ProtocolFactory() = 0; - virtual uint16_t getPort() const = 0; - virtual std::string getHost() const = 0; - virtual void accept(boost::shared_ptr<Poller>, ConnectionCodec::Factory*) = 0; - virtual void connect( - boost::shared_ptr<Poller>, - const std::string& host, int16_t port, - ConnectionCodec::Factory* codec, - ConnectFailedCallback failed) = 0; - virtual bool supports(const std::string& /*capability*/) { return false; } -}; - -inline ProtocolFactory::~ProtocolFactory() {} - -}} - - - -#endif //!_sys_ProtocolFactory_h diff --git a/cpp/src/qpid/sys/RdmaIOPlugin.cpp b/cpp/src/qpid/sys/RdmaIOPlugin.cpp deleted file mode 100644 index d53db20598..0000000000 --- a/cpp/src/qpid/sys/RdmaIOPlugin.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ProtocolFactory.h" - -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/rdma/RdmaIO.h" -#include "qpid/sys/rdma/rdma_exception.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/sys/SecuritySettings.h" - -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> -#include <memory> - -#include <netdb.h> - -using std::auto_ptr; -using std::string; -using std::stringstream; - -namespace qpid { -namespace sys { - -class RdmaIOHandler : public OutputControl { - std::string identifier; - ConnectionCodec::Factory* factory; - ConnectionCodec* codec; - bool readError; - - sys::Mutex pollingLock; - bool polling; - - Rdma::AsynchIO* aio; - Rdma::Connection::intrusive_ptr connection; - - void write(const framing::ProtocolInitiation&); - void disconnectAction(); - - public: - RdmaIOHandler(Rdma::Connection::intrusive_ptr c, ConnectionCodec::Factory* f); - ~RdmaIOHandler(); - void init(Rdma::AsynchIO* a); - void start(Poller::shared_ptr poller); - - // Output side - void close(); - void abort(); - void activateOutput(); - void giveReadCredit(int32_t credit); - void initProtocolOut(); - - // Input side - void readbuff(Rdma::AsynchIO& aio, Rdma::Buffer* buff); - void initProtocolIn(Rdma::Buffer* buff); - - // Notifications - void full(Rdma::AsynchIO& aio); - void idle(Rdma::AsynchIO& aio); - void error(Rdma::AsynchIO& aio); - void disconnected(); - void drained(); -}; - -RdmaIOHandler::RdmaIOHandler(Rdma::Connection::intrusive_ptr c, qpid::sys::ConnectionCodec::Factory* f) : - identifier(c->getFullName()), - factory(f), - codec(0), - readError(false), - polling(false), - connection(c) -{ -} - -RdmaIOHandler::~RdmaIOHandler() { - if (codec) - codec->closed(); - delete codec; - delete aio; -} - -void RdmaIOHandler::init(Rdma::AsynchIO* a) { - aio = a; -} - -void RdmaIOHandler::start(Poller::shared_ptr poller) { - Mutex::ScopedLock l(pollingLock); - assert(!polling); - - polling = true; - - aio->start(poller); -} - -void RdmaIOHandler::write(const framing::ProtocolInitiation& data) -{ - QPID_LOG(debug, "Rdma: SENT [" << identifier << "] INIT(" << data << ")"); - Rdma::Buffer* buff = aio->getSendBuffer(); - assert(buff); - framing::Buffer out(buff->bytes(), buff->byteCount()); - data.encode(out); - buff->dataCount(data.encodedSize()); - aio->queueWrite(buff); -} - -void RdmaIOHandler::close() { - aio->drainWriteQueue(boost::bind(&RdmaIOHandler::drained, this)); -} - -// TODO: Dummy implementation, need to fill this in for heartbeat timeout to work -void RdmaIOHandler::abort() { -} - -void RdmaIOHandler::activateOutput() { - aio->notifyPendingWrite(); -} - -void RdmaIOHandler::idle(Rdma::AsynchIO&) { - // TODO: Shouldn't need this test as idle() should only ever be called when - // the connection is writable anyway - if ( !aio->writable() ) { - return; - } - if (codec == 0) return; - if (!codec->canEncode()) { - return; - } - Rdma::Buffer* buff = aio->getSendBuffer(); - if (buff) { - size_t encoded=codec->encode(buff->bytes(), buff->byteCount()); - buff->dataCount(encoded); - aio->queueWrite(buff); - if (codec->isClosed()) { - close(); - } - } -} - -void RdmaIOHandler::initProtocolOut() { - // We mustn't have already started the conversation - // but we must be able to send - assert( codec == 0 ); - assert( aio->writable() ); - codec = factory->create(*this, identifier, SecuritySettings()); - write(framing::ProtocolInitiation(codec->getVersion())); -} - -void RdmaIOHandler::error(Rdma::AsynchIO&) { - disconnected(); -} - -namespace { - void stopped(RdmaIOHandler* async) { - delete async; - } -} - -void RdmaIOHandler::disconnectAction() { - { - Mutex::ScopedLock l(pollingLock); - // If we're closed already then we'll get to drained() anyway - if (!polling) return; - polling = false; - } - aio->stop(boost::bind(&stopped, this)); -} - -void RdmaIOHandler::disconnected() { - aio->requestCallback(boost::bind(&RdmaIOHandler::disconnectAction, this)); -} - -void RdmaIOHandler::drained() { - // We know we've drained the write queue now, but we don't have to do anything - // because we can rely on the client to disconnect to trigger the connection - // cleanup. -} - -void RdmaIOHandler::full(Rdma::AsynchIO&) { - QPID_LOG(debug, "Rdma: buffer full [" << identifier << "]"); -} - -// TODO: Dummy implementation of read throttling -void RdmaIOHandler::giveReadCredit(int32_t) { -} - -// The logic here is subtly different from TCP as RDMA is message oriented -// so we define that an RDMA message is a frame - in this case there is no putting back -// of any message remainder - there shouldn't be any. And what we read here can't be -// smaller than a frame -void RdmaIOHandler::readbuff(Rdma::AsynchIO&, Rdma::Buffer* buff) { - if (readError) { - return; - } - size_t decoded = 0; - try { - if (codec) { - decoded = codec->decode(buff->bytes(), buff->dataCount()); - }else{ - // Need to start protocol processing - initProtocolIn(buff); - } - }catch(const std::exception& e){ - QPID_LOG(error, e.what()); - readError = true; - close(); - } -} - -void RdmaIOHandler::initProtocolIn(Rdma::Buffer* buff) { - framing::Buffer in(buff->bytes(), buff->dataCount()); - framing::ProtocolInitiation protocolInit; - size_t decoded = 0; - if (protocolInit.decode(in)) { - decoded = in.getPosition(); - QPID_LOG(debug, "Rdma: RECV [" << identifier << "] INIT(" << protocolInit << ")"); - - codec = factory->create(protocolInit.getVersion(), *this, identifier, SecuritySettings()); - - // If we failed to create the codec then we don't understand the offered protocol version - if (!codec) { - // send valid version header & close connection. - write(framing::ProtocolInitiation(framing::highestProtocolVersion)); - readError = true; - close(); - } - } -} - -class RdmaIOProtocolFactory : public ProtocolFactory { - auto_ptr<Rdma::Listener> listener; - const uint16_t listeningPort; - - public: - RdmaIOProtocolFactory(int16_t port, int backlog); - void accept(Poller::shared_ptr, ConnectionCodec::Factory*); - void connect(Poller::shared_ptr, const string& host, int16_t port, ConnectionCodec::Factory*, ConnectFailedCallback); - - uint16_t getPort() const; - string getHost() const; - - private: - bool request(Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectionCodec::Factory*); - void established(Poller::shared_ptr, Rdma::Connection::intrusive_ptr); - void connected(Poller::shared_ptr, Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectionCodec::Factory*); - void connectionError(Rdma::Connection::intrusive_ptr, Rdma::ErrorType); - void disconnected(Rdma::Connection::intrusive_ptr); - void rejected(Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectFailedCallback); -}; - -// Static instance to initialise plugin -static class RdmaIOPlugin : public Plugin { - void earlyInitialize(Target&) { - } - - void initialize(Target& target) { - // Check whether we actually have any rdma devices - if ( Rdma::deviceCount() == 0 ) { - QPID_LOG(info, "Rdma: Disabled: no rdma devices found"); - return; - } - - broker::Broker* broker = dynamic_cast<broker::Broker*>(&target); - // Only provide to a Broker - if (broker) { - const broker::Broker::Options& opts = broker->getOptions(); - ProtocolFactory::shared_ptr protocol(new RdmaIOProtocolFactory(opts.port, opts.connectionBacklog)); - QPID_LOG(notice, "Rdma: Listening on RDMA port " << protocol->getPort()); - broker->registerProtocolFactory("rdma", protocol); - } - } -} rdmaPlugin; - -RdmaIOProtocolFactory::RdmaIOProtocolFactory(int16_t port, int /*backlog*/) : - listeningPort(port) -{} - -void RdmaIOProtocolFactory::established(Poller::shared_ptr poller, Rdma::Connection::intrusive_ptr ci) { - RdmaIOHandler* async = ci->getContext<RdmaIOHandler>(); - async->start(poller); -} - -bool RdmaIOProtocolFactory::request(Rdma::Connection::intrusive_ptr ci, const Rdma::ConnectionParams& cp, - ConnectionCodec::Factory* f) { - try { - if (cp.rdmaProtocolVersion == 0) { - QPID_LOG(warning, "Rdma: connection from protocol version 0 client"); - } - RdmaIOHandler* async = new RdmaIOHandler(ci, f); - Rdma::AsynchIO* aio = - new Rdma::AsynchIO(ci->getQueuePair(), - cp.rdmaProtocolVersion, - cp.maxRecvBufferSize, cp.initialXmitCredit, Rdma::DEFAULT_WR_ENTRIES, - boost::bind(&RdmaIOHandler::readbuff, async, _1, _2), - boost::bind(&RdmaIOHandler::idle, async, _1), - 0, // boost::bind(&RdmaIOHandler::full, async, _1), - boost::bind(&RdmaIOHandler::error, async, _1)); - async->init(aio); - - // Record aio so we can get it back from a connection - ci->addContext(async); - return true; - } catch (const Rdma::Exception& e) { - QPID_LOG(error, "Rdma: Cannot accept new connection (Rdma exception): " << e.what()); - } catch (const std::exception& e) { - QPID_LOG(error, "Rdma: Cannot accept new connection (unknown exception): " << e.what()); - } - - // If we get here we caught an exception so reject connection - return false; -} - -void RdmaIOProtocolFactory::connectionError(Rdma::Connection::intrusive_ptr, Rdma::ErrorType) { -} - -void RdmaIOProtocolFactory::disconnected(Rdma::Connection::intrusive_ptr ci) { - // If we've got a connection already tear it down, otherwise ignore - RdmaIOHandler* async = ci->getContext<RdmaIOHandler>(); - if (async) { - // Make sure we don't disconnect more than once - ci->removeContext(); - async->disconnected(); - } -} - -uint16_t RdmaIOProtocolFactory::getPort() const { - return listeningPort; // Immutable no need for lock. -} - -string RdmaIOProtocolFactory::getHost() const { - //return listener.getSockname(); - return ""; -} - -void RdmaIOProtocolFactory::accept(Poller::shared_ptr poller, ConnectionCodec::Factory* fact) { - ::sockaddr_in sin; - - sin.sin_family = AF_INET; - sin.sin_port = htons(listeningPort); - sin.sin_addr.s_addr = INADDR_ANY; - - listener.reset( - new Rdma::Listener( - Rdma::ConnectionParams(65536, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(&RdmaIOProtocolFactory::established, this, poller, _1), - boost::bind(&RdmaIOProtocolFactory::connectionError, this, _1, _2), - boost::bind(&RdmaIOProtocolFactory::disconnected, this, _1), - boost::bind(&RdmaIOProtocolFactory::request, this, _1, _2, fact))); - - SocketAddress sa("",boost::lexical_cast<std::string>(listeningPort)); - listener->start(poller, sa); -} - -// Only used for outgoing connections (in federation) -void RdmaIOProtocolFactory::rejected(Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectFailedCallback failed) { - failed(-1, "Connection rejected"); -} - -// Do the same as connection request and established but mark a client too -void RdmaIOProtocolFactory::connected(Poller::shared_ptr poller, Rdma::Connection::intrusive_ptr ci, const Rdma::ConnectionParams& cp, - ConnectionCodec::Factory* f) { - (void) request(ci, cp, f); - established(poller, ci); - RdmaIOHandler* async = ci->getContext<RdmaIOHandler>(); - async->initProtocolOut(); -} - -void RdmaIOProtocolFactory::connect( - Poller::shared_ptr poller, - const std::string& host, int16_t port, - ConnectionCodec::Factory* f, - ConnectFailedCallback failed) -{ - Rdma::Connector* c = - new Rdma::Connector( - Rdma::ConnectionParams(8000, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(&RdmaIOProtocolFactory::connected, this, poller, _1, _2, f), - boost::bind(&RdmaIOProtocolFactory::connectionError, this, _1, _2), - boost::bind(&RdmaIOProtocolFactory::disconnected, this, _1), - boost::bind(&RdmaIOProtocolFactory::rejected, this, _1, _2, failed)); - - SocketAddress sa(host, boost::lexical_cast<std::string>(port)); - c->start(poller, sa); -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/Runnable.cpp b/cpp/src/qpid/sys/Runnable.cpp deleted file mode 100644 index 325d87c91b..0000000000 --- a/cpp/src/qpid/sys/Runnable.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/Runnable.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace sys { - -Runnable::~Runnable() {} - -Runnable::Functor Runnable::functor() -{ - return boost::bind(&Runnable::run, this); -} - -}} diff --git a/cpp/src/qpid/sys/ScopedIncrement.h b/cpp/src/qpid/sys/ScopedIncrement.h deleted file mode 100644 index 8645ab2484..0000000000 --- a/cpp/src/qpid/sys/ScopedIncrement.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _posix_ScopedIncrement_h -#define _posix_ScopedIncrement_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <boost/noncopyable.hpp> -#include <boost/function.hpp> - -namespace qpid { -namespace sys { - -/** - * Increment counter in constructor and decrement in destructor. - * Optionally call a function if the decremented counter value is 0. - * Note the function must not throw, it is called in the destructor. - */ -template <class T, class F=boost::function<void()> > -class ScopedIncrement : boost::noncopyable -{ - public: - ScopedIncrement(T& c, F f=0) - : count(c), callback(f) { ++count; } - ~ScopedIncrement() { if (--count == 0 && callback) callback(); } - - private: - T& count; - F callback; -}; - - -/** Decrement counter in constructor and increment in destructor. */ -template <class T> -class ScopedDecrement : boost::noncopyable -{ - public: - ScopedDecrement(T& c) : count(c) { value = --count; } - ~ScopedDecrement() { ++count; } - - /** Return the value after the decrement. */ - operator long() { return value; } - - private: - T& count; - long value; -}; - - -}} - - -#endif // _posix_ScopedIncrement_h diff --git a/cpp/src/qpid/sys/SecurityLayer.h b/cpp/src/qpid/sys/SecurityLayer.h deleted file mode 100644 index 52bc40e352..0000000000 --- a/cpp/src/qpid/sys/SecurityLayer.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_SYS_SECURITYLAYER_H -#define QPID_SYS_SECURITYLAYER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Codec.h" - -namespace qpid { -namespace sys { - -/** - * Defines interface to a SASL negotiated Security Layer (for - * encryption/integrity) - */ -class SecurityLayer : public Codec -{ - public: - virtual void init(Codec*) = 0; - virtual ~SecurityLayer() {} -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_SECURITYLAYER_H*/ diff --git a/cpp/src/qpid/sys/SecuritySettings.h b/cpp/src/qpid/sys/SecuritySettings.h deleted file mode 100644 index bfcd08fd0f..0000000000 --- a/cpp/src/qpid/sys/SecuritySettings.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef QPID_SYS_SECURITYSETTINGS_H -#define QPID_SYS_SECURITYSETTINGS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -namespace qpid { -namespace sys { - -/** - * Conveys security information from a given transport to the upper - * layers. - */ -struct SecuritySettings -{ - /** - * Security Strength Factor (SSF). Possible values are: - * - * @li 0 No security - * @li 1 Integrity checking only - * @li >1 Integrity and confidentiality with the number - * giving the encryption key length. - */ - unsigned int ssf; - /** - * An authorisation id - */ - std::string authid; - - /** - * Disables SASL mechanisms that are vulnerable to passive - * dictionary-based password attacks - */ - bool nodict; - - SecuritySettings() : ssf(0), nodict(false) {} -}; - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_SECURITYSETTINGS_H*/ diff --git a/cpp/src/qpid/sys/Semaphore.h b/cpp/src/qpid/sys/Semaphore.h deleted file mode 100644 index 9d70f89aeb..0000000000 --- a/cpp/src/qpid/sys/Semaphore.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef _sys_Semaphore_h -#define _sys_Semaphore_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/Monitor.h" - -namespace qpid { -namespace sys { - -class Semaphore -{ -public: - Semaphore(uint c = 1) : count(c) {} - - void lock() { acquire(); } - void unlock() { release(); } - bool trylock() { return tryAcquire(); } - - bool tryAcquire() - { - Monitor::ScopedLock l(monitor); - if (count) { - count--; - return true; - } else { - return false; - } - } - - void acquire() - { - Monitor::ScopedLock l(monitor); - while (count == 0) monitor.wait(); - count--; - } - - void release(uint n) - { - Monitor::ScopedLock l(monitor); - if (count==0) monitor.notifyAll(); - count+=n; - } - - void release() - { - release(1); - } - - void forceLock() - { - Monitor::ScopedLock l(monitor); - count = 0; - } - -private: - Monitor monitor; - uint count; -}; - -}} - -#endif /*!_sys_Semaphore_h*/ diff --git a/cpp/src/qpid/sys/Shlib.cpp b/cpp/src/qpid/sys/Shlib.cpp deleted file mode 100644 index 342d726876..0000000000 --- a/cpp/src/qpid/sys/Shlib.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Shlib.h" - -#include "qpid/log/Statement.h" - -namespace qpid { -namespace sys { - -AutoShlib::~AutoShlib() throw() { - try { - unload(); - } catch(const std::exception& e) { - QPID_LOG(error, "Unloading shared library: " << e.what()); - } -} - -// Note: Other functions are defined in apr/Shlib.cpp or posix/Shlib.cpp. - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/Shlib.h b/cpp/src/qpid/sys/Shlib.h deleted file mode 100644 index 7f66cfec14..0000000000 --- a/cpp/src/qpid/sys/Shlib.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef QPID_SYS_SHLIB_H -#define QPID_SYS_SHLIB_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/CommonImportExport.h" -#include <boost/noncopyable.hpp> -#include <iostream> - -namespace qpid { -namespace sys { - -/** Encapsulates a shared library handle. - *@see AutoShlib - */ -class Shlib { - public: - /** Load a shared library */ - Shlib(const char* libname) { load(libname); } - - /** Load a shared library */ - Shlib(const std::string& libname) { load(libname.c_str()); } - - /** Unload shared library. */ - QPID_COMMON_EXTERN void unload(); - - /** Look up symbol. */ - QPID_COMMON_EXTERN void* getSymbol(const char* symbol); - - /** Look up symbol in shared library, cast it to the desired - * pointer type, void* by default. - */ - template <class T> - T getSymbol(const char* symbol) { - // Double cast avoids warning about casting object to function pointer - return reinterpret_cast<T>(reinterpret_cast<intptr_t>( - this->getSymbol(symbol))); - } - - private: - void* handle; - QPID_COMMON_EXTERN void load(const char* libname); -}; - -/** A shared library handle that unloads the shlib in it's dtor */ -class AutoShlib : public Shlib { - public: - /** Load shared library */ - AutoShlib(const std::string& libname) : Shlib(libname) {} - /** Calls unload() */ - QPID_COMMON_EXTERN ~AutoShlib() throw(); -}; - - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_SHLIB_H*/ diff --git a/cpp/src/qpid/sys/ShutdownHandler.h b/cpp/src/qpid/sys/ShutdownHandler.h deleted file mode 100644 index 88baecb5b6..0000000000 --- a/cpp/src/qpid/sys/ShutdownHandler.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ShutdownHandler_ -#define _ShutdownHandler_ - -namespace qpid { -namespace sys { - - class ShutdownHandler - { - public: - virtual void shutdown() = 0; - virtual ~ShutdownHandler(){} - }; - -} -} - -#endif diff --git a/cpp/src/qpid/sys/Socket.h b/cpp/src/qpid/sys/Socket.h deleted file mode 100644 index b1cded1aa1..0000000000 --- a/cpp/src/qpid/sys/Socket.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef _sys_Socket_h -#define _sys_Socket_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/CommonImportExport.h" -#include <string> - -namespace qpid { -namespace sys { - -class Duration; -class SocketAddress; - -class QPID_COMMON_CLASS_EXTERN Socket : public IOHandle -{ -public: - /** Create a socket wrapper for descriptor. */ - QPID_COMMON_EXTERN Socket(); - - /** Set timeout for read and write */ - void setTimeout(const Duration& interval) const; - - /** Set socket non blocking */ - void setNonblocking() const; - - QPID_COMMON_EXTERN void setTcpNoDelay() const; - - QPID_COMMON_EXTERN void connect(const std::string& host, uint16_t port) const; - QPID_COMMON_EXTERN void connect(const SocketAddress&) const; - - QPID_COMMON_EXTERN void close() const; - - /** Bind to a port and start listening. - *@param port 0 means choose an available port. - *@param backlog maximum number of pending connections. - *@return The bound port. - */ - QPID_COMMON_EXTERN int listen(uint16_t port = 0, int backlog = 10) const; - QPID_COMMON_EXTERN int listen(const SocketAddress&, int backlog = 10) const; - - /** Returns the "socket name" ie the address bound to - * the near end of the socket - */ - QPID_COMMON_EXTERN std::string getSockname() const; - - /** Returns the "peer name" ie the address bound to - * the remote end of the socket - */ - std::string getPeername() const; - - /** - * Returns an address (host and port) for the remote end of the - * socket - */ - QPID_COMMON_EXTERN std::string getPeerAddress() const; - /** - * Returns an address (host and port) for the local end of the - * socket - */ - QPID_COMMON_EXTERN std::string getLocalAddress() const; - - /** - * Returns the full address of the connection: local and remote host and port. - */ - QPID_COMMON_INLINE_EXTERN std::string getFullAddress() const { return getLocalAddress()+"-"+getPeerAddress(); } - - QPID_COMMON_EXTERN uint16_t getLocalPort() const; - uint16_t getRemotePort() const; - - /** - * Returns the error code stored in the socket. This may be used - * to determine the result of a non-blocking connect. - */ - int getError() const; - - /** Accept a connection from a socket that is already listening - * and has an incoming connection - */ - QPID_COMMON_EXTERN Socket* accept() const; - - // TODO The following are raw operations, maybe they need better wrapping? - QPID_COMMON_EXTERN int read(void *buf, size_t count) const; - QPID_COMMON_EXTERN int write(const void *buf, size_t count) const; - -private: - /** Create socket */ - void createSocket(const SocketAddress&) const; - - Socket(IOHandlePrivate*); - mutable std::string connectname; - mutable bool nonblocking; - mutable bool nodelay; -}; - -}} -#endif /*!_sys_Socket_h*/ diff --git a/cpp/src/qpid/sys/SocketAddress.h b/cpp/src/qpid/sys/SocketAddress.h deleted file mode 100644 index 27b9642f2c..0000000000 --- a/cpp/src/qpid/sys/SocketAddress.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _sys_SocketAddress_h -#define _sys_SocketAddress_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" -#include "qpid/CommonImportExport.h" -#include <string> - -struct addrinfo; - -namespace qpid { -namespace sys { - -class SocketAddress { - friend const ::addrinfo& getAddrInfo(const SocketAddress&); - -public: - /** Create a SocketAddress from hostname and port*/ - QPID_COMMON_EXTERN SocketAddress(const std::string& host, const std::string& port); - QPID_COMMON_EXTERN SocketAddress(const SocketAddress&); - QPID_COMMON_EXTERN SocketAddress& operator=(const SocketAddress&); - QPID_COMMON_EXTERN ~SocketAddress(); - - std::string asString() const; - -private: - std::string host; - std::string port; - mutable ::addrinfo* addrInfo; -}; - -}} -#endif /*!_sys_SocketAddress_h*/ diff --git a/cpp/src/qpid/sys/SslPlugin.cpp b/cpp/src/qpid/sys/SslPlugin.cpp deleted file mode 100644 index 0ec051caab..0000000000 --- a/cpp/src/qpid/sys/SslPlugin.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ProtocolFactory.h" - -#include "qpid/Plugin.h" -#include "qpid/sys/ssl/check.h" -#include "qpid/sys/ssl/util.h" -#include "qpid/sys/ssl/SslHandler.h" -#include "qpid/sys/ssl/SslIo.h" -#include "qpid/sys/ssl/SslSocket.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" - -#include <boost/bind.hpp> -#include <memory> - - -namespace qpid { -namespace sys { - -struct SslServerOptions : ssl::SslOptions -{ - uint16_t port; - bool clientAuth; - bool nodict; - - SslServerOptions() : port(5671), - clientAuth(false), - nodict(false) - { - addOptions() - ("ssl-port", optValue(port, "PORT"), "Port on which to listen for SSL connections") - ("ssl-require-client-authentication", optValue(clientAuth), - "Forces clients to authenticate in order to establish an SSL connection") - ("ssl-sasl-no-dict", optValue(nodict), - "Disables SASL mechanisms that are vulnerable to passive dictionary-based password attacks"); - } -}; - -class SslProtocolFactory : public ProtocolFactory { - const bool tcpNoDelay; - qpid::sys::ssl::SslSocket listener; - const uint16_t listeningPort; - std::auto_ptr<qpid::sys::ssl::SslAcceptor> acceptor; - bool nodict; - - public: - SslProtocolFactory(const SslServerOptions&, int backlog, bool nodelay); - void accept(Poller::shared_ptr, ConnectionCodec::Factory*); - void connect(Poller::shared_ptr, const std::string& host, int16_t port, - ConnectionCodec::Factory*, - boost::function2<void, int, std::string> failed); - - uint16_t getPort() const; - std::string getHost() const; - bool supports(const std::string& capability); - - private: - void established(Poller::shared_ptr, const qpid::sys::ssl::SslSocket&, ConnectionCodec::Factory*, - bool isClient); -}; - -// Static instance to initialise plugin -static struct SslPlugin : public Plugin { - SslServerOptions options; - - Options* getOptions() { return &options; } - - ~SslPlugin() { ssl::shutdownNSS(); } - - void earlyInitialize(Target&) { - } - - void initialize(Target& target) { - broker::Broker* broker = dynamic_cast<broker::Broker*>(&target); - // Only provide to a Broker - if (broker) { - if (options.certDbPath.empty()) { - QPID_LOG(notice, "SSL plugin not enabled, you must set --ssl-cert-db to enable it."); - } else { - try { - ssl::initNSS(options, true); - - const broker::Broker::Options& opts = broker->getOptions(); - ProtocolFactory::shared_ptr protocol(new SslProtocolFactory(options, - opts.connectionBacklog, - opts.tcpNoDelay)); - QPID_LOG(notice, "Listening for SSL connections on TCP port " << protocol->getPort()); - broker->registerProtocolFactory("ssl", protocol); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL plugin: " << e.what()); - } - } - } - } -} sslPlugin; - -SslProtocolFactory::SslProtocolFactory(const SslServerOptions& options, int backlog, bool nodelay) : - tcpNoDelay(nodelay), listeningPort(listener.listen(options.port, backlog, options.certName, options.clientAuth)), - nodict(options.nodict) -{} - -void SslProtocolFactory::established(Poller::shared_ptr poller, const qpid::sys::ssl::SslSocket& s, - ConnectionCodec::Factory* f, bool isClient) { - qpid::sys::ssl::SslHandler* async = new qpid::sys::ssl::SslHandler(s.getFullAddress(), f, nodict); - - if (tcpNoDelay) { - s.setTcpNoDelay(tcpNoDelay); - QPID_LOG(info, "Set TCP_NODELAY on connection to " << s.getPeerAddress()); - } - - if (isClient) - async->setClient(); - qpid::sys::ssl::SslIO* aio = new qpid::sys::ssl::SslIO(s, - boost::bind(&qpid::sys::ssl::SslHandler::readbuff, async, _1, _2), - boost::bind(&qpid::sys::ssl::SslHandler::eof, async, _1), - boost::bind(&qpid::sys::ssl::SslHandler::disconnect, async, _1), - boost::bind(&qpid::sys::ssl::SslHandler::closedSocket, async, _1, _2), - boost::bind(&qpid::sys::ssl::SslHandler::nobuffs, async, _1), - boost::bind(&qpid::sys::ssl::SslHandler::idle, async, _1)); - - async->init(aio, 4); - aio->start(poller); -} - -uint16_t SslProtocolFactory::getPort() const { - return listeningPort; // Immutable no need for lock. -} - -std::string SslProtocolFactory::getHost() const { - return listener.getSockname(); -} - -void SslProtocolFactory::accept(Poller::shared_ptr poller, - ConnectionCodec::Factory* fact) { - acceptor.reset( - new qpid::sys::ssl::SslAcceptor(listener, - boost::bind(&SslProtocolFactory::established, this, poller, _1, fact, false))); - acceptor->start(poller); -} - -void SslProtocolFactory::connect( - Poller::shared_ptr poller, - const std::string& host, int16_t port, - ConnectionCodec::Factory* fact, - ConnectFailedCallback failed) -{ - // Note that the following logic does not cause a memory leak. - // The allocated Socket is freed either by the SslConnector - // upon connection failure or by the SslIoHandle upon connection - // shutdown. The allocated SslConnector frees itself when it - // is no longer needed. - - qpid::sys::ssl::SslSocket* socket = new qpid::sys::ssl::SslSocket(); - new qpid::sys::ssl::SslConnector (*socket, poller, host, port, - boost::bind(&SslProtocolFactory::established, this, poller, _1, fact, true), - failed); -} - -namespace -{ -const std::string SSL = "ssl"; -} - -bool SslProtocolFactory::supports(const std::string& capability) -{ - std::string s = capability; - transform(s.begin(), s.end(), s.begin(), tolower); - return s == SSL; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/StateMonitor.h b/cpp/src/qpid/sys/StateMonitor.h deleted file mode 100644 index eac37a8543..0000000000 --- a/cpp/src/qpid/sys/StateMonitor.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_SYS_STATEMONITOR_H -#define QPID_SYS_STATEMONITOR_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Waitable.h" - -#include <bitset> - -namespace qpid { -namespace sys { - -/** - * A monitor with an enum state value. - * - *@param Enum: enum type to use for states. - *@param EnumMax: Highest enum value. - */ -template <class Enum, size_t MaxEnum> -class StateMonitor : public Waitable -{ - public: - struct Set : public std::bitset<MaxEnum + 1> { - Set() {} - Set(Enum s) { set(s); } - Set(Enum s, Enum t) { std::bitset<MaxEnum + 1>::set(s).set(t); } - Set(Enum s, Enum t, Enum u) { std::bitset<MaxEnum + 1>::set(s).set(t).set(u); } - Set(Enum s, Enum t, Enum u, Enum v) { std::bitset<MaxEnum + 1>::set(s).set(t).set(u).set(v); } - }; - - - StateMonitor(Enum initial) { state=initial; } - - /** @pre Caller holds a ScopedLock. */ - void set(Enum s) { state=s; notifyAll(); } - /** @pre Caller holds a ScopedLock. */ - StateMonitor& operator=(Enum s) { set(s); return *this; } - - /** @pre Caller holds a ScopedLock. */ - Enum get() const { return state; } - /** @pre Caller holds a ScopedLock. */ - operator Enum() const { return state; } - - /** @pre Caller holds a ScopedLock */ - void waitFor(Enum s) { ScopedWait w(*this); while (s != state) wait(); } - /** @pre Caller holds a ScopedLock */ - void waitFor(Set s) { ScopedWait w(*this); while (!s.test(state)) wait(); } - /** @pre Caller holds a ScopedLock */ - void waitNot(Enum s) { ScopedWait w(*this); while (s == state) wait(); } - /** @pre Caller holds a ScopedLock */ - void waitNot(Set s) { ScopedWait w(*this); while (s.test(state)) wait(); } - - private: - Enum state; -}; - -}} - - -#endif /*!QPID_SYS_STATEMONITOR_H*/ diff --git a/cpp/src/qpid/sys/TCPIOPlugin.cpp b/cpp/src/qpid/sys/TCPIOPlugin.cpp deleted file mode 100644 index a6528f9ad9..0000000000 --- a/cpp/src/qpid/sys/TCPIOPlugin.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ProtocolFactory.h" -#include "qpid/sys/AsynchIOHandler.h" -#include "qpid/sys/AsynchIO.h" - -#include "qpid/Plugin.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/Poller.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" - -#include <boost/bind.hpp> -#include <memory> - -namespace qpid { -namespace sys { - -class AsynchIOProtocolFactory : public ProtocolFactory { - const bool tcpNoDelay; - Socket listener; - const uint16_t listeningPort; - std::auto_ptr<AsynchAcceptor> acceptor; - - public: - AsynchIOProtocolFactory(int16_t port, int backlog, bool nodelay); - void accept(Poller::shared_ptr, ConnectionCodec::Factory*); - void connect(Poller::shared_ptr, const std::string& host, int16_t port, - ConnectionCodec::Factory*, - ConnectFailedCallback); - - uint16_t getPort() const; - std::string getHost() const; - - private: - void established(Poller::shared_ptr, const Socket&, ConnectionCodec::Factory*, - bool isClient); - void connectFailed(const Socket&, int, const std::string&, ConnectFailedCallback); -}; - -// Static instance to initialise plugin -static class TCPIOPlugin : public Plugin { - void earlyInitialize(Target&) { - } - - void initialize(Target& target) { - broker::Broker* broker = dynamic_cast<broker::Broker*>(&target); - // Only provide to a Broker - if (broker) { - const broker::Broker::Options& opts = broker->getOptions(); - ProtocolFactory::shared_ptr protocol(new AsynchIOProtocolFactory(opts.port, opts.connectionBacklog, - opts.tcpNoDelay)); - QPID_LOG(notice, "Listening on TCP port " << protocol->getPort()); - broker->registerProtocolFactory("tcp", protocol); - } - } -} tcpPlugin; - -AsynchIOProtocolFactory::AsynchIOProtocolFactory(int16_t port, int backlog, bool nodelay) : - tcpNoDelay(nodelay), listeningPort(listener.listen(port, backlog)) -{} - -void AsynchIOProtocolFactory::established(Poller::shared_ptr poller, const Socket& s, - ConnectionCodec::Factory* f, bool isClient) { - AsynchIOHandler* async = new AsynchIOHandler(s.getFullAddress(), f); - - if (tcpNoDelay) { - s.setTcpNoDelay(); - QPID_LOG(info, "Set TCP_NODELAY on connection to " << s.getPeerAddress()); - } - - if (isClient) - async->setClient(); - AsynchIO* aio = AsynchIO::create - (s, - boost::bind(&AsynchIOHandler::readbuff, async, _1, _2), - boost::bind(&AsynchIOHandler::eof, async, _1), - boost::bind(&AsynchIOHandler::disconnect, async, _1), - boost::bind(&AsynchIOHandler::closedSocket, async, _1, _2), - boost::bind(&AsynchIOHandler::nobuffs, async, _1), - boost::bind(&AsynchIOHandler::idle, async, _1)); - - async->init(aio, 4); - aio->start(poller); -} - -uint16_t AsynchIOProtocolFactory::getPort() const { - return listeningPort; // Immutable no need for lock. -} - -std::string AsynchIOProtocolFactory::getHost() const { - return listener.getSockname(); -} - -void AsynchIOProtocolFactory::accept(Poller::shared_ptr poller, - ConnectionCodec::Factory* fact) { - acceptor.reset( - AsynchAcceptor::create(listener, - boost::bind(&AsynchIOProtocolFactory::established, this, poller, _1, fact, false))); - acceptor->start(poller); -} - -void AsynchIOProtocolFactory::connectFailed( - const Socket& s, int ec, const std::string& emsg, - ConnectFailedCallback failedCb) -{ - failedCb(ec, emsg); - s.close(); - delete &s; -} - -void AsynchIOProtocolFactory::connect( - Poller::shared_ptr poller, - const std::string& host, int16_t port, - ConnectionCodec::Factory* fact, - ConnectFailedCallback failed) -{ - // Note that the following logic does not cause a memory leak. - // The allocated Socket is freed either by the AsynchConnector - // upon connection failure or by the AsynchIO upon connection - // shutdown. The allocated AsynchConnector frees itself when it - // is no longer needed. - - Socket* socket = new Socket(); - AsynchConnector* c = AsynchConnector::create( - *socket, - host, - port, - boost::bind(&AsynchIOProtocolFactory::established, - this, poller, _1, fact, true), - boost::bind(&AsynchIOProtocolFactory::connectFailed, - this, _1, _2, _3, failed)); - c->start(poller); -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/TimeoutHandler.h b/cpp/src/qpid/sys/TimeoutHandler.h deleted file mode 100644 index 0c10709bbf..0000000000 --- a/cpp/src/qpid/sys/TimeoutHandler.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TimeoutHandler_ -#define _TimeoutHandler_ - -namespace qpid { -namespace sys { - - class TimeoutHandler - { - public: - virtual void idleOut() = 0; - virtual void idleIn() = 0; - virtual ~TimeoutHandler(){} - }; - -} -} - - -#endif diff --git a/cpp/src/qpid/sys/Timer.cpp b/cpp/src/qpid/sys/Timer.cpp deleted file mode 100644 index fdb2e8c6bb..0000000000 --- a/cpp/src/qpid/sys/Timer.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Timer.h" -#include "qpid/sys/Mutex.h" -#include "qpid/log/Statement.h" - -#include <numeric> - -using boost::intrusive_ptr; -using std::max; - -namespace qpid { -namespace sys { - -TimerTask::TimerTask(Duration timeout, const std::string& n) : - name(n), - sortTime(AbsTime::FarFuture()), - period(timeout), - nextFireTime(AbsTime::now(), timeout), - cancelled(false) -{} - -TimerTask::TimerTask(AbsTime time, const std::string& n) : - name(n), - sortTime(AbsTime::FarFuture()), - period(0), - nextFireTime(time), - cancelled(false) -{} - -TimerTask::~TimerTask() {} - -bool TimerTask::readyToFire() const { - return !(nextFireTime > AbsTime::now()); -} - -void TimerTask::fireTask() { - cancelled = true; - fire(); -} - -// This can only be used to setup the next fire time. After the Timer has already fired -void TimerTask::setupNextFire() { - if (period && readyToFire()) { - nextFireTime = max(AbsTime::now(), AbsTime(nextFireTime, period)); - cancelled = false; - } else { - QPID_LOG(error, name << " couldn't setup next timer firing: " << Duration(nextFireTime, AbsTime::now()) << "[" << period << "]"); - } -} - -// Only allow tasks to be delayed -void TimerTask::restart() { nextFireTime = max(nextFireTime, AbsTime(AbsTime::now(), period)); } - -void TimerTask::cancel() { - ScopedLock<Mutex> l(callbackLock); - cancelled = true; -} - -Timer::Timer() : - active(false), - late(50 * TIME_MSEC), - overran(2 * TIME_MSEC), - lateCancel(500 * TIME_MSEC), - warn(5 * TIME_SEC) -{ - start(); -} - -Timer::~Timer() -{ - stop(); -} - -// TODO AStitcher 21/08/09 The threshholds for emitting warnings are a little arbitrary -void Timer::run() -{ - Monitor::ScopedLock l(monitor); - while (active) { - if (tasks.empty()) { - monitor.wait(); - } else { - intrusive_ptr<TimerTask> t = tasks.top(); - tasks.pop(); - assert(!(t->nextFireTime < t->sortTime)); - - // warn on extreme lateness - AbsTime start(AbsTime::now()); - Duration delay(t->sortTime, start); - { - ScopedLock<Mutex> l(t->callbackLock); - if (t->cancelled) { - { - Monitor::ScopedUnlock u(monitor); - drop(t); - } - if (delay > lateCancel) { - QPID_LOG(debug, t->name << " cancelled timer woken up " << - delay / TIME_MSEC << "ms late"); - } - continue; - } else if(Duration(t->nextFireTime, start) >= 0) { - { - Monitor::ScopedUnlock u(monitor); - fire(t); - } - // Warn if callback overran next timer's start. - AbsTime end(AbsTime::now()); - Duration overrun (0); - if (!tasks.empty()) { - overrun = Duration(tasks.top()->nextFireTime, end); - } - bool warningsEnabled; - QPID_LOG_TEST(warning, warningsEnabled); - if (warningsEnabled) { - if (overrun > overran) { - if (delay > overran) // if delay is significant to an overrun. - warn.lateAndOverran(t->name, delay, overrun, Duration(start, end)); - else - warn.overran(t->name, overrun, Duration(start, end)); - } - else if (delay > late) - warn.late(t->name, delay); - } - continue; - } else { - // If the timer was adjusted into the future it might no longer - // be the next event, so push and then get top to make sure - // You can only push events into the future - t->sortTime = t->nextFireTime; - tasks.push(t); - } - } - assert(!tasks.empty()); - monitor.wait(tasks.top()->sortTime); - } - } -} - -void Timer::add(intrusive_ptr<TimerTask> task) -{ - Monitor::ScopedLock l(monitor); - task->sortTime = task->nextFireTime; - tasks.push(task); - monitor.notify(); -} - -void Timer::start() -{ - Monitor::ScopedLock l(monitor); - if (!active) { - active = true; - runner = Thread(this); - } -} - -void Timer::stop() -{ - { - Monitor::ScopedLock l(monitor); - if (!active) return; - active = false; - monitor.notifyAll(); - } - runner.join(); -} - -// Allow subclasses to override behavior when firing a task. -void Timer::fire(boost::intrusive_ptr<TimerTask> t) { - try { - t->fireTask(); - } catch (const std::exception& e) { - QPID_LOG(error, "Exception thrown by timer task " << t->getName() << ": " << e.what()); - } -} - -// Provided for subclasses: called when a task is droped. -void Timer::drop(boost::intrusive_ptr<TimerTask>) {} - -bool operator<(const intrusive_ptr<TimerTask>& a, - const intrusive_ptr<TimerTask>& b) -{ - // Lower priority if time is later - return a.get() && b.get() && a->sortTime > b->sortTime; -} - -}} diff --git a/cpp/src/qpid/sys/Timer.h b/cpp/src/qpid/sys/Timer.h deleted file mode 100644 index 98ba39ce38..0000000000 --- a/cpp/src/qpid/sys/Timer.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef sys_Timer -#define sys_Timer - -#include "qpid/sys/TimerWarnings.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/RefCounted.h" -#include "qpid/CommonImportExport.h" -#include <memory> -#include <queue> - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace sys { - -class Timer; - -class TimerTask : public RefCounted { - friend class Timer; - friend bool operator<(const boost::intrusive_ptr<TimerTask>&, - const boost::intrusive_ptr<TimerTask>&); - - std::string name; - AbsTime sortTime; - Duration period; - AbsTime nextFireTime; - Mutex callbackLock; - volatile bool cancelled; - - bool readyToFire() const; - void fireTask(); - - public: - QPID_COMMON_EXTERN TimerTask(Duration period, const std::string& name); - QPID_COMMON_EXTERN TimerTask(AbsTime fireTime, const std::string& name); - QPID_COMMON_EXTERN virtual ~TimerTask(); - - QPID_COMMON_EXTERN void setupNextFire(); - QPID_COMMON_EXTERN void restart(); - QPID_COMMON_EXTERN void cancel(); - - std::string getName() const { return name; } - - protected: - // Must be overridden with callback - virtual void fire() = 0; -}; - -// For the priority_queue order -bool operator<(const boost::intrusive_ptr<TimerTask>& a, - const boost::intrusive_ptr<TimerTask>& b); - -class Timer : private Runnable { - qpid::sys::Monitor monitor; - std::priority_queue<boost::intrusive_ptr<TimerTask> > tasks; - qpid::sys::Thread runner; - bool active; - - // Runnable interface - void run(); - - public: - QPID_COMMON_EXTERN Timer(); - QPID_COMMON_EXTERN virtual ~Timer(); - - QPID_COMMON_EXTERN virtual void add(boost::intrusive_ptr<TimerTask> task); - QPID_COMMON_EXTERN virtual void start(); - QPID_COMMON_EXTERN virtual void stop(); - - protected: - QPID_COMMON_EXTERN virtual void fire(boost::intrusive_ptr<TimerTask> task); - QPID_COMMON_EXTERN virtual void drop(boost::intrusive_ptr<TimerTask> task); - // Allow derived classes to change the late/overran thresholds. - Duration late; - Duration overran; - Duration lateCancel; - TimerWarnings warn; -}; - - -}} - - -#endif diff --git a/cpp/src/qpid/sys/TimerWarnings.cpp b/cpp/src/qpid/sys/TimerWarnings.cpp deleted file mode 100644 index 87c3169456..0000000000 --- a/cpp/src/qpid/sys/TimerWarnings.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "TimerWarnings.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace sys { - -TimerWarnings::TimerWarnings(Duration reportInterval) : - interval(reportInterval), - nextReport(now(), reportInterval) -{} - -void TimerWarnings::late(const std::string& task, Duration delay) { - taskStats[task].lateDelay.add(delay); - log(); -} - -void TimerWarnings::overran(const std::string& task, Duration overrun, Duration time) -{ - taskStats[task].overranOverrun.add(overrun); - taskStats[task].overranTime.add(time); - log(); -} - -void TimerWarnings::lateAndOverran( - const std::string& task, Duration delay, Duration overrun, Duration time) -{ - taskStats[task].lateAndOverranDelay.add(delay); - taskStats[task].lateAndOverranOverrun.add(overrun); - taskStats[task].lateAndOverranTime.add(time); - log(); -} - -void TimerWarnings::log() { - if (!taskStats.empty() && nextReport < now()) { - for (TaskStatsMap::iterator i = taskStats.begin(); i != taskStats.end(); ++i) { - std::string task = i->first; - TaskStats& stats = i->second; - if (stats.lateDelay.count) - QPID_LOG(warning, task << " task late " - << stats.lateDelay.count << " times by " - << stats.lateDelay.average()/TIME_MSEC << "ms on average."); - - if (stats.overranOverrun.count) - QPID_LOG(warning, task << " task overran " - << stats.overranOverrun.count << " times by " - << stats.overranOverrun.average()/TIME_MSEC << "ms (taking " - << stats.overranTime.average() << "ns) on average."); - - if (stats.lateAndOverranOverrun.count) - QPID_LOG(warning, task << " task late and overran " - << stats.lateAndOverranOverrun.count << " times: late " - << stats.lateAndOverranDelay.average()/TIME_MSEC << "ms, overran " - << stats.lateAndOverranOverrun.average()/TIME_MSEC << "ms (taking " - << stats.lateAndOverranTime.average() << "ns) on average."); - - } - nextReport = AbsTime(now(), interval); - taskStats.clear(); - } -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/TimerWarnings.h b/cpp/src/qpid/sys/TimerWarnings.h deleted file mode 100644 index 337a434ab5..0000000000 --- a/cpp/src/qpid/sys/TimerWarnings.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef QPID_SYS_TIMERWARNINGS_H -#define QPID_SYS_TIMERWARNINGS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Time.h" -#include <map> -#include <string> - -namespace qpid { -namespace sys { - -/** - * The Timer class logs warnings when timer tasks are late and/or overrun. - * - * It is too expensive to log a warning for every late/overrun - * incident, doing so aggravates the problem of tasks over-running and - * being late. - * - * This class collects statistical data about each incident and prints - * an aggregated report at regular intervals. - */ -class TimerWarnings -{ - public: - TimerWarnings(Duration reportInterval); - - void late(const std::string& task, Duration delay); - - void overran(const std::string& task, Duration overrun, Duration time); - - void lateAndOverran(const std::string& task, - Duration delay, Duration overrun, Duration time); - - private: - struct Statistic { - Statistic() : total(0), count(0) {} - void add(int64_t value) { total += value; ++count; } - int64_t average() const { return count ? total/count : 0; } - int64_t total; - int64_t count; - }; - - // Keep statistics for 3 classes of incident: late, overrun and both. - struct TaskStats { - Statistic lateDelay; // Just late - Statistic overranOverrun, overranTime; // Just overrun - // Both - Statistic lateAndOverranDelay, lateAndOverranOverrun, lateAndOverranTime; - }; - - typedef std::map<std::string, TaskStats> TaskStatsMap; - - void log(); - - Duration interval; - AbsTime nextReport; - TaskStatsMap taskStats; -}; -}} // namespace qpid::sys - -#endif /*!QPID_SYS_TIMERWARNINGS_H*/ diff --git a/cpp/src/qpid/sys/Waitable.h b/cpp/src/qpid/sys/Waitable.h deleted file mode 100644 index 8f6bd17049..0000000000 --- a/cpp/src/qpid/sys/Waitable.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef QPID_SYS_WAITABLE_H -#define QPID_SYS_WAITABLE_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Monitor.h" -#include "qpid/sys/ExceptionHolder.h" -#include <assert.h> - -namespace qpid { -namespace sys { - -/** - * A monitor that keeps track of waiting threads. Threads declare a - * ScopedWait around wait() inside a ScopedLock to be considered - * waiters. - * - * Allows waiting threads to be interrupted by an exception. - */ -class Waitable : public Monitor { - public: - Waitable() : waiters(0) {} - - ~Waitable() { assert(waiters == 0); } - - /** Use this inside a scoped lock around the - * call to wait() to be counted as a waiter. - */ - struct ScopedWait { - Waitable& w; - ScopedWait(Waitable& w_) : w(w_) { ++w.waiters; } - ~ScopedWait() { if (--w.waiters==0) w.notifyAll(); } - }; - - /** Block till there are no more waiters in ScopedWaits. - * waitWaiters() does not raise an exception even if waiters - * were interrupted by one. - *@pre Must be called inside a ScopedLock but NOT a ScopedWait. - */ - void waitWaiters() { - while (waiters != 0) - Monitor::wait(); - } - - /** Returns the number of outstanding ScopedWaits. - * Must be called with the lock held. - */ - size_t hasWaiters() const { - return waiters; - } - - /** Set an execption to interrupt waiters in ScopedWait. - * Must be called with the lock held. - */ - void setException(const ExceptionHolder& e) { - exception = e; - notifyAll(); - - } - - /** True if the waitable has an exception */ - bool hasException() const { return exception; } - - /** Throws if the waitable has an exception */ - void checkException() const { exception.raise(); } - - /** Clear the exception if any */ - void resetException() { exception.reset(); } - - /** Throws an exception if one is set before or during the wait. */ - void wait() { - ExCheck e(exception); - Monitor::wait(); - } - - /** Throws an exception if one is set before or during the wait. */ - bool wait(const AbsTime& absoluteTime) { - ExCheck e(exception); - return Monitor::wait(absoluteTime); - } - - private: - struct ExCheck { - const ExceptionHolder& exception; - ExCheck(const ExceptionHolder& e) : exception(e) { e.raise(); } - ~ExCheck() { exception.raise(); } - }; - - size_t waiters; - ExceptionHolder exception; - - friend struct ScopedWait; -}; - -}} // namespace qpid::sys - - - -#endif /*!QPID_SYS_WAITABLE_H*/ diff --git a/cpp/src/qpid/sys/alloca.h b/cpp/src/qpid/sys/alloca.h deleted file mode 100644 index 0f58920908..0000000000 --- a/cpp/src/qpid/sys/alloca.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_SYS_ALLOCA_H -#define QPID_SYS_ALLOCA_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#if (defined(_WINDOWS) || defined (WIN32)) -# include <malloc.h> - -# if defined(_MSC_VER) -# ifdef alloc -# undef alloc -# endif -# define alloc _alloc -# ifdef alloca -# undef alloca -# endif -# define alloca _alloca -# endif -# if !defined _WINDOWS && !defined WIN32 -# include <alloca.h> -# endif -#endif - -#endif /*!QPID_SYS_ALLOCA_H*/ diff --git a/cpp/src/qpid/sys/apr/APRBase.cpp b/cpp/src/qpid/sys/apr/APRBase.cpp deleted file mode 100644 index 8bdba66bdc..0000000000 --- a/cpp/src/qpid/sys/apr/APRBase.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/log/Statement.h" -#include "qpid/sys/apr/APRBase.h" - -using namespace qpid::sys; - -APRBase* APRBase::instance = 0; - -APRBase* APRBase::getInstance(){ - if(instance == 0){ - instance = new APRBase(); - } - return instance; -} - - -APRBase::APRBase() : count(0){ - apr_initialize(); - CHECK_APR_SUCCESS(apr_pool_create(&pool, 0)); - CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, pool)); -} - -APRBase::~APRBase(){ - CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); - apr_pool_destroy(pool); - apr_terminate(); -} - -bool APRBase::_increment(){ - bool deleted(false); - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); - if(this == instance){ - count++; - }else{ - deleted = true; - } - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); - return !deleted; -} - -void APRBase::_decrement(){ - APRBase* copy = 0; - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); - if(--count == 0){ - copy = instance; - instance = 0; - } - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); - if(copy != 0){ - delete copy; - } -} - -void APRBase::increment(){ - int count = 0; - while(count++ < 2 && !getInstance()->_increment()) - QPID_LOG(warning, "APR initialization triggered concurrently with termination."); -} - -void APRBase::decrement(){ - getInstance()->_decrement(); -} - -std::string qpid::sys::get_desc(apr_status_t status){ - const int size = 50; - char tmp[size]; - return std::string(apr_strerror(status, tmp, size)); -} - diff --git a/cpp/src/qpid/sys/apr/APRBase.h b/cpp/src/qpid/sys/apr/APRBase.h deleted file mode 100644 index 7b5644a129..0000000000 --- a/cpp/src/qpid/sys/apr/APRBase.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _APRBase_ -#define _APRBase_ - -#include <string> -#include <apr_thread_mutex.h> -#include <apr_errno.h> - -namespace qpid { -namespace sys { - - /** - * Use of APR libraries necessitates explicit init and terminate - * calls. Any class using APR libs should obtain the reference to - * this singleton and increment on construction, decrement on - * destruction. This class can then correctly initialise apr - * before the first use and terminate after the last use. - */ - class APRBase{ - static APRBase* instance; - apr_pool_t* pool; - apr_thread_mutex_t* mutex; - int count; - - APRBase(); - ~APRBase(); - static APRBase* getInstance(); - bool _increment(); - void _decrement(); - public: - static void increment(); - static void decrement(); - }; - - //this is also a convenient place for a helper function for error checking: - void check(apr_status_t status, const char* file, const int line); - std::string get_desc(apr_status_t status); - -#define CHECK_APR_SUCCESS(A) qpid::sys::check(A, __FILE__, __LINE__); - -} -} - -// Inlined as it is called *a lot* -void inline qpid::sys::check(apr_status_t status, const char* file, const int line){ - if (status != APR_SUCCESS){ - char tmp[256]; - throw Exception(QPID_MSG(apr_strerror(status, tmp, size))) - } -} - - - - -#endif diff --git a/cpp/src/qpid/sys/apr/APRPool.cpp b/cpp/src/qpid/sys/apr/APRPool.cpp deleted file mode 100644 index e221bfc2f1..0000000000 --- a/cpp/src/qpid/sys/apr/APRPool.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/apr/APRPool.h" -#include "qpid/sys/apr/APRBase.h" -#include <boost/pool/detail/singleton.hpp> - -using namespace qpid::sys; - -APRPool::APRPool(){ - APRBase::increment(); - CHECK_APR_SUCCESS(apr_pool_create(&pool, NULL)); -} - -APRPool::~APRPool(){ - apr_pool_destroy(pool); - APRBase::decrement(); -} - -apr_pool_t* APRPool::get() { - return boost::details::pool::singleton_default<APRPool>::instance().pool; -} - diff --git a/cpp/src/qpid/sys/apr/APRPool.h b/cpp/src/qpid/sys/apr/APRPool.h deleted file mode 100644 index da7661fcfa..0000000000 --- a/cpp/src/qpid/sys/apr/APRPool.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _APRPool_ -#define _APRPool_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <boost/noncopyable.hpp> -#include <apr_pools.h> - -namespace qpid { -namespace sys { -/** - * Singleton APR memory pool. - */ -class APRPool : private boost::noncopyable { - public: - APRPool(); - ~APRPool(); - - /** Get singleton instance */ - static apr_pool_t* get(); - - private: - apr_pool_t* pool; -}; - -}} - - - - - -#endif /*!_APRPool_*/ diff --git a/cpp/src/qpid/sys/apr/Condition.h b/cpp/src/qpid/sys/apr/Condition.h deleted file mode 100644 index 66d465ca75..0000000000 --- a/cpp/src/qpid/sys/apr/Condition.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _sys_apr_Condition_h -#define _sys_apr_Condition_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/apr/APRPool.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Time.h" - -#include <sys/errno.h> -#include <boost/noncopyable.hpp> -#include <apr_thread_cond.h> - -namespace qpid { -namespace sys { - -/** - * A condition variable for thread synchronization. - */ -class Condition -{ - public: - inline Condition(); - inline ~Condition(); - inline void wait(Mutex&); - inline bool wait(Mutex&, const AbsTime& absoluteTime); - inline void notify(); - inline void notifyAll(); - - private: - apr_thread_cond_t* condition; -}; - - -Condition::Condition() { - CHECK_APR_SUCCESS(apr_thread_cond_create(&condition, APRPool::get())); -} - -Condition::~Condition() { - CHECK_APR_SUCCESS(apr_thread_cond_destroy(condition)); -} - -void Condition::wait(Mutex& mutex) { - CHECK_APR_SUCCESS(apr_thread_cond_wait(condition, mutex.mutex)); -} - -bool Condition::wait(Mutex& mutex, const AbsTime& absoluteTime){ - // APR uses microseconds. - apr_status_t status = - apr_thread_cond_timedwait( - condition, mutex.mutex, Duration(now(), absoluteTime)/TIME_USEC); - if(status != APR_TIMEUP) CHECK_APR_SUCCESS(status); - return status == 0; -} - -void Condition::notify(){ - CHECK_APR_SUCCESS(apr_thread_cond_signal(condition)); -} - -void Condition::notifyAll(){ - CHECK_APR_SUCCESS(apr_thread_cond_broadcast(condition)); -} - -}} -#endif /*!_sys_apr_Condition_h*/ diff --git a/cpp/src/qpid/sys/apr/Mutex.h b/cpp/src/qpid/sys/apr/Mutex.h deleted file mode 100644 index cb75f5b339..0000000000 --- a/cpp/src/qpid/sys/apr/Mutex.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef _sys_apr_Mutex_h -#define _sys_apr_Mutex_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/apr/APRBase.h" -#include "qpid/sys/apr/APRPool.h" - -#include <boost/noncopyable.hpp> -#include <apr_thread_mutex.h> - -namespace qpid { -namespace sys { - -class Condition; - -/** - * Mutex lock. - */ -class Mutex : private boost::noncopyable { - public: - typedef ScopedLock<Mutex> ScopedLock; - typedef ScopedUnlock<Mutex> ScopedUnlock; - - inline Mutex(); - inline ~Mutex(); - inline void lock(); - inline void unlock(); - inline bool trylock(); - - protected: - apr_thread_mutex_t* mutex; - friend class Condition; -}; - -Mutex::Mutex() { - CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, APRPool::get())); -} - -Mutex::~Mutex(){ - CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); -} - -void Mutex::lock() { - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); -} -void Mutex::unlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); -} - -bool Mutex::trylock() { - return apr_thread_mutex_trylock(mutex) == 0; -} - - -/** - * RW lock. - */ -class RWlock : private boost::noncopyable { - friend class Condition; - -public: - typedef ScopedRlock<RWlock> ScopedRlock; - typedef ScopedWlock<RWlock> ScopedWlock; - - inline RWlock(); - inline ~RWlock(); - inline void wlock(); // will write-lock - inline void rlock(); // will read-lock - inline void unlock(); - inline bool trywlock(); // will write-try - inline bool tryrlock(); // will read-try - - protected: - apr_thread_mutex_t* mutex; -}; - -RWlock::RWlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_NESTED, APRPool::get())); -} - -RWlock::~RWlock(){ - CHECK_APR_SUCCESS(apr_thread_mutex_destroy(mutex)); -} - -void RWlock::wlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); -} - -void RWlock::rlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_lock(mutex)); -} - -void RWlock::unlock() { - CHECK_APR_SUCCESS(apr_thread_mutex_unlock(mutex)); -} - -bool RWlock::trywlock() { - return apr_thread_mutex_trylock(mutex) == 0; -} - -bool RWlock::tryrlock() { - return apr_thread_mutex_trylock(mutex) == 0; -} - - -}} -#endif /*!_sys_apr_Mutex_h*/ diff --git a/cpp/src/qpid/sys/apr/Shlib.cpp b/cpp/src/qpid/sys/apr/Shlib.cpp deleted file mode 100644 index b7ee13a03b..0000000000 --- a/cpp/src/qpid/sys/apr/Shlib.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Shlib.h" -#include "qpid/sys/apr/APRBase.h" -#include "qpid/sys/apr/APRPool.h" -#include <apr_dso.h> - -namespace qpid { -namespace sys { - -void Shlib::load(const char* libname) { - apr_dso_handle_t* aprHandle; - CHECK_APR_SUCCESS( - apr_dso_load(&aprHandle, libname, APRPool::get())); - handle=aprHandle; -} - -void Shlib::unload() { - CHECK_APR_SUCCESS( - apr_dso_unload(static_cast<apr_dso_handle_t*>(handle))); -} - -void* Shlib::getSymbol(const char* name) { - apr_dso_handle_sym_t symbol; - CHECK_APR_SUCCESS(apr_dso_sym(&symbol, - static_cast<apr_dso_handle_t*>(handle), - name)); - return (void*) symbol; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/apr/Socket.cpp b/cpp/src/qpid/sys/apr/Socket.cpp deleted file mode 100644 index d9024d11c1..0000000000 --- a/cpp/src/qpid/sys/apr/Socket.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -#include "qpid/sys/Socket.h" - -#include "qpid/sys/apr/APRBase.h" -#include "qpid/sys/apr/APRPool.h" - -#include <apr_network_io.h> - -namespace qpid { -namespace sys { - -class SocketPrivate { -public: - SocketPrivate(apr_socket_t* s = 0) : - socket(s) - {} - - apr_socket_t* socket; -}; - -Socket::Socket() : - impl(new SocketPrivate) -{ - createTcp(); -} - -Socket::Socket(SocketPrivate* sp) : - impl(sp) -{} - -Socket::~Socket() { - delete impl; -} - -void Socket::createTcp() const { - apr_socket_t*& socket = impl->socket; - apr_socket_t* s; - CHECK_APR_SUCCESS( - apr_socket_create( - &s, APR_INET, SOCK_STREAM, APR_PROTO_TCP, - APRPool::get())); - socket = s; -} - -void Socket::setTimeout(const Duration& interval) const { - apr_socket_t*& socket = impl->socket; - apr_socket_timeout_set(socket, interval/TIME_USEC); -} - -void Socket::connect(const std::string& host, int port) const { - apr_socket_t*& socket = impl->socket; - apr_sockaddr_t* address; - CHECK_APR_SUCCESS( - apr_sockaddr_info_get( - &address, host.c_str(), APR_UNSPEC, port, APR_IPV4_ADDR_OK, - APRPool::get())); - CHECK_APR_SUCCESS(apr_socket_connect(socket, address)); -} - -void Socket::close() const { - apr_socket_t*& socket = impl->socket; - if (socket == 0) return; - CHECK_APR_SUCCESS(apr_socket_close(socket)); - socket = 0; -} - -ssize_t Socket::send(const void* data, size_t size) const -{ - apr_socket_t*& socket = impl->socket; - apr_size_t sent = size; - apr_status_t status = - apr_socket_send(socket, reinterpret_cast<const char*>(data), &sent); - if (APR_STATUS_IS_TIMEUP(status)) return SOCKET_TIMEOUT; - if (APR_STATUS_IS_EOF(status)) return SOCKET_EOF; - CHECK_APR_SUCCESS(status); - return sent; -} - -ssize_t Socket::recv(void* data, size_t size) const -{ - apr_socket_t*& socket = impl->socket; - apr_size_t received = size; - apr_status_t status = - apr_socket_recv(socket, reinterpret_cast<char*>(data), &received); - if (APR_STATUS_IS_TIMEUP(status)) - return SOCKET_TIMEOUT; - if (APR_STATUS_IS_EOF(status)) - return SOCKET_EOF; - CHECK_APR_SUCCESS(status); - return received; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/apr/Thread.cpp b/cpp/src/qpid/sys/apr/Thread.cpp deleted file mode 100644 index b52d0e6ace..0000000000 --- a/cpp/src/qpid/sys/apr/Thread.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/apr/Thread.h" -#include "qpid/sys/Runnable.h" - -using namespace qpid::sys; -using qpid::sys::Runnable; - -void* APR_THREAD_FUNC Thread::runRunnable(apr_thread_t* thread, void *data) { - reinterpret_cast<Runnable*>(data)->run(); - CHECK_APR_SUCCESS(apr_thread_exit(thread, APR_SUCCESS)); - return NULL; -} - - diff --git a/cpp/src/qpid/sys/apr/Thread.h b/cpp/src/qpid/sys/apr/Thread.h deleted file mode 100644 index 6cc63db5c9..0000000000 --- a/cpp/src/qpid/sys/apr/Thread.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef _sys_apr_Thread_h -#define _sys_apr_Thread_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/apr/APRPool.h" -#include "qpid/sys/apr/APRBase.h" - -#include <apr_thread_proc.h> -#include <apr_portable.h> - -namespace qpid { -namespace sys { - -class Runnable; - -class Thread -{ - public: - inline static Thread current(); - - /** ID of current thread for logging. - * Workaround for broken Thread::current() in APR - */ - inline static long logId(); - - inline static void yield(); - - inline Thread(); - inline explicit Thread(qpid::sys::Runnable*); - inline explicit Thread(qpid::sys::Runnable&); - - inline void join(); - - inline long id(); - - private: - static void* APR_THREAD_FUNC runRunnable(apr_thread_t* thread, void *data); - inline Thread(apr_thread_t* t); - apr_thread_t* thread; -}; - -Thread::Thread() : thread(0) {} - -Thread::Thread(Runnable* runnable) { - CHECK_APR_SUCCESS( - apr_thread_create(&thread, 0, runRunnable, runnable, APRPool::get())); -} - -Thread::Thread(Runnable& runnable) { - CHECK_APR_SUCCESS( - apr_thread_create(&thread, 0, runRunnable, &runnable, APRPool::get())); -} - -void Thread::join(){ - apr_status_t status; - if (thread != 0) - CHECK_APR_SUCCESS(apr_thread_join(&status, thread)); -} - -long Thread::id() { - return long(thread); -} - -/** ID of current thread for logging. - * Workaround for broken Thread::current() in APR - */ -long Thread::logId() { - return static_cast<long>(apr_os_thread_current()); -} - -Thread::Thread(apr_thread_t* t) : thread(t) {} - -Thread Thread::current(){ - apr_thread_t* thr; - apr_os_thread_t osthr = apr_os_thread_current(); - CHECK_APR_SUCCESS(apr_os_thread_put(&thr, &osthr, APRPool::get())); - return Thread(thr); -} - -void Thread::yield() -{ - apr_thread_yield(); -} - -}} -#endif /*!_sys_apr_Thread_h*/ diff --git a/cpp/src/qpid/sys/apr/Time.cpp b/cpp/src/qpid/sys/apr/Time.cpp deleted file mode 100644 index 34e740b144..0000000000 --- a/cpp/src/qpid/sys/apr/Time.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Time.h" - -#include <apr_time.h> - -namespace qpid { -namespace sys { - -AbsTime AbsTime::now() { - AbsTime time_now; - time_now.time_ns = apr_time_now() * TIME_USEC; - return time_now; -} - -}} - diff --git a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp deleted file mode 100644 index 3d868da64b..0000000000 --- a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/cyrus/CyrusSecurityLayer.h" -#include <algorithm> -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include <string.h> - -namespace qpid { -namespace sys { -namespace cyrus { - -CyrusSecurityLayer::CyrusSecurityLayer(sasl_conn_t* c, uint16_t maxFrameSize) : - conn(c), decrypted(0), decryptedSize(0), encrypted(0), encryptedSize(0), codec(0), maxInputSize(0), - decodeBuffer(maxFrameSize), encodeBuffer(maxFrameSize), encoded(0) -{ - const void* value(0); - int result = sasl_getprop(conn, SASL_MAXOUTBUF, &value); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL encode error: " << sasl_errdetail(conn))); - } - maxInputSize = *(reinterpret_cast<const unsigned*>(value)); -} - -size_t CyrusSecurityLayer::decode(const char* input, size_t size) -{ - size_t inStart = 0; - do { - size_t inSize = std::min(size - inStart, maxInputSize); - int result = sasl_decode(conn, input + inStart, inSize, &decrypted, &decryptedSize); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL decode error: " << sasl_errdetail(conn))); - } - inStart += inSize; - size_t copied = 0; - do { - size_t count = std::min(decryptedSize - copied, decodeBuffer.size - decodeBuffer.position); - ::memcpy(decodeBuffer.data + decodeBuffer.position, decrypted + copied, count); - copied += count; - decodeBuffer.position += count; - size_t decodedSize = codec->decode(decodeBuffer.data, decodeBuffer.position); - if (decodedSize < decodeBuffer.position) { - ::memmove(decodeBuffer.data, decodeBuffer.data + decodedSize, decodeBuffer.position - decodedSize); - } - decodeBuffer.position -= decodedSize; - } while (copied < decryptedSize); - } while (inStart < size); - return size; -} - -size_t CyrusSecurityLayer::encode(const char* buffer, size_t size) -{ - size_t processed = 0;//records how many bytes have been written to buffer - do { - if (!encrypted) { - if (!encoded) { - encodeBuffer.position = 0; - encoded = codec->encode(encodeBuffer.data, encodeBuffer.size); - if (!encoded) break;//nothing more to do - } - - size_t encryptable = std::min(encoded, maxInputSize); - int result = sasl_encode(conn, encodeBuffer.data + encodeBuffer.position, encryptable, &encrypted, &encryptedSize); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL encode error: " << sasl_errdetail(conn))); - } - encodeBuffer.position += encryptable; - encoded -= encryptable; - } - size_t remaining = size - processed; - if (remaining < encryptedSize) { - //can't fit all encrypted data in the buffer we've - //been given, copy in what we can and hold on to the - //rest until the next call - ::memcpy(const_cast<char*>(buffer + processed), encrypted, remaining); - processed += remaining; - encrypted += remaining; - encryptedSize -= remaining; - } else { - ::memcpy(const_cast<char*>(buffer + processed), encrypted, encryptedSize); - processed += encryptedSize; - encrypted = 0; - encryptedSize = 0; - } - } while (processed < size); - return processed; -} - -bool CyrusSecurityLayer::canEncode() -{ - return codec && (encrypted || codec->canEncode()); -} - -void CyrusSecurityLayer::init(qpid::sys::Codec* c) -{ - codec = c; -} - -CyrusSecurityLayer::DataBuffer::DataBuffer(size_t s) : position(0), size(s) -{ - data = new char[size]; -} - -CyrusSecurityLayer::DataBuffer::~DataBuffer() -{ - delete[] data; -} - -}}} // namespace qpid::sys::cyrus diff --git a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h deleted file mode 100644 index 1645cf1a58..0000000000 --- a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef QPID_SYS_CYRUS_CYRUSSECURITYLAYER_H -#define QPID_SYS_CYRUS_CYRUSSECURITYLAYER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/SecurityLayer.h" -#include <sasl/sasl.h> - -namespace qpid { -namespace sys { -namespace cyrus { - - -/** - * Implementation of SASL security layer using cyrus-sasl library - */ -class CyrusSecurityLayer : public qpid::sys::SecurityLayer -{ - public: - CyrusSecurityLayer(sasl_conn_t*, uint16_t maxFrameSize); - size_t decode(const char* buffer, size_t size); - size_t encode(const char* buffer, size_t size); - bool canEncode(); - void init(qpid::sys::Codec*); - private: - struct DataBuffer - { - char* data; - size_t position; - const size_t size; - DataBuffer(size_t); - ~DataBuffer(); - }; - - sasl_conn_t* conn; - const char* decrypted; - unsigned decryptedSize; - const char* encrypted; - unsigned encryptedSize; - qpid::sys::Codec* codec; - size_t maxInputSize; - DataBuffer decodeBuffer; - DataBuffer encodeBuffer; - size_t encoded; -}; -}}} // namespace qpid::sys::cyrus - -#endif /*!QPID_SYS_CYRUS_CYRUSSECURITYLAYER_H*/ diff --git a/cpp/src/qpid/sys/epoll/EpollPoller.cpp b/cpp/src/qpid/sys/epoll/EpollPoller.cpp deleted file mode 100644 index 9ad05c71a3..0000000000 --- a/cpp/src/qpid/sys/epoll/EpollPoller.cpp +++ /dev/null @@ -1,674 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Poller.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/AtomicCount.h" -#include "qpid/sys/DeletionManager.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include "qpid/log/Statement.h" - -#include <sys/epoll.h> -#include <errno.h> -#include <signal.h> - -#include <assert.h> -#include <queue> -#include <set> -#include <exception> - -namespace qpid { -namespace sys { - -// Deletion manager to handle deferring deletion of PollerHandles to when they definitely aren't being used -DeletionManager<PollerHandlePrivate> PollerHandleDeletionManager; - -// Instantiate (and define) class static for DeletionManager -template <> -DeletionManager<PollerHandlePrivate>::AllThreadsStatuses DeletionManager<PollerHandlePrivate>::allThreadsStatuses(0); - -class PollerHandlePrivate { - friend class Poller; - friend class PollerPrivate; - friend class PollerHandle; - - enum FDStat { - ABSENT, - MONITORED, - INACTIVE, - HUNGUP, - MONITORED_HUNGUP, - INTERRUPTED, - INTERRUPTED_HUNGUP, - DELETED - }; - - ::__uint32_t events; - const IOHandlePrivate* ioHandle; - PollerHandle* pollerHandle; - FDStat stat; - Mutex lock; - - PollerHandlePrivate(const IOHandlePrivate* h, PollerHandle* p) : - events(0), - ioHandle(h), - pollerHandle(p), - stat(ABSENT) { - } - - int fd() const { - return toFd(ioHandle); - } - - bool isActive() const { - return stat == MONITORED || stat == MONITORED_HUNGUP; - } - - void setActive() { - stat = (stat == HUNGUP || stat == INTERRUPTED_HUNGUP) - ? MONITORED_HUNGUP - : MONITORED; - } - - bool isInactive() const { - return stat == INACTIVE || stat == HUNGUP; - } - - void setInactive() { - stat = INACTIVE; - } - - bool isIdle() const { - return stat == ABSENT; - } - - void setIdle() { - stat = ABSENT; - } - - bool isHungup() const { - return - stat == MONITORED_HUNGUP || - stat == HUNGUP || - stat == INTERRUPTED_HUNGUP; - } - - void setHungup() { - assert(stat == MONITORED); - stat = HUNGUP; - } - - bool isInterrupted() const { - return stat == INTERRUPTED || stat == INTERRUPTED_HUNGUP; - } - - void setInterrupted() { - stat = (stat == MONITORED_HUNGUP || stat == HUNGUP) - ? INTERRUPTED_HUNGUP - : INTERRUPTED; - } - - bool isDeleted() const { - return stat == DELETED; - } - - void setDeleted() { - stat = DELETED; - } -}; - -PollerHandle::PollerHandle(const IOHandle& h) : - impl(new PollerHandlePrivate(h.impl, this)) -{} - -PollerHandle::~PollerHandle() { - { - ScopedLock<Mutex> l(impl->lock); - if (impl->isDeleted()) { - return; - } - impl->pollerHandle = 0; - if (impl->isInterrupted()) { - impl->setDeleted(); - return; - } - assert(impl->isIdle()); - impl->setDeleted(); - } - PollerHandleDeletionManager.markForDeletion(impl); -} - -class HandleSet -{ - Mutex lock; - std::set<PollerHandle*> handles; - public: - void add(PollerHandle*); - void remove(PollerHandle*); - void cleanup(); -}; - -void HandleSet::add(PollerHandle* h) -{ - ScopedLock<Mutex> l(lock); - handles.insert(h); -} -void HandleSet::remove(PollerHandle* h) -{ - ScopedLock<Mutex> l(lock); - handles.erase(h); -} -void HandleSet::cleanup() -{ - // Inform all registered handles of disconnection - std::set<PollerHandle*> copy; - handles.swap(copy); - for (std::set<PollerHandle*>::const_iterator i = copy.begin(); i != copy.end(); ++i) { - Poller::Event event(*i, Poller::DISCONNECTED); - event.process(); - } -} - -/** - * Concrete implementation of Poller to use the Linux specific epoll - * interface - */ -class PollerPrivate { - friend class Poller; - - static const int DefaultFds = 256; - - struct ReadablePipe { - int fds[2]; - - /** - * This encapsulates an always readable pipe which we can add - * to the epoll set to force epoll_wait to return - */ - ReadablePipe() { - QPID_POSIX_CHECK(::pipe(fds)); - // Just write the pipe's fds to the pipe - QPID_POSIX_CHECK(::write(fds[1], fds, 2)); - } - - ~ReadablePipe() { - ::close(fds[0]); - ::close(fds[1]); - } - - int getFD() { - return fds[0]; - } - }; - - static ReadablePipe alwaysReadable; - static int alwaysReadableFd; - - class InterruptHandle: public PollerHandle { - std::queue<PollerHandle*> handles; - - void processEvent(Poller::EventType) { - PollerHandle* handle = handles.front(); - handles.pop(); - assert(handle); - - // Synthesise event - Poller::Event event(handle, Poller::INTERRUPTED); - - // Process synthesised event - event.process(); - } - - public: - InterruptHandle() : - PollerHandle(DummyIOHandle) - {} - - void addHandle(PollerHandle& h) { - handles.push(&h); - } - - PollerHandle* getHandle() { - PollerHandle* handle = handles.front(); - handles.pop(); - return handle; - } - - bool queuedHandles() { - return handles.size() > 0; - } - }; - - const int epollFd; - bool isShutdown; - InterruptHandle interruptHandle; - HandleSet registeredHandles; - AtomicCount threadCount; - - static ::__uint32_t directionToEpollEvent(Poller::Direction dir) { - switch (dir) { - case Poller::INPUT: return ::EPOLLIN; - case Poller::OUTPUT: return ::EPOLLOUT; - case Poller::INOUT: return ::EPOLLIN | ::EPOLLOUT; - default: return 0; - } - } - - static Poller::EventType epollToDirection(::__uint32_t events) { - // POLLOUT & POLLHUP are mutually exclusive really, but at least socketpairs - // can give you both! - events = (events & ::EPOLLHUP) ? events & ~::EPOLLOUT : events; - ::__uint32_t e = events & (::EPOLLIN | ::EPOLLOUT); - switch (e) { - case ::EPOLLIN: return Poller::READABLE; - case ::EPOLLOUT: return Poller::WRITABLE; - case ::EPOLLIN | ::EPOLLOUT: return Poller::READ_WRITABLE; - default: - return (events & (::EPOLLHUP | ::EPOLLERR)) ? - Poller::DISCONNECTED : Poller::INVALID; - } - } - - PollerPrivate() : - epollFd(::epoll_create(DefaultFds)), - isShutdown(false) { - QPID_POSIX_CHECK(epollFd); - // Add always readable fd into our set (but not listening to it yet) - ::epoll_event epe; - epe.events = 0; - epe.data.u64 = 1; - QPID_POSIX_CHECK(::epoll_ctl(epollFd, EPOLL_CTL_ADD, alwaysReadableFd, &epe)); - } - - ~PollerPrivate() { - // It's probably okay to ignore any errors here as there can't be data loss - ::close(epollFd); - - // Need to put the interruptHandle in idle state to delete it - static_cast<PollerHandle&>(interruptHandle).impl->setIdle(); - } - - void resetMode(PollerHandlePrivate& handle); - - void interrupt() { - ::epoll_event epe; - // Use EPOLLONESHOT so we only wake a single thread - epe.events = ::EPOLLIN | ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &static_cast<PollerHandle&>(interruptHandle); - QPID_POSIX_CHECK(::epoll_ctl(epollFd, EPOLL_CTL_MOD, alwaysReadableFd, &epe)); - } - - void interruptAll() { - ::epoll_event epe; - // Not EPOLLONESHOT, so we eventually get all threads - epe.events = ::EPOLLIN; - epe.data.u64 = 2; // Keep valgrind happy - QPID_POSIX_CHECK(::epoll_ctl(epollFd, EPOLL_CTL_MOD, alwaysReadableFd, &epe)); - } -}; - -PollerPrivate::ReadablePipe PollerPrivate::alwaysReadable; -int PollerPrivate::alwaysReadableFd = alwaysReadable.getFD(); - -void Poller::registerHandle(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock<Mutex> l(eh.lock); - assert(eh.isIdle()); - - ::epoll_event epe; - epe.events = ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - - impl->registeredHandles.add(&handle); - QPID_POSIX_CHECK(::epoll_ctl(impl->epollFd, EPOLL_CTL_ADD, eh.fd(), &epe)); - - eh.setActive(); -} - -void Poller::unregisterHandle(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock<Mutex> l(eh.lock); - assert(!eh.isIdle()); - - impl->registeredHandles.remove(&handle); - int rc = ::epoll_ctl(impl->epollFd, EPOLL_CTL_DEL, eh.fd(), 0); - // Ignore EBADF since deleting a nonexistent fd has the overall required result! - // And allows the case where a sloppy program closes the fd and then does the delFd() - if (rc == -1 && errno != EBADF) { - QPID_POSIX_CHECK(rc); - } - - eh.setIdle(); -} - -void PollerPrivate::resetMode(PollerHandlePrivate& eh) { - PollerHandle* ph; - { - ScopedLock<Mutex> l(eh.lock); - assert(!eh.isActive()); - - if (eh.isIdle() || eh.isDeleted()) { - return; - } - - if (eh.events==0) { - eh.setActive(); - return; - } - - if (!eh.isInterrupted()) { - ::epoll_event epe; - epe.events = eh.events | ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - - QPID_POSIX_CHECK(::epoll_ctl(epollFd, EPOLL_CTL_MOD, eh.fd(), &epe)); - - eh.setActive(); - return; - } - ph = eh.pollerHandle; - } - - PollerHandlePrivate& ihp = *static_cast<PollerHandle&>(interruptHandle).impl; - ScopedLock<Mutex> l(ihp.lock); - interruptHandle.addHandle(*ph); - ihp.setActive(); - interrupt(); -} - -void Poller::monitorHandle(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock<Mutex> l(eh.lock); - assert(!eh.isIdle()); - - ::__uint32_t oldEvents = eh.events; - eh.events |= PollerPrivate::directionToEpollEvent(dir); - - // If no change nothing more to do - avoid unnecessary system call - if (oldEvents==eh.events) { - return; - } - - // If we're not actually listening wait till we are to perform change - if (!eh.isActive()) { - return; - } - - ::epoll_event epe; - epe.events = eh.events | ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - - QPID_POSIX_CHECK(::epoll_ctl(impl->epollFd, EPOLL_CTL_MOD, eh.fd(), &epe)); -} - -void Poller::unmonitorHandle(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock<Mutex> l(eh.lock); - assert(!eh.isIdle()); - - ::__uint32_t oldEvents = eh.events; - eh.events &= ~PollerPrivate::directionToEpollEvent(dir); - - // If no change nothing more to do - avoid unnecessary system call - if (oldEvents==eh.events) { - return; - } - - // If we're not actually listening wait till we are to perform change - if (!eh.isActive()) { - return; - } - - ::epoll_event epe; - epe.events = eh.events | ::EPOLLONESHOT; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - - QPID_POSIX_CHECK(::epoll_ctl(impl->epollFd, EPOLL_CTL_MOD, eh.fd(), &epe)); -} - -void Poller::shutdown() { - // NB: this function must be async-signal safe, it must not - // call any function that is not async-signal safe. - - // Allow sloppy code to shut us down more than once - if (impl->isShutdown) - return; - - // Don't use any locking here - isShutdown will be visible to all - // after the epoll_ctl() anyway (it's a memory barrier) - impl->isShutdown = true; - - impl->interruptAll(); -} - -bool Poller::interrupt(PollerHandle& handle) { - { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock<Mutex> l(eh.lock); - if (eh.isIdle() || eh.isDeleted()) { - return false; - } - - if (eh.isInterrupted()) { - return true; - } - - // Stop monitoring handle for read or write - ::epoll_event epe; - epe.events = 0; - epe.data.u64 = 0; // Keep valgrind happy - epe.data.ptr = &eh; - QPID_POSIX_CHECK(::epoll_ctl(impl->epollFd, EPOLL_CTL_MOD, eh.fd(), &epe)); - - if (eh.isInactive()) { - eh.setInterrupted(); - return true; - } - eh.setInterrupted(); - } - - PollerPrivate::InterruptHandle& ih = impl->interruptHandle; - PollerHandlePrivate& eh = *static_cast<PollerHandle&>(ih).impl; - ScopedLock<Mutex> l(eh.lock); - ih.addHandle(handle); - - impl->interrupt(); - eh.setActive(); - return true; -} - -void Poller::run() { - // Ensure that we exit thread responsibly under all circumstances - try { - // Make sure we can't be interrupted by signals at a bad time - ::sigset_t ss; - ::sigfillset(&ss); - ::pthread_sigmask(SIG_SETMASK, &ss, 0); - - ++(impl->threadCount); - do { - Event event = wait(); - - // If can read/write then dispatch appropriate callbacks - if (event.handle) { - event.process(); - } else { - // Handle shutdown - switch (event.type) { - case SHUTDOWN: - PollerHandleDeletionManager.destroyThreadState(); - //last thread to respond to shutdown cleans up: - if (--(impl->threadCount) == 0) impl->registeredHandles.cleanup(); - return; - default: - // This should be impossible - assert(false); - } - } - } while (true); - } catch (const std::exception& e) { - QPID_LOG(error, "IO worker thread exiting with unhandled exception: " << e.what()); - } - PollerHandleDeletionManager.destroyThreadState(); - --(impl->threadCount); -} - -bool Poller::hasShutdown() -{ - return impl->isShutdown; -} - -Poller::Event Poller::wait(Duration timeout) { - static __thread PollerHandlePrivate* lastReturnedHandle = 0; - epoll_event epe; - int timeoutMs = (timeout == TIME_INFINITE) ? -1 : timeout / TIME_MSEC; - AbsTime targetTimeout = - (timeout == TIME_INFINITE) ? - FAR_FUTURE : - AbsTime(now(), timeout); - - if (lastReturnedHandle) { - impl->resetMode(*lastReturnedHandle); - lastReturnedHandle = 0; - } - - // Repeat until we weren't interrupted by signal - do { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - int rc = ::epoll_wait(impl->epollFd, &epe, 1, timeoutMs); - if (rc ==-1 && errno != EINTR) { - QPID_POSIX_CHECK(rc); - } else if (rc > 0) { - assert(rc == 1); - void* dataPtr = epe.data.ptr; - - // Check if this is an interrupt - PollerPrivate::InterruptHandle& interruptHandle = impl->interruptHandle; - if (dataPtr == &interruptHandle) { - // If we are shutting down we need to rearm the shutdown interrupt to - // ensure everyone still sees it. It's okay that this might be overridden - // below as we will be back here if it is. - if (impl->isShutdown) { - impl->interruptAll(); - } - PollerHandle* wrappedHandle = 0; - { - ScopedLock<Mutex> l(interruptHandle.impl->lock); - if (interruptHandle.impl->isActive()) { - wrappedHandle = interruptHandle.getHandle(); - // If there is an interrupt queued behind this one we need to arm it - // We do it this way so that another thread can pick it up - if (interruptHandle.queuedHandles()) { - impl->interrupt(); - interruptHandle.impl->setActive(); - } else { - interruptHandle.impl->setInactive(); - } - } - } - if (wrappedHandle) { - PollerHandlePrivate& eh = *wrappedHandle->impl; - { - ScopedLock<Mutex> l(eh.lock); - if (!eh.isDeleted()) { - if (!eh.isIdle()) { - eh.setInactive(); - } - lastReturnedHandle = &eh; - assert(eh.pollerHandle == wrappedHandle); - return Event(wrappedHandle, INTERRUPTED); - } - } - PollerHandleDeletionManager.markForDeletion(&eh); - } - continue; - } - - // Check for shutdown - if (impl->isShutdown) { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - return Event(0, SHUTDOWN); - } - - PollerHandlePrivate& eh = *static_cast<PollerHandlePrivate*>(dataPtr); - ScopedLock<Mutex> l(eh.lock); - - // the handle could have gone inactive since we left the epoll_wait - if (eh.isActive()) { - PollerHandle* handle = eh.pollerHandle; - assert(handle); - - // If the connection has been hungup we could still be readable - // (just not writable), allow us to readable until we get here again - if (epe.events & ::EPOLLHUP) { - if (eh.isHungup()) { - eh.setInactive(); - // Don't set up last Handle so that we don't reset this handle - // on re-entering Poller::wait. This means that we will never - // be set active again once we've returned disconnected, and so - // can never be returned again. - return Event(handle, DISCONNECTED); - } - eh.setHungup(); - } else { - eh.setInactive(); - } - lastReturnedHandle = &eh; - return Event(handle, PollerPrivate::epollToDirection(epe.events)); - } - } - // We only get here if one of the following: - // * epoll_wait was interrupted by a signal - // * epoll_wait timed out - // * the state of the handle changed after being returned by epoll_wait - // - // The only things we can do here are return a timeout or wait more. - // Obviously if we timed out we return timeout; if the wait was meant to - // be indefinite then we should never return with a time out so we go again. - // If the wait wasn't indefinite, we check whether we are after the target wait - // time or not - if (timeoutMs == -1) { - continue; - } - if (rc == 0 && now() > targetTimeout) { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - return Event(0, TIMEOUT); - } - } while (true); -} - -// Concrete constructors -Poller::Poller() : - impl(new PollerPrivate()) -{} - -Poller::~Poller() { - delete impl; -} - -}} diff --git a/cpp/src/qpid/sys/posix/AsynchIO.cpp b/cpp/src/qpid/sys/posix/AsynchIO.cpp deleted file mode 100644 index 119a6aa8a4..0000000000 --- a/cpp/src/qpid/sys/posix/AsynchIO.cpp +++ /dev/null @@ -1,611 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/DispatchHandle.h" -#include "qpid/sys/Time.h" -#include "qpid/log/Statement.h" - -#include "qpid/sys/posix/check.h" - -// TODO The basic algorithm here is not really POSIX specific and with a -// bit more abstraction could (should) be promoted to be platform portable -#include <unistd.h> -#include <sys/socket.h> -#include <signal.h> -#include <errno.h> -#include <string.h> - -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> - -using namespace qpid::sys; - -namespace { - -struct StaticInit { - StaticInit() { - /** - * Make *process* not generate SIGPIPE when writing to closed - * pipe/socket (necessary as default action is to terminate process) - */ - ::signal(SIGPIPE, SIG_IGN); - }; -} init; - -/* - * We keep per thread state to avoid locking overhead. The assumption is that - * on average all the connections are serviced by all the threads so the state - * recorded in each thread is about the same. If this turns out not to be the - * case we could rebalance the info occasionally. - */ -__thread int threadReadTotal = 0; -__thread int threadMaxRead = 0; -__thread int threadReadCount = 0; -__thread int threadWriteTotal = 0; -__thread int threadWriteCount = 0; -__thread int64_t threadMaxReadTimeNs = 2 * 1000000; // start at 2ms -} - -/* - * Asynch Acceptor - */ -namespace qpid { -namespace sys { -namespace posix { - -class AsynchAcceptor : public qpid::sys::AsynchAcceptor { -public: - AsynchAcceptor(const Socket& s, AsynchAcceptor::Callback callback); - ~AsynchAcceptor(); - void start(Poller::shared_ptr poller); - -private: - void readable(DispatchHandle& handle); - -private: - AsynchAcceptor::Callback acceptedCallback; - DispatchHandle handle; - const Socket& socket; - -}; - -AsynchAcceptor::AsynchAcceptor(const Socket& s, - AsynchAcceptor::Callback callback) : - acceptedCallback(callback), - handle(s, boost::bind(&AsynchAcceptor::readable, this, _1), 0, 0), - socket(s) { - - s.setNonblocking(); -} - -AsynchAcceptor::~AsynchAcceptor() { - handle.stopWatch(); -} - -void AsynchAcceptor::start(Poller::shared_ptr poller) { - handle.startWatch(poller); -} - -/* - * We keep on accepting as long as there is something to accept - */ -void AsynchAcceptor::readable(DispatchHandle& h) { - Socket* s; - do { - errno = 0; - // TODO: Currently we ignore the peers address, perhaps we should - // log it or use it for connection acceptance. - try { - s = socket.accept(); - if (s) { - acceptedCallback(*s); - } else { - break; - } - } catch (const std::exception& e) { - QPID_LOG(error, "Could not accept socket: " << e.what()); - break; - } - } while (true); - - h.rewatch(); -} - -/* - * POSIX version of AsynchIO TCP socket connector. - * - * The class is implemented in terms of DispatchHandle to allow it to be - * deleted by deleting the contained DispatchHandle. - */ -class AsynchConnector : public qpid::sys::AsynchConnector, - private DispatchHandle { - -private: - void connComplete(DispatchHandle& handle); - -private: - ConnectedCallback connCallback; - FailedCallback failCallback; - const Socket& socket; - -public: - AsynchConnector(const Socket& socket, - std::string hostname, - uint16_t port, - ConnectedCallback connCb, - FailedCallback failCb); - void start(Poller::shared_ptr poller); - void stop(); -}; - -AsynchConnector::AsynchConnector(const Socket& s, - std::string hostname, - uint16_t port, - ConnectedCallback connCb, - FailedCallback failCb) : - DispatchHandle(s, - 0, - boost::bind(&AsynchConnector::connComplete, this, _1), - boost::bind(&AsynchConnector::connComplete, this, _1)), - connCallback(connCb), - failCallback(failCb), - socket(s) -{ - socket.setNonblocking(); - SocketAddress sa(hostname, boost::lexical_cast<std::string>(port)); - // Note, not catching any exceptions here, also has effect of destructing - socket.connect(sa); -} - -void AsynchConnector::start(Poller::shared_ptr poller) -{ - startWatch(poller); -} - -void AsynchConnector::stop() -{ - stopWatch(); -} - -void AsynchConnector::connComplete(DispatchHandle& h) -{ - h.stopWatch(); - int errCode = socket.getError(); - if (errCode == 0) { - connCallback(socket); - } else { - failCallback(socket, errCode, strError(errCode)); - } - DispatchHandle::doDelete(); -} - -/* - * POSIX version of AsynchIO reader/writer - * - * The class is implemented in terms of DispatchHandle to allow it to be - * deleted by deleting the contained DispatchHandle. - */ -class AsynchIO : public qpid::sys::AsynchIO, private DispatchHandle { - -public: - AsynchIO(const Socket& s, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0); - - // Methods inherited from qpid::sys::AsynchIO - - virtual void queueForDeletion(); - - virtual void start(Poller::shared_ptr poller); - virtual void queueReadBuffer(BufferBase* buff); - virtual void unread(BufferBase* buff); - virtual void queueWrite(BufferBase* buff); - virtual void notifyPendingWrite(); - virtual void queueWriteClose(); - virtual bool writeQueueEmpty(); - virtual void startReading(); - virtual void stopReading(); - virtual void requestCallback(RequestCallback); - virtual BufferBase* getQueuedBuffer(); - -private: - ~AsynchIO(); - - // Methods that are callback targets from Dispatcher. - void readable(DispatchHandle& handle); - void writeable(DispatchHandle& handle); - void disconnected(DispatchHandle& handle); - void requestedCall(RequestCallback); - void close(DispatchHandle& handle); - -private: - ReadCallback readCallback; - EofCallback eofCallback; - DisconnectCallback disCallback; - ClosedCallback closedCallback; - BuffersEmptyCallback emptyCallback; - IdleCallback idleCallback; - const Socket& socket; - std::deque<BufferBase*> bufferQueue; - std::deque<BufferBase*> writeQueue; - bool queuedClose; - /** - * This flag is used to detect and handle concurrency between - * calls to notifyPendingWrite() (which can be made from any thread) and - * the execution of the writeable() method (which is always on the - * thread processing this handle. - */ - volatile bool writePending; - /** - * This records whether we've been reading is flow controlled: - * it's safe as a simple boolean as the only way to be stopped - * is in calls only allowed in the callback context, the only calls - * checking it are also in calls only allowed in callback context. - */ - volatile bool readingStopped; -}; - -AsynchIO::AsynchIO(const Socket& s, - ReadCallback rCb, EofCallback eofCb, DisconnectCallback disCb, - ClosedCallback cCb, BuffersEmptyCallback eCb, IdleCallback iCb) : - - DispatchHandle(s, - boost::bind(&AsynchIO::readable, this, _1), - boost::bind(&AsynchIO::writeable, this, _1), - boost::bind(&AsynchIO::disconnected, this, _1)), - readCallback(rCb), - eofCallback(eofCb), - disCallback(disCb), - closedCallback(cCb), - emptyCallback(eCb), - idleCallback(iCb), - socket(s), - queuedClose(false), - writePending(false), - readingStopped(false) { - - s.setNonblocking(); -} - -struct deleter -{ - template <typename T> - void operator()(T *ptr){ delete ptr;} -}; - -AsynchIO::~AsynchIO() { - std::for_each( bufferQueue.begin(), bufferQueue.end(), deleter()); - std::for_each( writeQueue.begin(), writeQueue.end(), deleter()); -} - -void AsynchIO::queueForDeletion() { - DispatchHandle::doDelete(); -} - -void AsynchIO::start(Poller::shared_ptr poller) { - DispatchHandle::startWatch(poller); -} - -void AsynchIO::queueReadBuffer(BufferBase* buff) { - assert(buff); - buff->dataStart = 0; - buff->dataCount = 0; - - bool queueWasEmpty = bufferQueue.empty(); - bufferQueue.push_back(buff); - if (queueWasEmpty && !readingStopped) - DispatchHandle::rewatchRead(); -} - -void AsynchIO::unread(BufferBase* buff) { - assert(buff); - buff->squish(); - - bool queueWasEmpty = bufferQueue.empty(); - bufferQueue.push_front(buff); - if (queueWasEmpty && !readingStopped) - DispatchHandle::rewatchRead(); -} - -void AsynchIO::queueWrite(BufferBase* buff) { - assert(buff); - // If we've already closed the socket then throw the write away - if (queuedClose) { - queueReadBuffer(buff); - return; - } else { - writeQueue.push_front(buff); - } - writePending = false; - DispatchHandle::rewatchWrite(); -} - -// This can happen outside the callback context -void AsynchIO::notifyPendingWrite() { - writePending = true; - DispatchHandle::rewatchWrite(); -} - -void AsynchIO::queueWriteClose() { - queuedClose = true; - DispatchHandle::rewatchWrite(); -} - -bool AsynchIO::writeQueueEmpty() { - return writeQueue.empty(); -} - -// This can happen outside the callback context -void AsynchIO::startReading() { - readingStopped = false; - DispatchHandle::rewatchRead(); -} - -void AsynchIO::stopReading() { - readingStopped = true; - DispatchHandle::unwatchRead(); -} - -void AsynchIO::requestCallback(RequestCallback callback) { - // TODO creating a function object every time isn't all that - // efficient - if this becomes heavily used do something better (what?) - assert(callback); - DispatchHandle::call(boost::bind(&AsynchIO::requestedCall, this, callback)); -} - -void AsynchIO::requestedCall(RequestCallback callback) { - assert(callback); - callback(*this); -} - -/** Return a queued buffer if there are enough - * to spare - */ -AsynchIO::BufferBase* AsynchIO::getQueuedBuffer() { - // Always keep at least one buffer (it might have data that was "unread" in it) - if (bufferQueue.size()<=1) - return 0; - BufferBase* buff = bufferQueue.back(); - assert(buff); - buff->dataStart = 0; - buff->dataCount = 0; - bufferQueue.pop_back(); - return buff; -} - -/* - * We keep on reading as long as we have something to read, a buffer - * to put it in and reading is not stopped by flow control. - */ -void AsynchIO::readable(DispatchHandle& h) { - if (readingStopped) { - // We have been flow controlled. - return; - } - int readTotal = 0; - AbsTime readStartTime = AbsTime::now(); - do { - // (Try to) get a buffer - if (!bufferQueue.empty()) { - // Read into buffer - BufferBase* buff = bufferQueue.front(); - assert(buff); - bufferQueue.pop_front(); - errno = 0; - int readCount = buff->byteCount-buff->dataCount; - int rc = socket.read(buff->bytes + buff->dataCount, readCount); - if (rc > 0) { - buff->dataCount += rc; - threadReadTotal += rc; - readTotal += rc; - - readCallback(*this, buff); - if (readingStopped) { - // We have been flow controlled. - break; - } - - if (rc != readCount) { - // If we didn't fill the read buffer then time to stop reading - break; - } - - // Stop reading if we've overrun our timeslot - if (Duration(readStartTime, AbsTime::now()) > threadMaxReadTimeNs) { - break; - } - - } else { - // Put buffer back (at front so it doesn't interfere with unread buffers) - bufferQueue.push_front(buff); - assert(buff); - - // Eof or other side has gone away - if (rc == 0 || errno == ECONNRESET) { - eofCallback(*this); - h.unwatchRead(); - break; - } else if (errno == EAGAIN) { - // We have just put a buffer back so we know - // we can carry on watching for reads - break; - } else { - // Report error then just treat as a socket disconnect - QPID_LOG(error, "Error reading socket: " << qpid::sys::strError(errno) << "(" << errno << ")" ); - eofCallback(*this); - h.unwatchRead(); - break; - } - } - } else { - // Something to read but no buffer - if (emptyCallback) { - emptyCallback(*this); - } - // If we still have no buffers we can't do anything more - if (bufferQueue.empty()) { - h.unwatchRead(); - break; - } - - } - } while (true); - - ++threadReadCount; - threadMaxRead = std::max(threadMaxRead, readTotal); - return; -} - -/* - * We carry on writing whilst we have data to write and we can write - */ -void AsynchIO::writeable(DispatchHandle& h) { - int writeTotal = 0; - do { - // See if we've got something to write - if (!writeQueue.empty()) { - // Write buffer - BufferBase* buff = writeQueue.back(); - writeQueue.pop_back(); - errno = 0; - assert(buff->dataStart+buff->dataCount <= buff->byteCount); - int rc = socket.write(buff->bytes+buff->dataStart, buff->dataCount); - if (rc >= 0) { - threadWriteTotal += rc; - writeTotal += rc; - - // If we didn't write full buffer put rest back - if (rc != buff->dataCount) { - buff->dataStart += rc; - buff->dataCount -= rc; - writeQueue.push_back(buff); - break; - } - - // Recycle the buffer - queueReadBuffer(buff); - - // If we've already written more than the max for reading then stop - // (this is to stop writes dominating reads) - if (writeTotal > threadMaxRead) - break; - } else { - // Put buffer back - writeQueue.push_back(buff); - if (errno == ECONNRESET || errno == EPIPE) { - // Just stop watching for write here - we'll get a - // disconnect callback soon enough - h.unwatchWrite(); - break; - } else if (errno == EAGAIN) { - // We have just put a buffer back so we know - // we can carry on watching for writes - break; - } else { - // Report error then just treat as a socket disconnect - QPID_LOG(error, "Error writing socket: " << qpid::sys::strError(errno) << "(" << errno << ")" ); - h.unwatchWrite(); - break; - } - } - } else { - // If we're waiting to close the socket then can do it now as there is nothing to write - if (queuedClose) { - close(h); - break; - } - // Fd is writable, but nothing to write - if (idleCallback) { - writePending = false; - idleCallback(*this); - } - // If we still have no buffers to write we can't do anything more - if (writeQueue.empty() && !writePending && !queuedClose) { - h.unwatchWrite(); - // The following handles the case where writePending is - // set to true after the test above; in this case its - // possible that the unwatchWrite overwrites the - // desired rewatchWrite so we correct that here - if (writePending) - h.rewatchWrite(); - break; - } - } - } while (true); - - ++threadWriteCount; - return; -} - -void AsynchIO::disconnected(DispatchHandle& h) { - // If we have not already queued close then call disconnected callback before closing - if (!queuedClose && disCallback) disCallback(*this); - close(h); -} - -/* - * Close the socket and callback to say we've done it - */ -void AsynchIO::close(DispatchHandle& h) { - h.stopWatch(); - socket.close(); - if (closedCallback) { - closedCallback(*this, socket); - } -} - -} // namespace posix - -AsynchAcceptor* AsynchAcceptor::create(const Socket& s, - Callback callback) -{ - return new posix::AsynchAcceptor(s, callback); -} - -AsynchConnector* AsynchConnector::create(const Socket& s, - std::string hostname, - uint16_t port, - ConnectedCallback connCb, - FailedCallback failCb) -{ - return new posix::AsynchConnector(s, hostname, port, connCb, failCb); -} - -AsynchIO* AsynchIO::create(const Socket& s, - AsynchIO::ReadCallback rCb, - AsynchIO::EofCallback eofCb, - AsynchIO::DisconnectCallback disCb, - AsynchIO::ClosedCallback cCb, - AsynchIO::BuffersEmptyCallback eCb, - AsynchIO::IdleCallback iCb) -{ - return new posix::AsynchIO(s, rCb, eofCb, disCb, cCb, eCb, iCb); -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/posix/FileSysDir.cpp b/cpp/src/qpid/sys/posix/FileSysDir.cpp deleted file mode 100755 index 22dc487e74..0000000000 --- a/cpp/src/qpid/sys/posix/FileSysDir.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/FileSysDir.h" -#include "qpid/sys/StrError.h" -#include "qpid/Exception.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <cerrno> -#include <unistd.h> - -namespace qpid { -namespace sys { - -bool FileSysDir::exists (void) const -{ - const char *cpath = dirPath.c_str (); - struct stat s; - if (::stat(cpath, &s)) { - if (errno == ENOENT) { - return false; - } - throw qpid::Exception (strError(errno) + - ": Can't check directory: " + dirPath); - } - if (S_ISDIR(s.st_mode)) - return true; - throw qpid::Exception(dirPath + " is not a directory"); -} - -void FileSysDir::mkdir(void) -{ - if (::mkdir(dirPath.c_str(), 0755)) - throw Exception ("Can't create directory: " + dirPath); -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/posix/Fork.cpp b/cpp/src/qpid/sys/posix/Fork.cpp deleted file mode 100644 index a0d404a16e..0000000000 --- a/cpp/src/qpid/sys/posix/Fork.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "qpid/sys/Fork.h" -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" - -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/select.h> -#include <sys/types.h> -#include <unistd.h> - -namespace qpid { -namespace sys { - -using namespace std; - -namespace { - -void writeStr(int fd, const std::string& str) { - const char* WRITE_ERR = "Error writing to parent process"; - int size = str.size(); - if (int(sizeof(size)) > ::write(fd, &size, sizeof(size))) throw ErrnoException(WRITE_ERR); - if (size > ::write(fd, str.data(), size)) throw ErrnoException(WRITE_ERR); -} - -string readStr(int fd) { - string value; - const char* READ_ERR = "Error reading from forked process"; - int size; - if (int(sizeof(size)) > ::read(fd, &size, sizeof(size))) throw ErrnoException(READ_ERR); - if (size > 0) { // Read string message - value.resize(size); - if (size > ::read(fd, const_cast<char*>(value.data()), size)) throw ErrnoException(READ_ERR); - } - return value; -} - -} // namespace - -Fork::Fork() {} -Fork::~Fork() {} - -void Fork::fork() { - pid_t pid = ::fork(); - if (pid < 0) throw ErrnoException("Failed to fork the process"); - if (pid == 0) child(); - else parent(pid); -} - -ForkWithMessage::ForkWithMessage() { - pipeFds[0] = pipeFds[1] = -1; -} - -struct AutoCloseFd { - int fd; - AutoCloseFd(int d) : fd(d) {} - ~AutoCloseFd() { ::close(fd); } -}; - -void ForkWithMessage::fork() { - if(::pipe(pipeFds) < 0) throw ErrnoException("Can't create pipe"); - pid_t pid = ::fork(); - if(pid < 0) throw ErrnoException("Fork fork failed"); - if (pid == 0) { // Child - AutoCloseFd ac(pipeFds[1]); // Write side. - ::close(pipeFds[0]); // Read side - try { - child(); - } - catch (const std::exception& e) { - QPID_LOG(error, "Error in forked child: " << e.what()); - std::string msg = e.what(); - if (msg.empty()) msg = " "; // Make sure we send a non-empty error string. - writeStr(pipeFds[1], msg); - } - } - else { // Parent - close(pipeFds[1]); // Write side. - AutoCloseFd ac(pipeFds[0]); // Read side - parent(pid); - } -} - -string ForkWithMessage::wait(int timeout) { // parent waits for child. - errno = 0; - struct timeval tv; - tv.tv_sec = timeout; - tv.tv_usec = 0; - - fd_set fds; - FD_ZERO(&fds); - FD_SET(pipeFds[0], &fds); - int n=select(FD_SETSIZE, &fds, 0, 0, &tv); - if(n<0) throw ErrnoException("Error waiting for fork"); - if (n==0) throw Exception("Timed out waiting for fork"); - - string error = readStr(pipeFds[0]); - if (error.empty()) return readStr(pipeFds[0]); - else throw Exception("Error in forked process: " + error); -} - -// Write empty error string followed by value string to pipe. -void ForkWithMessage::ready(const string& value) { // child - // Write empty string for error followed by value. - writeStr(pipeFds[1], string()); // No error - writeStr(pipeFds[1], value); -} - - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/posix/Fork.h b/cpp/src/qpid/sys/posix/Fork.h deleted file mode 100644 index 698c61ed30..0000000000 --- a/cpp/src/qpid/sys/posix/Fork.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef QPID_SYS_POSIX_FORK_H -#define QPID_SYS_POSIX_FORK_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <string> -#include <sys/types.h> - -namespace qpid { -namespace sys { - -/** - * Fork the process. Call parent() in parent and child() in child. - */ -class Fork { - public: - Fork(); - virtual ~Fork(); - - /** - * Fork the process. - * Calls parent() in the parent process, child() in the child. - */ - virtual void fork(); - - protected: - - /** Called in parent process. - *@child pid of child process - */ - virtual void parent(pid_t child) = 0; - - /** Called in child process */ - virtual void child() = 0; -}; - -/** - * Like Fork but also allows the child to send a string message - * or throw an exception to the parent. - */ -class ForkWithMessage : public Fork { - public: - ForkWithMessage(); - void fork(); - - protected: - /** Call from parent(): wait for child to send a value or throw exception. - * @timeout in seconds to wait for response. - * @return value passed by child to ready(). - */ - std::string wait(int timeout); - - /** Call from child(): Send a value to the parent. - *@param value returned by parent call to wait(). - */ - void ready(const std::string& value); - - private: - int pipeFds[2]; -}; - -}} // namespace qpid::sys - - - -#endif /*!QPID_SYS_POSIX_FORK_H*/ diff --git a/cpp/src/qpid/sys/posix/IOHandle.cpp b/cpp/src/qpid/sys/posix/IOHandle.cpp deleted file mode 100644 index 9c049ee1de..0000000000 --- a/cpp/src/qpid/sys/posix/IOHandle.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IOHandle.h" - -#include "qpid/sys/posix/PrivatePosix.h" - -namespace qpid { -namespace sys { - -int toFd(const IOHandlePrivate* h) -{ - return h->fd; -} - -NullIOHandle DummyIOHandle; - -IOHandle::IOHandle(IOHandlePrivate* h) : - impl(h) -{} - -IOHandle::~IOHandle() { - delete impl; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/posix/LockFile.cpp b/cpp/src/qpid/sys/posix/LockFile.cpp deleted file mode 100755 index 1862ff6ac9..0000000000 --- a/cpp/src/qpid/sys/posix/LockFile.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * Copyright (c) 2008 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/LockFile.h" -#include "qpid/sys/posix/PidFile.h" - -#include <string> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include "qpid/sys/posix/check.h" - -namespace qpid { -namespace sys { - -class LockFilePrivate { - friend class LockFile; - friend class PidFile; - - int fd; - -public: - LockFilePrivate(int f) : fd(f) {} -}; - -LockFile::LockFile(const std::string& path_, bool create) - : path(path_), created(create) { - - errno = 0; - int flags=create ? O_WRONLY|O_CREAT|O_NOFOLLOW : O_RDWR; - int fd = ::open(path.c_str(), flags, 0644); - if (fd < 0) throw ErrnoException("Cannot open " + path, errno); - if (::lockf(fd, F_TLOCK, 0) < 0) { - ::close(fd); - throw ErrnoException("Cannot lock " + path, errno); - } - impl.reset(new LockFilePrivate(fd)); -} - -LockFile::~LockFile() { - if (impl) { - int f = impl->fd; - if (f >= 0) { - int unused_ret; - unused_ret = ::lockf(f, F_ULOCK, 0); // Suppress warnings about ignoring return value. - ::close(f); - impl->fd = -1; - } - } -} - -int LockFile::read(void* bytes, size_t len) const { - if (!impl) - throw Exception("Lock file not open: " + path); - - ssize_t rc = ::read(impl->fd, bytes, len); - if ((ssize_t)len > rc) { - throw Exception("Cannot read lock file: " + path); - } - return rc; -} - -int LockFile::write(void* bytes, size_t len) const { - if (!impl) - throw Exception("Lock file not open: " + path); - - ssize_t rc = ::write(impl->fd, bytes, len); - if ((ssize_t)len > rc) { - throw Exception("Cannot write lock file: " + path); - } - return rc; -} - -PidFile::PidFile(const std::string& path_, bool create): - LockFile(path_, create) -{} - -pid_t PidFile::readPid(void) const { - pid_t pid; - int desired_read = sizeof(pid_t); - read(&pid, desired_read); - return pid; -} - -void PidFile::writePid(void) { - pid_t pid = getpid(); - int desired_write = sizeof(pid_t); - write(&pid, desired_write); -} - -}} /* namespace qpid::sys */ diff --git a/cpp/src/qpid/sys/posix/Mutex.cpp b/cpp/src/qpid/sys/posix/Mutex.cpp deleted file mode 100644 index 0e1f0d30c2..0000000000 --- a/cpp/src/qpid/sys/posix/Mutex.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace sys { - -/** - * Initialise a recursive mutex attr for use in creating mutexes later - * (we use pthread_once to make sure it is initialised exactly once) - */ - -namespace { -pthread_once_t onceControl = PTHREAD_ONCE_INIT; -pthread_mutexattr_t mutexattr; - -void initMutexattr() { - pthread_mutexattr_init(&mutexattr); - pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); -} -} - -const pthread_mutexattr_t* Mutex::getAttribute() { - pthread_once(&onceControl, initMutexattr); - return &mutexattr; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/posix/PidFile.h b/cpp/src/qpid/sys/posix/PidFile.h deleted file mode 100644 index fb19d407f4..0000000000 --- a/cpp/src/qpid/sys/posix/PidFile.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _sys_PidFile_h -#define _sys_PidFile_h - -/* - * - * Copyright (c) 2008 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/LockFile.h" - -#include "qpid/CommonImportExport.h" -#include "qpid/sys/IntegerTypes.h" - -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <string> - -namespace qpid { -namespace sys { - -class PidFile : public LockFile -{ -public: - QPID_COMMON_EXTERN PidFile(const std::string& path_, bool create); - - /** - * Read the process ID from the lock file. This method assumes that - * if there is a process ID in the file, it was written there by - * writePid(); thus, it's at the start of the file. - * - * Throws an exception if there is an error reading the file. - * - * @returns The stored process ID. No validity check is done on it. - */ - QPID_COMMON_EXTERN pid_t readPid(void) const; - - /** - * Write the current process's ID to the lock file. It's written at - * the start of the file and will overwrite any other content that - * may be in the file. - * - * Throws an exception if the write fails. - */ - QPID_COMMON_EXTERN void writePid(void); -}; - -}} /* namespace qpid::sys */ - -#endif /*!_sys_PidFile_h*/ diff --git a/cpp/src/qpid/sys/posix/PipeHandle.cpp b/cpp/src/qpid/sys/posix/PipeHandle.cpp deleted file mode 100755 index 4b19783338..0000000000 --- a/cpp/src/qpid/sys/posix/PipeHandle.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/sys/PipeHandle.h" -#include "qpid/sys/posix/check.h" -#include <unistd.h> -#include <fcntl.h> -#include <sys/socket.h> - -namespace qpid { -namespace sys { - -PipeHandle::PipeHandle(bool nonBlocking) { - - int pair[2]; - pair[0] = pair[1] = -1; - - if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) == -1) - throw qpid::Exception(QPID_MSG("Creation of pipe failed")); - - writeFd = pair[0]; - readFd = pair[1]; - - // Set the socket to non-blocking - if (nonBlocking) { - int flags = fcntl(readFd, F_GETFL); - fcntl(readFd, F_SETFL, flags | O_NONBLOCK); - } -} - -PipeHandle::~PipeHandle() { - close(readFd); - close(writeFd); -} - -int PipeHandle::read(void* buf, size_t bufSize) { - return ::read(readFd,buf,bufSize); -} - -int PipeHandle::write(const void* buf, size_t bufSize) { - return ::write(writeFd,buf,bufSize); -} - -int PipeHandle::getReadHandle() { - return readFd; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/posix/PollableCondition.cpp b/cpp/src/qpid/sys/posix/PollableCondition.cpp deleted file mode 100644 index b22a615a54..0000000000 --- a/cpp/src/qpid/sys/posix/PollableCondition.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef QPID_SYS_LINUX_POLLABLECONDITION_CPP -#define QPID_SYS_LINUX_POLLABLECONDITION_CPP - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/PollableCondition.h" -#include "qpid/sys/DispatchHandle.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include "qpid/Exception.h" - -#include <boost/bind.hpp> - -#include <unistd.h> -#include <fcntl.h> - -namespace qpid { -namespace sys { - -class PollableConditionPrivate : public sys::IOHandle { - friend class PollableCondition; - -private: - PollableConditionPrivate(const sys::PollableCondition::Callback& cb, - sys::PollableCondition& parent, - const boost::shared_ptr<sys::Poller>& poller); - ~PollableConditionPrivate(); - - void dispatch(sys::DispatchHandle& h); - void set(); - void clear(); - -private: - PollableCondition::Callback cb; - PollableCondition& parent; - boost::shared_ptr<sys::Poller> poller; - int writeFd; - std::auto_ptr<DispatchHandleRef> handle; -}; - -PollableConditionPrivate::PollableConditionPrivate( - const sys::PollableCondition::Callback& cb, - sys::PollableCondition& parent, - const boost::shared_ptr<sys::Poller>& poller -) : IOHandle(new sys::IOHandlePrivate), cb(cb), parent(parent) -{ - int fds[2]; - if (::pipe(fds) == -1) - throw ErrnoException(QPID_MSG("Can't create PollableCondition")); - impl->fd = fds[0]; - writeFd = fds[1]; - if (::fcntl(impl->fd, F_SETFL, O_NONBLOCK) == -1) - throw ErrnoException(QPID_MSG("Can't create PollableCondition")); - if (::fcntl(writeFd, F_SETFL, O_NONBLOCK) == -1) - throw ErrnoException(QPID_MSG("Can't create PollableCondition")); - handle.reset (new DispatchHandleRef( - *this, - boost::bind(&sys::PollableConditionPrivate::dispatch, this, _1), - 0, 0)); - handle->startWatch(poller); - handle->unwatch(); - - // Make the read FD readable - static const char dummy=0; - ssize_t n = ::write(writeFd, &dummy, 1); - if (n == -1 && errno != EAGAIN) - throw ErrnoException("Error setting PollableCondition"); -} - -PollableConditionPrivate::~PollableConditionPrivate() { - handle->stopWatch(); - close(writeFd); -} - -void PollableConditionPrivate::dispatch(sys::DispatchHandle&) { - cb(parent); -} - -void PollableConditionPrivate::set() { - handle->rewatch(); -} - -void PollableConditionPrivate::clear() { - handle->unwatch(); -} - - -PollableCondition::PollableCondition(const Callback& cb, - const boost::shared_ptr<sys::Poller>& poller -) : impl(new PollableConditionPrivate(cb, *this, poller)) -{ -} - -PollableCondition::~PollableCondition() -{ - delete impl; -} - -void PollableCondition::set() { impl->set(); } - -void PollableCondition::clear() { impl->clear(); } - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_LINUX_POLLABLECONDITION_CPP*/ diff --git a/cpp/src/qpid/sys/posix/Shlib.cpp b/cpp/src/qpid/sys/posix/Shlib.cpp deleted file mode 100644 index 3fb685d5b8..0000000000 --- a/cpp/src/qpid/sys/posix/Shlib.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Shlib.h" -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include <dlfcn.h> - - -namespace qpid { -namespace sys { - -void Shlib::load(const char* name) { - ::dlerror(); - handle = ::dlopen(name, RTLD_NOW); - const char* error = ::dlerror(); - if (error) { - throw Exception(QPID_MSG(error << ": " << name)); - } -} - -void Shlib::unload() { - if (handle) { - ::dlerror(); - ::dlclose(handle); - const char* error = ::dlerror(); - if (error) { - throw Exception(QPID_MSG(error)); - } - handle = 0; - } -} - -void* Shlib::getSymbol(const char* name) { - ::dlerror(); - void* sym = ::dlsym(handle, name); - const char* error = ::dlerror(); - if (error) - throw Exception(QPID_MSG(error << ": " << name)); - return sym; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/posix/Socket.cpp b/cpp/src/qpid/sys/posix/Socket.cpp deleted file mode 100644 index 3449a753e3..0000000000 --- a/cpp/src/qpid/sys/posix/Socket.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Socket.h" - -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" - -#include <fcntl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/errno.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <netdb.h> -#include <cstdlib> -#include <string.h> -#include <iostream> - -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> - -namespace qpid { -namespace sys { - -namespace { -std::string getName(int fd, bool local, bool includeService = false) -{ - ::sockaddr_storage name; // big enough for any socket address - ::socklen_t namelen = sizeof(name); - - int result = -1; - if (local) { - result = ::getsockname(fd, (::sockaddr*)&name, &namelen); - } else { - result = ::getpeername(fd, (::sockaddr*)&name, &namelen); - } - - QPID_POSIX_CHECK(result); - - char servName[NI_MAXSERV]; - char dispName[NI_MAXHOST]; - if (includeService) { - if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName), - servName, sizeof(servName), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw QPID_POSIX_ERROR(rc); - return std::string(dispName) + ":" + std::string(servName); - - } else { - if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName), 0, 0, NI_NUMERICHOST) != 0) - throw QPID_POSIX_ERROR(rc); - return dispName; - } -} - -std::string getService(int fd, bool local) -{ - ::sockaddr_storage name; // big enough for any socket address - ::socklen_t namelen = sizeof(name); - - int result = -1; - if (local) { - result = ::getsockname(fd, (::sockaddr*)&name, &namelen); - } else { - result = ::getpeername(fd, (::sockaddr*)&name, &namelen); - } - - QPID_POSIX_CHECK(result); - - char servName[NI_MAXSERV]; - if (int rc=::getnameinfo((::sockaddr*)&name, namelen, 0, 0, - servName, sizeof(servName), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw QPID_POSIX_ERROR(rc); - return servName; -} -} - -Socket::Socket() : - IOHandle(new IOHandlePrivate), - nonblocking(false), - nodelay(false) -{} - -Socket::Socket(IOHandlePrivate* h) : - IOHandle(h), - nonblocking(false), - nodelay(false) -{} - -void Socket::createSocket(const SocketAddress& sa) const -{ - int& socket = impl->fd; - if (socket != -1) Socket::close(); - int s = ::socket(getAddrInfo(sa).ai_family, getAddrInfo(sa).ai_socktype, 0); - if (s < 0) throw QPID_POSIX_ERROR(errno); - socket = s; - - try { - if (nonblocking) setNonblocking(); - if (nodelay) setTcpNoDelay(); - } catch (std::exception&) { - ::close(s); - socket = -1; - throw; - } -} - -void Socket::setTimeout(const Duration& interval) const -{ - const int& socket = impl->fd; - struct timeval tv; - toTimeval(tv, interval); - setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); -} - -void Socket::setNonblocking() const { - int& socket = impl->fd; - nonblocking = true; - if (socket != -1) { - QPID_POSIX_CHECK(::fcntl(socket, F_SETFL, O_NONBLOCK)); - } -} - -void Socket::setTcpNoDelay() const -{ - int& socket = impl->fd; - nodelay = true; - if (socket != -1) { - int flag = 1; - int result = setsockopt(impl->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)); - QPID_POSIX_CHECK(result); - } -} - -void Socket::connect(const std::string& host, uint16_t port) const -{ - SocketAddress sa(host, boost::lexical_cast<std::string>(port)); - connect(sa); -} - -void Socket::connect(const SocketAddress& addr) const -{ - connectname = addr.asString(); - - createSocket(addr); - - const int& socket = impl->fd; - // TODO the correct thing to do here is loop on failure until you've used all the returned addresses - if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) < 0) && - (errno != EINPROGRESS)) { - throw Exception(QPID_MSG(strError(errno) << ": " << connectname)); - } - // When connecting to a port on the same host which no longer has - // a process associated with it, the OS occasionally chooses the - // remote port (which is unoccupied) as the port to bind the local - // end of the socket, resulting in a "circular" connection. - // - // This seems like something the OS should prevent but I have - // confirmed that sporadic hangs in - // cluster_tests.LongTests.test_failover on RHEL5 are caused by - // such a circular connection. - // - // Raise an error if we see such a connection, since we know there is - // no listener on the peer address. - // - if (getLocalAddress() == getPeerAddress()) { - close(); - throw Exception(QPID_MSG("Connection refused: " << connectname)); - } -} - -void -Socket::close() const -{ - int& socket = impl->fd; - if (socket == -1) return; - if (::close(socket) < 0) throw QPID_POSIX_ERROR(errno); - socket = -1; -} - -int Socket::listen(uint16_t port, int backlog) const -{ - SocketAddress sa("", boost::lexical_cast<std::string>(port)); - return listen(sa, backlog); -} - -int Socket::listen(const SocketAddress& sa, int backlog) const -{ - createSocket(sa); - - const int& socket = impl->fd; - int yes=1; - QPID_POSIX_CHECK(setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes))); - - if (::bind(socket, getAddrInfo(sa).ai_addr, getAddrInfo(sa).ai_addrlen) < 0) - throw Exception(QPID_MSG("Can't bind to port " << sa.asString() << ": " << strError(errno))); - if (::listen(socket, backlog) < 0) - throw Exception(QPID_MSG("Can't listen on port " << sa.asString() << ": " << strError(errno))); - - struct sockaddr_in name; - socklen_t namelen = sizeof(name); - if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0) - throw QPID_POSIX_ERROR(errno); - - return ntohs(name.sin_port); -} - -Socket* Socket::accept() const -{ - int afd = ::accept(impl->fd, 0, 0); - if ( afd >= 0) - return new Socket(new IOHandlePrivate(afd)); - else if (errno == EAGAIN) - return 0; - else throw QPID_POSIX_ERROR(errno); -} - -int Socket::read(void *buf, size_t count) const -{ - return ::read(impl->fd, buf, count); -} - -int Socket::write(const void *buf, size_t count) const -{ - return ::write(impl->fd, buf, count); -} - -std::string Socket::getSockname() const -{ - return getName(impl->fd, true); -} - -std::string Socket::getPeername() const -{ - return getName(impl->fd, false); -} - -std::string Socket::getPeerAddress() const -{ - if (connectname.empty()) { - connectname = getName(impl->fd, false, true); - } - return connectname; -} - -std::string Socket::getLocalAddress() const -{ - return getName(impl->fd, true, true); -} - -uint16_t Socket::getLocalPort() const -{ - return std::atoi(getService(impl->fd, true).c_str()); -} - -uint16_t Socket::getRemotePort() const -{ - return std::atoi(getService(impl->fd, true).c_str()); -} - -int Socket::getError() const -{ - int result; - socklen_t rSize = sizeof (result); - - if (::getsockopt(impl->fd, SOL_SOCKET, SO_ERROR, &result, &rSize) < 0) - throw QPID_POSIX_ERROR(errno); - - return result; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/posix/SocketAddress.cpp b/cpp/src/qpid/sys/posix/SocketAddress.cpp deleted file mode 100644 index 8f5f29d793..0000000000 --- a/cpp/src/qpid/sys/posix/SocketAddress.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/SocketAddress.h" - -#include "qpid/sys/posix/check.h" - -#include <sys/socket.h> -#include <string.h> -#include <netdb.h> - -namespace qpid { -namespace sys { - -SocketAddress::SocketAddress(const std::string& host0, const std::string& port0) : - host(host0), - port(port0), - addrInfo(0) -{ -} - -SocketAddress::SocketAddress(const SocketAddress& sa) : - host(sa.host), - port(sa.port), - addrInfo(0) -{ -} - -SocketAddress& SocketAddress::operator=(const SocketAddress& sa) -{ - if (&sa != this) { - host = sa.host; - port = sa.port; - - if (addrInfo) { - ::freeaddrinfo(addrInfo); - addrInfo = 0; - } - } - return *this; -} - -SocketAddress::~SocketAddress() -{ - if (addrInfo) { - ::freeaddrinfo(addrInfo); - } -} - -std::string SocketAddress::asString() const -{ - return host + ":" + port; -} - -const ::addrinfo& getAddrInfo(const SocketAddress& sa) -{ - if (!sa.addrInfo) { - ::addrinfo hints; - ::memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; // Change this to support IPv6 - hints.ai_socktype = SOCK_STREAM; - - const char* node = 0; - if (sa.host.empty()) { - hints.ai_flags |= AI_PASSIVE; - } else { - node = sa.host.c_str(); - } - const char* service = sa.port.empty() ? "0" : sa.port.c_str(); - - int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo); - if (n != 0) - throw Exception(QPID_MSG("Cannot resolve " << sa.host << ": " << ::gai_strerror(n))); - } - - return *sa.addrInfo; -} - -}} diff --git a/cpp/src/qpid/sys/posix/StrError.cpp b/cpp/src/qpid/sys/posix/StrError.cpp deleted file mode 100644 index 633e20213c..0000000000 --- a/cpp/src/qpid/sys/posix/StrError.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/StrError.h" - -#include <string.h> - -namespace qpid { -namespace sys { - -std::string strError(int err) { - char buf[512] = "Unknown error"; -#ifdef _GNU_SOURCE - // GNU strerror_r returns the message - return ::strerror_r(err, buf, sizeof(buf)); -#else - // POSIX strerror_r doesn't return the buffer - ::strerror_r(err, buf, sizeof(buf)); - return std::string(buf); -#endif -} - -}} diff --git a/cpp/src/qpid/sys/posix/SystemInfo.cpp b/cpp/src/qpid/sys/posix/SystemInfo.cpp deleted file mode 100755 index a19ab6885c..0000000000 --- a/cpp/src/qpid/sys/posix/SystemInfo.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/SystemInfo.h" - -#include "qpid/sys/posix/check.h" - -#include <sys/ioctl.h> -#include <sys/utsname.h> -#include <sys/types.h> // For FreeBSD -#include <sys/socket.h> // For FreeBSD -#include <netinet/in.h> // For FreeBSD -#include <ifaddrs.h> -#include <iostream> -#include <fstream> -#include <sstream> -#include <netdb.h> - -#ifndef HOST_NAME_MAX -# define HOST_NAME_MAX 256 -#endif - -using namespace std; - -namespace qpid { -namespace sys { - -long SystemInfo::concurrency() { -#ifdef _SC_NPROCESSORS_ONLN // Linux specific. - return sysconf(_SC_NPROCESSORS_ONLN); -#else - return -1; -#endif -} - -bool SystemInfo::getLocalHostname (Address &address) { - char name[HOST_NAME_MAX]; - if (::gethostname(name, sizeof(name)) != 0) - return false; - address.host = name; - return true; -} - -static const string LOCALHOST("127.0.0.1"); -static const string TCP("tcp"); - -void SystemInfo::getLocalIpAddresses (uint16_t port, - std::vector<Address> &addrList) { - ::ifaddrs* ifaddr = 0; - QPID_POSIX_CHECK(::getifaddrs(&ifaddr)); - for (::ifaddrs* ifap = ifaddr; ifap != 0; ifap = ifap->ifa_next) { - if (ifap->ifa_addr == 0) continue; - - int family = ifap->ifa_addr->sa_family; - switch (family) { - case AF_INET: { - char dispName[NI_MAXHOST]; - int rc = ::getnameinfo( - ifap->ifa_addr, - (family == AF_INET) - ? sizeof(struct sockaddr_in) - : sizeof(struct sockaddr_in6), - dispName, sizeof(dispName), - 0, 0, NI_NUMERICHOST); - if (rc != 0) { - throw QPID_POSIX_ERROR(rc); - } - string addr(dispName); - if (addr != LOCALHOST) { - addrList.push_back(Address(TCP, addr, port)); - } - break; - } - // TODO: Url parsing currently can't cope with IPv6 addresses so don't return them - // when it can cope move this line to above "case AF_INET:" - case AF_INET6: - default: - continue; - } - } - freeifaddrs(ifaddr); - - if (addrList.empty()) { - addrList.push_back(Address(TCP, LOCALHOST, port)); - } -} - -void SystemInfo::getSystemId (std::string &osName, - std::string &nodeName, - std::string &release, - std::string &version, - std::string &machine) -{ - struct utsname _uname; - if (uname (&_uname) == 0) - { - osName = _uname.sysname; - nodeName = _uname.nodename; - release = _uname.release; - version = _uname.version; - machine = _uname.machine; - } -} - -uint32_t SystemInfo::getProcessId() -{ - return (uint32_t) ::getpid(); -} - -uint32_t SystemInfo::getParentProcessId() -{ - return (uint32_t) ::getppid(); -} - -// Linux specific (Solaris has quite different stuff in /proc) -string SystemInfo::getProcessName() -{ - string value; - - ifstream input("/proc/self/status"); - if (input.good()) { - while (!input.eof()) { - string key; - input >> key; - if (key == "Name:") { - input >> value; - break; - } - } - input.close(); - } - - return value; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/posix/Thread.cpp b/cpp/src/qpid/sys/posix/Thread.cpp deleted file mode 100644 index a1d6396763..0000000000 --- a/cpp/src/qpid/sys/posix/Thread.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Thread.h" - -#include "qpid/sys/Runnable.h" -#include "qpid/sys/posix/check.h" - -#include <pthread.h> - -namespace qpid { -namespace sys { - -namespace { -void* runRunnable(void* p) -{ - static_cast<Runnable*>(p)->run(); - return 0; -} -} - -class ThreadPrivate { -public: - pthread_t thread; - - ThreadPrivate(Runnable* runnable) { - QPID_POSIX_ASSERT_THROW_IF(::pthread_create(&thread, NULL, runRunnable, runnable)); - } - - ThreadPrivate() : thread(::pthread_self()) {} -}; - -Thread::Thread() {} - -Thread::Thread(Runnable* runnable) : impl(new ThreadPrivate(runnable)) {} - -Thread::Thread(Runnable& runnable) : impl(new ThreadPrivate(&runnable)) {} - -Thread::operator bool() { - return impl; -} - -bool Thread::operator==(const Thread& t) const { - return ::pthread_equal(impl->thread, t.impl->thread) != 0; -} - -bool Thread::operator!=(const Thread& t) const { - return !(*this==t); -} - -void Thread::join(){ - if (impl) { - QPID_POSIX_ASSERT_THROW_IF(::pthread_join(impl->thread, 0)); - } -} - -unsigned long Thread::logId() { - // This does need to be the C cast operator as - // pthread_t could be either a pointer or an integer - // and so we can't know static_cast<> or reinterpret_cast<> - return (unsigned long) ::pthread_self(); -} - -Thread Thread::current() { - Thread t; - t.impl.reset(new ThreadPrivate()); - return t; -} - -}} diff --git a/cpp/src/qpid/sys/posix/Time.cpp b/cpp/src/qpid/sys/posix/Time.cpp deleted file mode 100644 index 9661f0c5e8..0000000000 --- a/cpp/src/qpid/sys/posix/Time.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/posix/PrivatePosix.h" - -#include "qpid/sys/Time.h" -#include <ostream> -#include <time.h> -#include <stdio.h> -#include <sys/time.h> -#include <unistd.h> -#include <iomanip> - -namespace { -int64_t max_abstime() { return std::numeric_limits<int64_t>::max(); } -} - -namespace qpid { -namespace sys { - -AbsTime::AbsTime(const AbsTime& t, const Duration& d) : - timepoint(d == Duration::max() ? max_abstime() : t.timepoint+d.nanosecs) -{} - -AbsTime AbsTime::Epoch() { - AbsTime epoch; epoch.timepoint = 0; - return epoch; -} - -AbsTime AbsTime::FarFuture() { - AbsTime ff; ff.timepoint = max_abstime(); return ff; -} - -AbsTime AbsTime::now() { - struct timespec ts; - ::clock_gettime(CLOCK_REALTIME, &ts); - AbsTime time_now; - time_now.timepoint = toTime(ts).nanosecs; - return time_now; -} - -Duration::Duration(const AbsTime& start, const AbsTime& finish) : - nanosecs(finish.timepoint - start.timepoint) -{} - -struct timespec& toTimespec(struct timespec& ts, const Duration& t) { - ts.tv_sec = t / TIME_SEC; - ts.tv_nsec = t % TIME_SEC; - return ts; -} - -struct timeval& toTimeval(struct timeval& tv, const Duration& t) { - tv.tv_sec = t/TIME_SEC; - tv.tv_usec = (t%TIME_SEC)/TIME_USEC; - return tv; -} - -Duration toTime(const struct timespec& ts) { - return ts.tv_sec*TIME_SEC + ts.tv_nsec; -} - -std::ostream& operator<<(std::ostream& o, const Duration& d) { - return o << int64_t(d) << "ns"; -} - -namespace { -inline std::ostream& outputFormattedTime(std::ostream& o, const ::time_t* time) { - ::tm timeinfo; - char time_string[100]; - ::strftime(time_string, 100, - "%Y-%m-%d %H:%M:%S", - localtime_r(time, &timeinfo)); - return o << time_string; -} -} - -std::ostream& operator<<(std::ostream& o, const AbsTime& t) { - ::time_t rawtime(t.timepoint/TIME_SEC); - return outputFormattedTime(o, &rawtime); -} - -void outputFormattedNow(std::ostream& o) { - ::time_t rawtime; - ::time(&rawtime); - outputFormattedTime(o, &rawtime); - o << " "; -} - -void outputHiresNow(std::ostream& o) { - ::timespec time; - ::clock_gettime(CLOCK_REALTIME, &time); - o << time.tv_sec << "." << std::setw(9) << std::setfill('0') << time.tv_nsec << "s "; -} - -void sleep(int secs) { - ::sleep(secs); -} - -void usleep(uint64_t usecs) { - ::usleep(usecs); -} - -}} diff --git a/cpp/src/qpid/sys/rdma/RdmaClient.cpp b/cpp/src/qpid/sys/rdma/RdmaClient.cpp deleted file mode 100644 index 38e9b59541..0000000000 --- a/cpp/src/qpid/sys/rdma/RdmaClient.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/rdma/RdmaIO.h" -#include "qpid/sys/rdma/rdma_exception.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" - -#include <netdb.h> -#include <arpa/inet.h> - -#include <vector> -#include <string> -#include <iostream> -#include <algorithm> -#include <cmath> -#include <boost/bind.hpp> - -using std::vector; -using std::string; -using std::cout; -using std::cerr; -using std::copy; -using std::rand; - -using qpid::sys::Thread; -using qpid::sys::Poller; -using qpid::sys::Dispatcher; -using qpid::sys::SocketAddress; -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::sys::TIME_SEC; -using qpid::sys::TIME_INFINITE; - -namespace qpid { -namespace tests { - -// count of messages -int64_t smsgs = 0; -int64_t sbytes = 0; -int64_t rmsgs = 0; -int64_t rbytes = 0; - -int target = 1000000; -int msgsize = 200; -AbsTime startTime; -Duration sendingDuration(TIME_INFINITE); -Duration fullTestDuration(TIME_INFINITE); - -// Random generator -// This is an RNG designed by George Marsaglia see http://en.wikipedia.org/wiki/Xorshift -class Xor128Generator { - uint32_t x; - uint32_t y; - uint32_t z; - uint32_t w; - -public: - Xor128Generator() : - x(123456789),y(362436069),z(521288629),w(88675123) - {++(*this);} - - Xor128Generator& operator++() { - uint32_t t = x ^ (x << 11); - x = y; y = z; z = w; - w = w ^ (w >> 19) ^ t ^ (t >> 8); - return *this; - } - - uint32_t operator*() { - return w; - } -}; - -Xor128Generator output; -Xor128Generator input; - -void write(Rdma::AsynchIO& aio) { - while (aio.writable() && smsgs < target) { - Rdma::Buffer* b = aio.getSendBuffer(); - if (!b) break; - b->dataCount(msgsize); - uint32_t* ip = reinterpret_cast<uint32_t*>(b->bytes()); - uint32_t* lip = ip + b->dataCount() / sizeof(uint32_t); - while (ip != lip) {*ip++ = *output; ++output;} - aio.queueWrite(b); - ++smsgs; - sbytes += msgsize; - } -} - -void dataError(Rdma::AsynchIO&) { - cout << "Data error:\n"; -} - -void data(Poller::shared_ptr p, Rdma::AsynchIO& aio, Rdma::Buffer* b) { - ++rmsgs; - rbytes += b->dataCount(); - - // Check message is unaltered - bool match = true; - uint32_t* ip = reinterpret_cast<uint32_t*>(b->bytes()); - uint32_t* lip = ip + b->dataCount() / sizeof(uint32_t); - while (ip != lip) { if (*ip++ != *input) {match = false; break;} ++input;} - if (!match) { - cout << "Data doesn't match: at msg " << rmsgs << " byte " << rbytes-b->dataCount() << " (ish)\n"; - exit(1); - } - - // When all messages have been recvd stop - if (rmsgs < target) { - write(aio); - } else { - fullTestDuration = std::min(fullTestDuration, Duration(startTime, AbsTime::now())); - if (aio.incompletedWrites() == 0) - p->shutdown(); - } -} - -void full(Rdma::AsynchIO& a, Rdma::Buffer* b) { - // Warn as we shouldn't get here anymore - cerr << "!"; - - // Don't need to keep buffer just adjust the counts - --smsgs; - sbytes -= b->dataCount(); - - // Give buffer back - a.returnSendBuffer(b); -} - -void idle(Poller::shared_ptr p, Rdma::AsynchIO& aio) { - if (smsgs < target) { - write(aio); - } else { - sendingDuration = std::min(sendingDuration, Duration(startTime, AbsTime::now())); - if (rmsgs >= target && aio.incompletedWrites() == 0) - p->shutdown(); - } -} - -void drained(Rdma::AsynchIO&) { - cout << "Drained:\n"; -} - -void connected(Poller::shared_ptr poller, Rdma::Connection::intrusive_ptr& ci, const Rdma::ConnectionParams& cp) { - cout << "Connected\n"; - Rdma::QueuePair::intrusive_ptr q = ci->getQueuePair(); - - Rdma::AsynchIO* aio = new Rdma::AsynchIO(ci->getQueuePair(), - cp.rdmaProtocolVersion, - cp.maxRecvBufferSize, cp.initialXmitCredit , Rdma::DEFAULT_WR_ENTRIES, - boost::bind(&data, poller, _1, _2), - boost::bind(&idle, poller, _1), - &full, - dataError); - - startTime = AbsTime::now(); - write(*aio); - - aio->start(poller); -} - -void disconnected(boost::shared_ptr<Poller> p, Rdma::Connection::intrusive_ptr&) { - cout << "Disconnected\n"; - p->shutdown(); -} - -void connectionError(boost::shared_ptr<Poller> p, Rdma::Connection::intrusive_ptr&, const Rdma::ErrorType) { - cout << "Connection error\n"; - p->shutdown(); -} - -void rejected(boost::shared_ptr<Poller> p, Rdma::Connection::intrusive_ptr&, const Rdma::ConnectionParams&) { - cout << "Connection rejected\n"; - p->shutdown(); -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char* argv[]) { - vector<string> args(&argv[0], &argv[argc]); - - string host = args[1]; - string port = (args.size() < 3) ? "20079" : args[2]; - - if (args.size() > 3) - msgsize = atoi(args[3].c_str()); - cout << "Message size: " << msgsize << "\n"; - - try { - boost::shared_ptr<Poller> p(new Poller()); - - Rdma::Connector c( - Rdma::ConnectionParams(msgsize, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(&connected, p, _1, _2), - boost::bind(&connectionError, p, _1, _2), - boost::bind(&disconnected, p, _1), - boost::bind(&rejected, p, _1, _2)); - - SocketAddress sa(host, port); - cout << "Connecting to: " << sa.asString() <<"\n"; - c.start(p, sa); - - // The poller loop blocks all signals so run in its own thread - Thread t(*p); - t.join(); - } catch (Rdma::Exception& e) { - int err = e.getError(); - cerr << "Error: " << e.what() << "(" << err << ")\n"; - } - - cout - << "Sent: " << smsgs - << "msgs (" << sbytes - << "bytes) in: " << double(sendingDuration)/TIME_SEC - << "s: " << double(smsgs)*TIME_SEC/sendingDuration - << "msgs/s(" << double(sbytes)*TIME_SEC/sendingDuration - << "bytes/s)\n"; - cout - << "Recd: " << rmsgs - << "msgs (" << rbytes - << "bytes) in: " << double(fullTestDuration)/TIME_SEC - << "s: " << double(rmsgs)*TIME_SEC/fullTestDuration - << "msgs/s(" << double(rbytes)*TIME_SEC/fullTestDuration - << "bytes/s)\n"; - -} diff --git a/cpp/src/qpid/sys/rdma/RdmaIO.cpp b/cpp/src/qpid/sys/rdma/RdmaIO.cpp deleted file mode 100644 index 78bcdec68e..0000000000 --- a/cpp/src/qpid/sys/rdma/RdmaIO.cpp +++ /dev/null @@ -1,720 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/rdma/RdmaIO.h" - -#include "qpid/log/Statement.h" - -#include <string> -#include <boost/bind.hpp> - -using qpid::sys::SocketAddress; -using qpid::sys::DispatchHandle; -using qpid::sys::Poller; -using qpid::sys::ScopedLock; -using qpid::sys::Mutex; - -namespace Rdma { - // Set packing as these are 'on the wire' structures -# pragma pack(push, 1) - - // Header structure for each transmitted frame - struct FrameHeader { - const static uint32_t FlagsMask = 0xf0000000; - uint32_t data; // written in network order - - FrameHeader() {} - FrameHeader(uint32_t credit, uint32_t flags = 0) { - data = htonl((credit & ~FlagsMask) | (flags & FlagsMask)); - } - - uint32_t credit() const { - return ntohl(data) & ~FlagsMask; - } - - uint32_t flags() const { - return ntohl(data) & FlagsMask; - } - }; - - const size_t FrameHeaderSize = sizeof(FrameHeader); - - // Structure for Connection Parameters on the network - // - // The original version (now called 0) of these parameters had a couple of mistakes: - // * No way to version the protocol (need to introduce a new protocol for iWarp) - // * Used host order int32 (but only deployed on LE archs as far as we know) - // so effectively was LE on the wire which is the opposite of network order. - // - // Fortunately the values sent were sufficiently restricted that a 16 bit short could - // be carved out to indicate the protocol version as these bits were always sent as 0. - // - // So the current version of parameters uses the last 2 bytes to indicate the protocol - // version, if this is 0 then we interpret the rest of the struct without byte swapping - // to remain compatible with the previous protocol. - struct NConnectionParams { - uint32_t maxRecvBufferSize; - uint16_t initialXmitCredit; - uint16_t rdmaProtocolVersion; - - NConnectionParams(const ConnectionParams& c) : - maxRecvBufferSize(c.rdmaProtocolVersion ? htonl(c.maxRecvBufferSize) : c.maxRecvBufferSize), - initialXmitCredit(c.rdmaProtocolVersion ? htons(c.initialXmitCredit) : c.initialXmitCredit), - // 0 is the same with/without byteswapping! - rdmaProtocolVersion(htons(c.rdmaProtocolVersion)) - {} - - operator ConnectionParams() const { - return - ConnectionParams( - rdmaProtocolVersion ? ntohl(maxRecvBufferSize) : maxRecvBufferSize, - rdmaProtocolVersion ? ntohs(initialXmitCredit) : initialXmitCredit, - ntohs(rdmaProtocolVersion)); - } - }; -# pragma pack(pop) - - class IOException : public std::exception { - std::string s; - - public: - IOException(std::string s0): s(s0) {} - ~IOException() throw() {} - - const char* what() const throw() { - return s.c_str(); - } - }; - - AsynchIO::AsynchIO( - QueuePair::intrusive_ptr q, - int version, - int size, - int xCredit, - int rCount, - ReadCallback rc, - IdleCallback ic, - FullCallback fc, - ErrorCallback ec - ) : - protocolVersion(version), - bufferSize(size), - recvCredit(0), - xmitCredit(xCredit), - recvBufferCount(rCount), - xmitBufferCount(xCredit), - outstandingWrites(0), - draining(false), - state(IDLE), - qp(q), - dataHandle(*qp, boost::bind(&AsynchIO::dataEvent, this), 0, 0), - readCallback(rc), - idleCallback(ic), - fullCallback(fc), - errorCallback(ec), - pendingWriteAction(boost::bind(&AsynchIO::writeEvent, this)) - { - if (protocolVersion > maxSupportedProtocolVersion) - throw IOException("Unsupported Rdma Protocol"); - qp->nonblocking(); - qp->notifyRecv(); - qp->notifySend(); - - // Prepost recv buffers before we go any further - qp->allocateRecvBuffers(recvBufferCount, bufferSize+FrameHeaderSize); - - // Create xmit buffers, reserve space for frame header. - qp->createSendBuffers(xmitBufferCount, bufferSize, FrameHeaderSize); - } - - AsynchIO::~AsynchIO() { - // Warn if we are deleting whilst there are still unreclaimed write buffers - if ( outstandingWrites>0 ) - QPID_LOG(error, "RDMA: qp=" << qp << ": Deleting queue before all write buffers finished"); - - // Turn off callbacks if necessary (before doing the deletes) - if (state != STOPPED) { - QPID_LOG(error, "RDMA: qp=" << qp << ": Deleting queue whilst not shutdown"); - dataHandle.stopWatch(); - } - // TODO: It might turn out to be more efficient in high connection loads to reuse the - // buffers rather than having to reregister them all the time (this would be straightforward if all - // connections haver the same buffer size and harder otherwise) - } - - void AsynchIO::start(Poller::shared_ptr poller) { - dataHandle.startWatch(poller); - } - - // State constraints - // On entry: None - // On exit: STOPPED - // Mark for deletion/Delete this object when we have no outstanding writes - void AsynchIO::stop(NotifyCallback nc) { - ScopedLock<Mutex> l(stateLock); - state = STOPPED; - notifyCallback = nc; - dataHandle.call(boost::bind(&AsynchIO::doStoppedCallback, this)); - } - - namespace { - void requestedCall(AsynchIO* aio, AsynchIO::RequestCallback callback) { - assert(callback); - callback(*aio); - } - } - - void AsynchIO::requestCallback(RequestCallback callback) { - // TODO creating a function object every time isn't all that - // efficient - if this becomes heavily used do something better (what?) - assert(callback); - dataHandle.call(boost::bind(&requestedCall, this, callback)); - } - - // Mark writing closed (so we don't accept any more writes or make any idle callbacks) - void AsynchIO::drainWriteQueue(NotifyCallback nc) { - draining = true; - notifyCallback = nc; - } - - void AsynchIO::queueBuffer(Buffer* buff, int credit) { - switch (protocolVersion) { - case 0: - if (!buff) { - Buffer* ob = getSendBuffer(); - // Have to send something as adapters hate it when you try to transfer 0 bytes - *reinterpret_cast< uint32_t* >(ob->bytes()) = htonl(credit); - ob->dataCount(sizeof(uint32_t)); - qp->postSend(credit | IgnoreData, ob); - } else if (credit > 0) { - qp->postSend(credit, buff); - } else { - qp->postSend(buff); - } - break; - case 1: - if (!buff) - buff = getSendBuffer(); - // Add FrameHeader after frame data - FrameHeader header(credit); - assert(buff->dataCount() <= buff->byteCount()); // ensure app data doesn't impinge on reserved space. - ::memcpy(buff->bytes()+buff->dataCount(), &header, FrameHeaderSize); - buff->dataCount(buff->dataCount()+FrameHeaderSize); - qp->postSend(buff); - break; - } - } - - Buffer* AsynchIO::extractBuffer(const QueuePairEvent& e) { - Buffer* b = e.getBuffer(); - switch (protocolVersion) { - case 0: { - bool dataPresent = true; - // Get our xmitCredit if it was sent - if (e.immPresent() ) { - assert(xmitCredit>=0); - xmitCredit += (e.getImm() & ~FlagsMask); - dataPresent = ((e.getImm() & IgnoreData) == 0); - assert(xmitCredit>0); - } - if (!dataPresent) { - b->dataCount(0); - } - break; - } - case 1: - b->dataCount(b->dataCount()-FrameHeaderSize); - FrameHeader header; - ::memcpy(&header, b->bytes()+b->dataCount(), FrameHeaderSize); - assert(xmitCredit>=0); - xmitCredit += header.credit(); - assert(xmitCredit>=0); - break; - } - - return b; - } - - void AsynchIO::queueWrite(Buffer* buff) { - // Make sure we don't overrun our available buffers - // either at our end or the known available at the peers end - if (writable()) { - // TODO: We might want to batch up sending credit - int creditSent = recvCredit & ~FlagsMask; - queueBuffer(buff, creditSent); - recvCredit -= creditSent; - ++outstandingWrites; - --xmitCredit; - assert(xmitCredit>=0); - } else { - if (fullCallback) { - fullCallback(*this, buff); - } else { - QPID_LOG(error, "RDMA: qp=" << qp << ": Write queue full, but no callback, throwing buffer away"); - returnSendBuffer(buff); - } - } - } - - // State constraints - // On entry: None - // On exit: NOTIFY_PENDING || STOPPED - void AsynchIO::notifyPendingWrite() { - ScopedLock<Mutex> l(stateLock); - switch (state) { - case IDLE: - dataHandle.call(pendingWriteAction); - // Fall Thru - case NOTIFY: - state = NOTIFY_PENDING; - break; - case NOTIFY_PENDING: - case STOPPED: - break; - } - } - - // State constraints - // On entry: IDLE || STOPPED - // On exit: IDLE || STOPPED - void AsynchIO::dataEvent() { - { - ScopedLock<Mutex> l(stateLock); - - if (state == STOPPED) return; - - state = NOTIFY_PENDING; - } - processCompletions(); - - writeEvent(); - } - - // State constraints - // On entry: NOTIFY_PENDING || STOPPED - // On exit: IDLE || STOPPED - void AsynchIO::writeEvent() { - State newState; - do { - { - ScopedLock<Mutex> l(stateLock); - - switch (state) { - case STOPPED: - return; - default: - state = NOTIFY; - } - } - - doWriteCallback(); - - { - ScopedLock<Mutex> l(stateLock); - - newState = state; - switch (newState) { - case NOTIFY_PENDING: - case STOPPED: - break; - default: - state = IDLE; - } - } - } while (newState == NOTIFY_PENDING); - } - - void AsynchIO::processCompletions() { - QueuePair::intrusive_ptr q = qp->getNextChannelEvent(); - - // Re-enable notification for queue: - // This needs to happen before we could do anything that could generate more work completion - // events (ie the callbacks etc. in the following). - // This can't make us reenter this code as the handle attached to the completion queue will still be - // disabled by the poller until we leave this code - qp->notifyRecv(); - qp->notifySend(); - - int recvEvents = 0; - int sendEvents = 0; - - // If no event do nothing - if (!q) - return; - - assert(q == qp); - - // Repeat until no more events - do { - QueuePairEvent e(qp->getNextEvent()); - if (!e) - break; - - ::ibv_wc_status status = e.getEventStatus(); - if (status != IBV_WC_SUCCESS) { - // Need special check for IBV_WC_WR_FLUSH_ERR here - // we will get this for every send/recv queue entry that was pending - // when disconnected, these aren't real errors and mostly need to be ignored - if (status == IBV_WC_WR_FLUSH_ERR) { - QueueDirection dir = e.getDirection(); - if (dir == SEND) { - Buffer* b = e.getBuffer(); - ++sendEvents; - returnSendBuffer(b); - --outstandingWrites; - } else { - ++recvEvents; - } - continue; - } - errorCallback(*this); - // TODO: Probably need to flush queues at this point - return; - } - - // Test if recv (or recv with imm) - //::ibv_wc_opcode eventType = e.getEventType(); - QueueDirection dir = e.getDirection(); - if (dir == RECV) { - ++recvEvents; - - Buffer* b = extractBuffer(e); - - // if there was no data sent then the message was only to update our credit - if ( b->dataCount() > 0 ) { - readCallback(*this, b); - } - - // At this point the buffer has been consumed so put it back on the recv queue - // TODO: Is this safe to do if the connection is disconnected already? - qp->postRecv(b); - - // Received another message - ++recvCredit; - - // Send recvCredit if it is large enough (it will have got this large because we've not sent anything recently) - if (recvCredit > recvBufferCount/2) { - // TODO: This should use RDMA write with imm as there might not ever be a buffer to receive this message - // but this is a little unlikely, as to get in this state we have to have received messages without sending any - // for a while so its likely we've received an credit update from the far side. - if (writable()) { - int creditSent = recvCredit & ~FlagsMask; - queueBuffer(0, creditSent); - recvCredit -= creditSent; - ++outstandingWrites; - --xmitCredit; - assert(xmitCredit>=0); - } else { - QPID_LOG(warning, "RDMA: qp=" << qp << ": Unable to send unsolicited credit"); - } - } - } else { - Buffer* b = e.getBuffer(); - ++sendEvents; - returnSendBuffer(b); - --outstandingWrites; - } - } while (true); - - // Not sure if this is expected or not - if (recvEvents == 0 && sendEvents == 0) { - QPID_LOG(debug, "RDMA: qp=" << qp << ": Got channel event with no recv/send completions"); - } - } - - void AsynchIO::doWriteCallback() { - // TODO: maybe don't call idle unless we're low on write buffers - // Keep on calling the idle routine as long as we are writable and we got something to write last call - - // Do callback even if there are no available free buffers as the application itself might be - // holding onto buffers - while (writable()) { - int xc = xmitCredit; - idleCallback(*this); - // Check whether we actually wrote anything - if (xmitCredit == xc) { - QPID_LOG(debug, "RDMA: qp=" << qp << ": Called for data, but got none: xmitCredit=" << xmitCredit); - return; - } - } - - checkDrained(); - } - - void AsynchIO::checkDrained() { - // If we've got all the write confirmations and we're draining - // We might get deleted in the drained callback so return immediately - if (draining) { - if (outstandingWrites == 0) { - draining = false; - NotifyCallback nc; - nc.swap(notifyCallback); - nc(*this); - } - return; - } - } - - void AsynchIO::doStoppedCallback() { - // Ensure we can't get any more callbacks (except for the stopped callback) - dataHandle.stopWatch(); - - NotifyCallback nc; - nc.swap(notifyCallback); - nc(*this); - } - - ConnectionManager::ConnectionManager( - ErrorCallback errc, - DisconnectedCallback dc - ) : - state(IDLE), - ci(Connection::make()), - handle(*ci, boost::bind(&ConnectionManager::event, this, _1), 0, 0), - errorCallback(errc), - disconnectedCallback(dc) - { - QPID_LOG(debug, "RDMA: ci=" << ci << ": Creating ConnectionManager"); - ci->nonblocking(); - } - - ConnectionManager::~ConnectionManager() - { - QPID_LOG(debug, "RDMA: ci=" << ci << ": Deleting ConnectionManager"); - } - - void ConnectionManager::start(Poller::shared_ptr poller, const qpid::sys::SocketAddress& addr) { - startConnection(ci, addr); - handle.startWatch(poller); - } - - void ConnectionManager::doStoppedCallback() { - // Ensure we can't get any more callbacks (except for the stopped callback) - handle.stopWatch(); - - NotifyCallback nc; - nc.swap(notifyCallback); - nc(*this); - } - - void ConnectionManager::stop(NotifyCallback nc) { - state = STOPPED; - notifyCallback = nc; - handle.call(boost::bind(&ConnectionManager::doStoppedCallback, this)); - } - - void ConnectionManager::event(DispatchHandle&) { - if (state.get() == STOPPED) return; - connectionEvent(ci); - } - - Listener::Listener( - const ConnectionParams& cp, - EstablishedCallback ec, - ErrorCallback errc, - DisconnectedCallback dc, - ConnectionRequestCallback crc - ) : - ConnectionManager(errc, dc), - checkConnectionParams(cp), - connectionRequestCallback(crc), - establishedCallback(ec) - { - } - - void Listener::startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr) { - ci->bind(addr); - ci->listen(); - } - - namespace { - const int64_t PoisonContext = -1; - } - - void Listener::connectionEvent(Connection::intrusive_ptr ci) { - ConnectionEvent e(ci->getNextEvent()); - - // If (for whatever reason) there was no event do nothing - if (!e) - return; - - // Important documentation ommision the new rdma_cm_id - // you get from CONNECT_REQUEST has the same context info - // as its parent listening rdma_cm_id - ::rdma_cm_event_type eventType = e.getEventType(); - ::rdma_conn_param conn_param = e.getConnectionParam(); - Rdma::Connection::intrusive_ptr id = e.getConnection(); - - // Check for previous disconnection (it appears that you actually can get connection - // request events after a disconnect event in rare circumstances) - if (reinterpret_cast<int64_t>(id->getContext<void*>())==PoisonContext) - return; - - switch (eventType) { - case RDMA_CM_EVENT_CONNECT_REQUEST: { - // Make sure peer has sent params we can use - if (!conn_param.private_data || conn_param.private_data_len < sizeof(NConnectionParams)) { - QPID_LOG(warning, "Rdma: rejecting connection attempt: unusable connection parameters"); - id->reject(); - break; - } - - const NConnectionParams* rcp = static_cast<const NConnectionParams*>(conn_param.private_data); - ConnectionParams cp = *rcp; - - // Reject if requested msg size is bigger than we allow - if ( - cp.maxRecvBufferSize > checkConnectionParams.maxRecvBufferSize || - cp.initialXmitCredit > checkConnectionParams.initialXmitCredit - ) { - QPID_LOG(warning, "Rdma: rejecting connection attempt: connection parameters out of range: (" - << cp.maxRecvBufferSize << ">" << checkConnectionParams.maxRecvBufferSize << " || " - << cp.initialXmitCredit << ">" << checkConnectionParams.initialXmitCredit - << ")"); - id->reject(&checkConnectionParams); - break; - } - - bool accept = true; - if (connectionRequestCallback) - accept = connectionRequestCallback(id, cp); - - if (accept) { - // Accept connection - cp.initialXmitCredit = checkConnectionParams.initialXmitCredit; - id->accept(conn_param, rcp); - } else { - // Reject connection - QPID_LOG(warning, "Rdma: rejecting connection attempt: application policy"); - id->reject(); - } - break; - } - case RDMA_CM_EVENT_ESTABLISHED: - establishedCallback(id); - break; - case RDMA_CM_EVENT_DISCONNECTED: - disconnectedCallback(id); - // Poison the id context so that we do no more callbacks on it - id->removeContext(); - id->addContext(reinterpret_cast<void*>(PoisonContext)); - break; - case RDMA_CM_EVENT_CONNECT_ERROR: - errorCallback(id, CONNECT_ERROR); - break; - default: - // Unexpected response - errorCallback(id, UNKNOWN); - //std::cerr << "Warning: unexpected response to listen - " << eventType << "\n"; - } - } - - Connector::Connector( - const ConnectionParams& cp, - ConnectedCallback cc, - ErrorCallback errc, - DisconnectedCallback dc, - RejectedCallback rc - ) : - ConnectionManager(errc, dc), - connectionParams(cp), - rejectedCallback(rc), - connectedCallback(cc) - { - } - - void Connector::startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr) { - ci->resolve_addr(addr); - } - - void Connector::connectionEvent(Connection::intrusive_ptr ci) { - ConnectionEvent e(ci->getNextEvent()); - - // If (for whatever reason) there was no event do nothing - if (!e) - return; - - ::rdma_cm_event_type eventType = e.getEventType(); - ::rdma_conn_param conn_param = e.getConnectionParam(); - Rdma::Connection::intrusive_ptr id = e.getConnection(); - switch (eventType) { - case RDMA_CM_EVENT_ADDR_RESOLVED: - // RESOLVE_ADDR - ci->resolve_route(); - break; - case RDMA_CM_EVENT_ADDR_ERROR: - // RESOLVE_ADDR - errorCallback(ci, ADDR_ERROR); - break; - case RDMA_CM_EVENT_ROUTE_RESOLVED: { - // RESOLVE_ROUTE: - NConnectionParams rcp(connectionParams); - ci->connect(&rcp); - break; - } - case RDMA_CM_EVENT_ROUTE_ERROR: - // RESOLVE_ROUTE: - errorCallback(ci, ROUTE_ERROR); - break; - case RDMA_CM_EVENT_CONNECT_ERROR: - // CONNECTING - errorCallback(ci, CONNECT_ERROR); - break; - case RDMA_CM_EVENT_UNREACHABLE: - // CONNECTING - errorCallback(ci, UNREACHABLE); - break; - case RDMA_CM_EVENT_REJECTED: { - // CONNECTING - - // We can get this event if our peer is not running on the other side - // in this case we could get nearly anything in the private data: - // From private_data == 0 && private_data_len == 0 (Chelsio iWarp) - // to 148 bytes of zeros (Mellanox IB) - // - // So assume that if the the private data is absent or not the size of - // the connection parameters it isn't valid - ConnectionParams cp(0, 0, 0); - if (conn_param.private_data && conn_param.private_data_len == sizeof(NConnectionParams)) { - // Extract private data from event - const NConnectionParams* rcp = static_cast<const NConnectionParams*>(conn_param.private_data); - cp = *rcp; - } - rejectedCallback(ci, cp); - break; - } - case RDMA_CM_EVENT_ESTABLISHED: { - // CONNECTING - // Extract private data from event - assert(conn_param.private_data && conn_param.private_data_len >= sizeof(NConnectionParams)); - const NConnectionParams* rcp = static_cast<const NConnectionParams*>(conn_param.private_data); - ConnectionParams cp = *rcp; - connectedCallback(ci, cp); - break; - } - case RDMA_CM_EVENT_DISCONNECTED: - // ESTABLISHED - disconnectedCallback(ci); - break; - default: - QPID_LOG(warning, "RDMA: Unexpected event in connect: " << eventType); - } - } -} diff --git a/cpp/src/qpid/sys/rdma/RdmaIO.h b/cpp/src/qpid/sys/rdma/RdmaIO.h deleted file mode 100644 index ec9caaf08d..0000000000 --- a/cpp/src/qpid/sys/rdma/RdmaIO.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef Rdma_Acceptor_h -#define Rdma_Acceptor_h - -#include "qpid/sys/rdma/rdma_wrap.h" - -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/DispatchHandle.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/SocketAddress.h" - -#include <netinet/in.h> - -#include <boost/function.hpp> - -namespace Rdma { - - class Connection; - - class AsynchIO - { - typedef boost::function1<void, AsynchIO&> ErrorCallback; - typedef boost::function2<void, AsynchIO&, Buffer*> ReadCallback; - typedef boost::function1<void, AsynchIO&> IdleCallback; - typedef boost::function2<void, AsynchIO&, Buffer*> FullCallback; - typedef boost::function1<void, AsynchIO&> NotifyCallback; - - int protocolVersion; - int bufferSize; - int recvCredit; - int xmitCredit; - int recvBufferCount; - int xmitBufferCount; - int outstandingWrites; - bool draining; - enum State {IDLE, NOTIFY, NOTIFY_PENDING, STOPPED}; - State state; - qpid::sys::Mutex stateLock; - QueuePair::intrusive_ptr qp; - qpid::sys::DispatchHandleRef dataHandle; - - ReadCallback readCallback; - IdleCallback idleCallback; - FullCallback fullCallback; - ErrorCallback errorCallback; - NotifyCallback notifyCallback; - qpid::sys::DispatchHandle::Callback pendingWriteAction; - - public: - typedef boost::function1<void, AsynchIO&> RequestCallback; - - // TODO: Instead of specifying a buffer size specify the amount of memory the AsynchIO class can use - // for buffers both read and write (allocate half to each up front) and fail if we cannot allocate that much - // locked memory - AsynchIO( - QueuePair::intrusive_ptr q, - int version, - int size, - int xCredit, - int rCount, - ReadCallback rc, - IdleCallback ic, - FullCallback fc, - ErrorCallback ec - ); - ~AsynchIO(); - - void start(qpid::sys::Poller::shared_ptr poller); - bool writable() const; - void queueWrite(Buffer* buff); - void notifyPendingWrite(); - void drainWriteQueue(NotifyCallback); - void stop(NotifyCallback); - void requestCallback(RequestCallback); - int incompletedWrites() const; - Buffer* getSendBuffer(); - void returnSendBuffer(Buffer*); - - private: - const static int maxSupportedProtocolVersion = 1; - - // Constants for the peer-peer command messages - // These are sent in the high bits if the imm data of an rdma message - // The low bits are used to send the credit - const static int FlagsMask = 0xF0000000; // Mask for all flag bits - be sure to update this if you add more command bits - const static int IgnoreData = 0x10000000; // Message contains no application data - - void dataEvent(); - void writeEvent(); - void processCompletions(); - void doWriteCallback(); - void checkDrained(); - void doStoppedCallback(); - - void queueBuffer(Buffer* buff, int credit); - Buffer* extractBuffer(const QueuePairEvent& e); - }; - - // We're only writable if: - // * not draining write queue - // * we've got space in the transmit queue - // * we've got credit to transmit - // * if there's only 1 transmit credit we must send some credit - inline bool AsynchIO::writable() const { - assert(xmitCredit>=0); - return !draining && - outstandingWrites < xmitBufferCount && - xmitCredit > 0 && - ( xmitCredit > 1 || recvCredit > 0); - } - - inline int AsynchIO::incompletedWrites() const { - return outstandingWrites; - } - - inline Buffer* AsynchIO::getSendBuffer() { - return qp->getSendBuffer(); - } - - inline void AsynchIO::returnSendBuffer(Buffer* b) { - qp->returnSendBuffer(b); - } - - // These are the parameters necessary to start the conversation - // * Each peer HAS to allocate buffers of the size of the maximum receive from its peer - // * Each peer HAS to know the initial "credit" it has for transmitting to its peer - struct ConnectionParams { - uint32_t maxRecvBufferSize; - uint16_t initialXmitCredit; - uint16_t rdmaProtocolVersion; - - // Default to protocol version 1 - ConnectionParams(uint32_t s, uint16_t c, uint16_t v = 1) : - maxRecvBufferSize(s), - initialXmitCredit(c), - rdmaProtocolVersion(v) - {} - }; - - enum ErrorType { - ADDR_ERROR, - ROUTE_ERROR, - CONNECT_ERROR, - UNREACHABLE, - UNKNOWN - }; - - typedef boost::function2<void, Rdma::Connection::intrusive_ptr, ErrorType> ErrorCallback; - typedef boost::function1<void, Rdma::Connection::intrusive_ptr> DisconnectedCallback; - - class ConnectionManager { - typedef boost::function1<void, ConnectionManager&> NotifyCallback; - - enum State {IDLE, STOPPED}; - qpid::sys::AtomicValue<State> state; - Connection::intrusive_ptr ci; - qpid::sys::DispatchHandleRef handle; - NotifyCallback notifyCallback; - - protected: - ErrorCallback errorCallback; - DisconnectedCallback disconnectedCallback; - - public: - ConnectionManager( - ErrorCallback errc, - DisconnectedCallback dc - ); - - virtual ~ConnectionManager(); - - void start(qpid::sys::Poller::shared_ptr poller, const qpid::sys::SocketAddress& addr); - void stop(NotifyCallback); - - private: - void event(qpid::sys::DispatchHandle& handle); - void doStoppedCallback(); - - virtual void startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr) = 0; - virtual void connectionEvent(Connection::intrusive_ptr ci) = 0; - }; - - typedef boost::function2<bool, Rdma::Connection::intrusive_ptr, const ConnectionParams&> ConnectionRequestCallback; - typedef boost::function1<void, Rdma::Connection::intrusive_ptr> EstablishedCallback; - - class Listener : public ConnectionManager - { - ConnectionParams checkConnectionParams; - ConnectionRequestCallback connectionRequestCallback; - EstablishedCallback establishedCallback; - - public: - Listener( - const ConnectionParams& cp, - EstablishedCallback ec, - ErrorCallback errc, - DisconnectedCallback dc, - ConnectionRequestCallback crc = 0 - ); - - private: - void startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr); - void connectionEvent(Connection::intrusive_ptr ci); - }; - - typedef boost::function2<void, Rdma::Connection::intrusive_ptr, const ConnectionParams&> RejectedCallback; - typedef boost::function2<void, Rdma::Connection::intrusive_ptr, const ConnectionParams&> ConnectedCallback; - - class Connector : public ConnectionManager - { - ConnectionParams connectionParams; - RejectedCallback rejectedCallback; - ConnectedCallback connectedCallback; - - public: - Connector( - const ConnectionParams& cp, - ConnectedCallback cc, - ErrorCallback errc, - DisconnectedCallback dc, - RejectedCallback rc = 0 - ); - - private: - void startConnection(Connection::intrusive_ptr ci, const qpid::sys::SocketAddress& addr); - void connectionEvent(Connection::intrusive_ptr ci); - }; -} - -#endif // Rdma_Acceptor_h diff --git a/cpp/src/qpid/sys/rdma/RdmaServer.cpp b/cpp/src/qpid/sys/rdma/RdmaServer.cpp deleted file mode 100644 index 9b0710fd8f..0000000000 --- a/cpp/src/qpid/sys/rdma/RdmaServer.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Thread.h" -#include "qpid/sys/rdma/RdmaIO.h" -#include "qpid/sys/rdma/rdma_exception.h" - -#include <arpa/inet.h> - -#include <vector> -#include <queue> -#include <string> -#include <iostream> - -#include <boost/bind.hpp> - -using std::vector; -using std::queue; -using std::string; -using std::cout; -using std::cerr; - -using qpid::sys::Thread; -using qpid::sys::SocketAddress; -using qpid::sys::Poller; - -// All the accepted connections -namespace qpid { -namespace tests { - -struct Buffer { - char* bytes() const {return bytes_;} - int32_t byteCount() const {return size;} - - Buffer(const int32_t s): - bytes_(new char[s]), - size(s) - { - } - - ~Buffer() { - delete [] bytes_; - } -private: - char* bytes_; - int32_t size; -}; - -struct ConRec { - Rdma::Connection::intrusive_ptr connection; - Rdma::AsynchIO* data; - queue<Buffer*> queuedWrites; - - ConRec(Rdma::Connection::intrusive_ptr c) : - connection(c) - {} -}; - -void dataError(Rdma::AsynchIO&) { - cout << "Data error:\n"; -} - -void idle(ConRec* cr, Rdma::AsynchIO& a) { - // Need to make sure full is not called as it would reorder messages - while (!cr->queuedWrites.empty() && a.writable()) { - Rdma::Buffer* rbuf = a.getSendBuffer(); - if (!rbuf) break; - Buffer* buf = cr->queuedWrites.front(); - cr->queuedWrites.pop(); - std::copy(buf->bytes(), buf->bytes()+buf->byteCount(), rbuf->bytes()); - rbuf->dataCount(buf->byteCount()); - delete buf; - a.queueWrite(rbuf); - } -} - -void data(ConRec* cr, Rdma::AsynchIO& a, Rdma::Buffer* b) { - // Echo data back - Rdma::Buffer* buf = 0; - if (cr->queuedWrites.empty() && a.writable()) { - buf = a.getSendBuffer(); - } - if (buf) { - std::copy(b->bytes(), b->bytes()+b->dataCount(), buf->bytes()); - buf->dataCount(b->dataCount()); - a.queueWrite(buf); - } else { - Buffer* buf = new Buffer(b->dataCount()); - std::copy(b->bytes(), b->bytes()+b->dataCount(), buf->bytes()); - cr->queuedWrites.push(buf); - // Try to empty queue - idle(cr, a); - } -} - -void full(ConRec*, Rdma::AsynchIO&, Rdma::Buffer*) { - // Shouldn't ever be called - cout << "!"; -} - -void drained(Rdma::AsynchIO&) { - cout << "Drained:\n"; -} - -void disconnected(Rdma::Connection::intrusive_ptr& ci) { - ConRec* cr = ci->getContext<ConRec>(); - cr->connection->disconnect(); - cr->data->drainWriteQueue(drained); - delete cr; - cout << "Disconnected: " << cr << "\n"; -} - -void connectionError(Rdma::Connection::intrusive_ptr& ci, Rdma::ErrorType) { - ConRec* cr = ci->getContext<ConRec>(); - cr->connection->disconnect(); - if (cr) { - cr->data->drainWriteQueue(drained); - delete cr; - } - cout << "Connection error: " << cr << "\n"; -} - -bool connectionRequest(Rdma::Connection::intrusive_ptr& ci, const Rdma::ConnectionParams& cp) { - cout << "Incoming connection: "; - - // For fun reject alternate connection attempts - static bool x = false; - x = true; - - // Must create aio here so as to prepost buffers *before* we accept connection - if (x) { - ConRec* cr = new ConRec(ci); - Rdma::AsynchIO* aio = - new Rdma::AsynchIO(ci->getQueuePair(), - cp.rdmaProtocolVersion, - cp.maxRecvBufferSize, cp.initialXmitCredit, Rdma::DEFAULT_WR_ENTRIES, - boost::bind(data, cr, _1, _2), - boost::bind(idle, cr, _1), - boost::bind(full, cr, _1, _2), - dataError); - ci->addContext(cr); - cr->data = aio; - cout << "Accept=>" << cr << "\n"; - } else { - cout << "Reject\n"; - } - - return x; -} - -void connected(Poller::shared_ptr poller, Rdma::Connection::intrusive_ptr& ci) { - static int cnt = 0; - ConRec* cr = ci->getContext<ConRec>(); - cout << "Connected: " << cr << "(" << ++cnt << ")\n"; - - cr->data->start(poller); -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char* argv[]) { - vector<string> args(&argv[0], &argv[argc]); - - std::string port = (args.size() < 2) ? "20079" : args[1]; - cout << "Listening on port: " << port << "\n"; - - try { - boost::shared_ptr<Poller> p(new Poller()); - - Rdma::Listener a( - Rdma::ConnectionParams(16384, Rdma::DEFAULT_WR_ENTRIES), - boost::bind(connected, p, _1), - connectionError, - disconnected, - connectionRequest); - - - SocketAddress sa("", port); - a.start(p, sa); - - // The poller loop blocks all signals so run in its own thread - Thread t(*p); - - ::pause(); - p->shutdown(); - t.join(); - } catch (Rdma::Exception& e) { - int err = e.getError(); - cerr << "Error: " << e.what() << "(" << err << ")\n"; - } -} diff --git a/cpp/src/qpid/sys/rdma/rdma_exception.h b/cpp/src/qpid/sys/rdma/rdma_exception.h deleted file mode 100644 index a3a289e38a..0000000000 --- a/cpp/src/qpid/sys/rdma/rdma_exception.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef RDMA_EXCEPTION_H -#define RDMA_EXCEPTION_H - -#include <exception> - -#include <errno.h> -#include <string.h> - -namespace Rdma { - static __thread char s[50]; - class Exception : public std::exception { - int err; - - public: - Exception(int e) : err(e) {} - int getError() { return err; } - const char* what() const throw() { - return ::strerror_r(err, s, 50); - } - }; - - inline void THROW_ERRNO() { - throw Rdma::Exception(errno); - } - - inline void CHECK(int rc) { - if (rc != 0) - throw Rdma::Exception((rc == -1) ? errno : rc >0 ? rc : -rc); - } - - inline int GETERR(int rc) { - return (rc == -1) ? errno : rc > 0 ? rc : -rc; - } - - inline void CHECK_IBV(int rc) { - if (rc != 0) - throw Rdma::Exception(rc); - } - - template <typename T> - inline - T* CHECK_NULL(T* rc) { - if (rc == 0) - THROW_ERRNO(); - return rc; - } -} - -#endif // RDMA_EXCEPTION_H diff --git a/cpp/src/qpid/sys/rdma/rdma_factories.cpp b/cpp/src/qpid/sys/rdma/rdma_factories.cpp deleted file mode 100644 index a66f5b4035..0000000000 --- a/cpp/src/qpid/sys/rdma/rdma_factories.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/rdma/rdma_factories.h" - -#include "qpid/sys/rdma/rdma_exception.h" - - -namespace Rdma { - // Intentionally ignore return values for these functions - // - we can't do anything about then anyway - void acker(::rdma_cm_event* e) throw () { - if (e) (void) ::rdma_ack_cm_event(e); - } - - void destroyEChannel(::rdma_event_channel* c) throw () { - if (c) (void) ::rdma_destroy_event_channel(c); - } - - void destroyId(::rdma_cm_id* i) throw () { - if (i) (void) ::rdma_destroy_id(i); - } - - void deallocPd(::ibv_pd* p) throw () { - if (p) (void) ::ibv_dealloc_pd(p); - } - - void deregMr(::ibv_mr* mr) throw () { - if (mr) (void) ::ibv_dereg_mr(mr); - } - - void destroyCChannel(::ibv_comp_channel* c) throw () { - if (c) (void) ::ibv_destroy_comp_channel(c); - } - - void destroyCq(::ibv_cq* cq) throw () { - if (cq) (void) ::ibv_destroy_cq(cq); - } - - void destroyQp(::ibv_qp* qp) throw () { - if (qp) (void) ::ibv_destroy_qp(qp); - } - - boost::shared_ptr< ::rdma_cm_id > mkId(::rdma_cm_id* i) { - return boost::shared_ptr< ::rdma_cm_id >(i, destroyId); - } - - boost::shared_ptr< ::rdma_cm_event > mkEvent(::rdma_cm_event* e) { - return boost::shared_ptr< ::rdma_cm_event >(e, acker); - } - - boost::shared_ptr< ::ibv_qp > mkQp(::ibv_qp* qp) { - return boost::shared_ptr< ::ibv_qp > (qp, destroyQp); - } - - boost::shared_ptr< ::rdma_event_channel > mkEChannel() { - ::rdma_event_channel* c = CHECK_NULL(::rdma_create_event_channel()); - return boost::shared_ptr< ::rdma_event_channel >(c, destroyEChannel); - } - - boost::shared_ptr< ::rdma_cm_id > - mkId(::rdma_event_channel* ec, void* context, ::rdma_port_space ps) { - ::rdma_cm_id* i; - CHECK(::rdma_create_id(ec, &i, context, ps)); - return mkId(i); - } - - boost::shared_ptr< ::ibv_pd > allocPd(::ibv_context* c) { - ::ibv_pd* pd = CHECK_NULL(::ibv_alloc_pd(c)); - return boost::shared_ptr< ::ibv_pd >(pd, deallocPd); - } - - boost::shared_ptr< ::ibv_mr > regMr(::ibv_pd* pd, void* addr, size_t length, ::ibv_access_flags access) { - ::ibv_mr* mr = CHECK_NULL(::ibv_reg_mr(pd, addr, length, access)); - return boost::shared_ptr< ::ibv_mr >(mr, deregMr); - } - - boost::shared_ptr< ::ibv_comp_channel > mkCChannel(::ibv_context* c) { - ::ibv_comp_channel* cc = CHECK_NULL(::ibv_create_comp_channel(c)); - return boost::shared_ptr< ::ibv_comp_channel >(cc, destroyCChannel); - } - - boost::shared_ptr< ::ibv_cq > - mkCq(::ibv_context* c, int cqe, void* context, ::ibv_comp_channel* cc) { - ::ibv_cq* cq = CHECK_NULL(::ibv_create_cq(c, cqe, context, cc, 0)); - return boost::shared_ptr< ::ibv_cq >(cq, destroyCq); - } -} diff --git a/cpp/src/qpid/sys/rdma/rdma_factories.h b/cpp/src/qpid/sys/rdma/rdma_factories.h deleted file mode 100644 index bfca71fc7e..0000000000 --- a/cpp/src/qpid/sys/rdma/rdma_factories.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef RDMA_FACTORIES_H -#define RDMA_FACTORIES_H - -#include <rdma/rdma_cma.h> - -#include <boost/shared_ptr.hpp> - -namespace Rdma { - boost::shared_ptr< ::rdma_event_channel > mkEChannel(); - boost::shared_ptr< ::rdma_cm_id > mkId(::rdma_event_channel* ec, void* context, ::rdma_port_space ps); - boost::shared_ptr< ::rdma_cm_id > mkId(::rdma_cm_id* i); - boost::shared_ptr< ::rdma_cm_event > mkEvent(::rdma_cm_event* e); - boost::shared_ptr< ::ibv_qp > mkQp(::ibv_qp* qp); - boost::shared_ptr< ::ibv_pd > allocPd(::ibv_context* c); - boost::shared_ptr< ::ibv_mr > regMr(::ibv_pd* pd, void* addr, size_t length, ::ibv_access_flags access); - boost::shared_ptr< ::ibv_comp_channel > mkCChannel(::ibv_context* c); - boost::shared_ptr< ::ibv_cq > mkCq(::ibv_context* c, int cqe, void* context, ::ibv_comp_channel* cc); -} - -#endif // RDMA_FACTORIES_H diff --git a/cpp/src/qpid/sys/rdma/rdma_wrap.cpp b/cpp/src/qpid/sys/rdma/rdma_wrap.cpp deleted file mode 100644 index efe454c5be..0000000000 --- a/cpp/src/qpid/sys/rdma/rdma_wrap.cpp +++ /dev/null @@ -1,566 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/rdma/rdma_wrap.h" - -#include "qpid/sys/rdma/rdma_factories.h" -#include "qpid/sys/rdma/rdma_exception.h" - -#include "qpid/sys/posix/PrivatePosix.h" - -#include <fcntl.h> -#include <netdb.h> - -#include <iostream> -#include <stdexcept> - -namespace Rdma { - const ::rdma_conn_param DEFAULT_CONNECT_PARAM = { - 0, // .private_data - 0, // .private_data_len - 4, // .responder_resources - 4, // .initiator_depth - 0, // .flow_control - 5, // .retry_count - 7 // .rnr_retry_count - }; - - // This is moderately inefficient so don't use in a critical path - int deviceCount() { - int count; - ::ibv_free_device_list(::ibv_get_device_list(&count)); - return count; - } - - Buffer::Buffer(uint32_t lkey, char* bytes, const int32_t byteCount, - const int32_t reserve) : - bufferSize(byteCount + reserve), reserved(reserve) - { - sge.addr = (uintptr_t) bytes; - sge.length = 0; - sge.lkey = lkey; - } - - QueuePairEvent::QueuePairEvent() : - dir(NONE) - {} - - QueuePairEvent::QueuePairEvent( - const ::ibv_wc& w, - boost::shared_ptr< ::ibv_cq > c, - QueueDirection d) : - cq(c), - wc(w), - dir(d) - { - assert(dir != NONE); - } - - QueuePairEvent::operator bool() const { - return dir != NONE; - } - - bool QueuePairEvent::immPresent() const { - return wc.wc_flags & IBV_WC_WITH_IMM; - } - - uint32_t QueuePairEvent::getImm() const { - return ntohl(wc.imm_data); - } - - QueueDirection QueuePairEvent::getDirection() const { - return dir; - } - - ::ibv_wc_opcode QueuePairEvent::getEventType() const { - return wc.opcode; - } - - ::ibv_wc_status QueuePairEvent::getEventStatus() const { - return wc.status; - } - - Buffer* QueuePairEvent::getBuffer() const { - Buffer* b = reinterpret_cast<Buffer*>(wc.wr_id); - b->dataCount(wc.byte_len); - return b; - } - - QueuePair::QueuePair(boost::shared_ptr< ::rdma_cm_id > i) : - qpid::sys::IOHandle(new qpid::sys::IOHandlePrivate), - pd(allocPd(i->verbs)), - cchannel(mkCChannel(i->verbs)), - scq(mkCq(i->verbs, DEFAULT_CQ_ENTRIES, 0, cchannel.get())), - rcq(mkCq(i->verbs, DEFAULT_CQ_ENTRIES, 0, cchannel.get())), - outstandingSendEvents(0), - outstandingRecvEvents(0) - { - impl->fd = cchannel->fd; - - // Set cq context to this QueuePair object so we can find - // ourselves again - scq->cq_context = this; - rcq->cq_context = this; - - ::ibv_device_attr dev_attr; - CHECK(::ibv_query_device(i->verbs, &dev_attr)); - - ::ibv_qp_init_attr qp_attr = {}; - - // TODO: make a default struct for this - qp_attr.cap.max_send_wr = DEFAULT_WR_ENTRIES; - qp_attr.cap.max_send_sge = 1; - qp_attr.cap.max_recv_wr = DEFAULT_WR_ENTRIES; - qp_attr.cap.max_recv_sge = 1; - - qp_attr.send_cq = scq.get(); - qp_attr.recv_cq = rcq.get(); - qp_attr.qp_type = IBV_QPT_RC; - - CHECK(::rdma_create_qp(i.get(), pd.get(), &qp_attr)); - qp = mkQp(i->qp); - - // Set the qp context to this so we can find ourselves again - qp->qp_context = this; - } - - QueuePair::~QueuePair() { - // Reset back pointer in case someone else has the qp - qp->qp_context = 0; - - // Dispose queue pair before we ack events - qp.reset(); - - if (outstandingSendEvents > 0) - ::ibv_ack_cq_events(scq.get(), outstandingSendEvents); - if (outstandingRecvEvents > 0) - ::ibv_ack_cq_events(rcq.get(), outstandingRecvEvents); - - // Deallocate recv buffer memory - if (rmr) delete [] static_cast<char*>(rmr->addr); - - // Deallocate recv buffer memory - if (smr) delete [] static_cast<char*>(smr->addr); - - // The buffers vectors automatically deletes all the buffers we've allocated - } - - // Create buffers to use for writing - void QueuePair::createSendBuffers(int sendBufferCount, int bufferSize, int reserved) - { - assert(!smr); - - // Round up buffersize to cacheline (64 bytes) - int dataLength = (bufferSize+reserved+63) & (~63); - - // Allocate memory block for all receive buffers - char* mem = new char [sendBufferCount * dataLength]; - smr = regMr(pd.get(), mem, sendBufferCount * dataLength, ::IBV_ACCESS_LOCAL_WRITE); - sendBuffers.reserve(sendBufferCount); - freeBuffers.reserve(sendBufferCount); - for (int i = 0; i<sendBufferCount; ++i) { - // Allocate xmit buffer - sendBuffers.push_back(Buffer(smr->lkey, &mem[i*dataLength], bufferSize, reserved)); - freeBuffers.push_back(i); - } - } - - Buffer* QueuePair::getSendBuffer() { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(bufferLock); - if (freeBuffers.empty()) - return 0; - int i = freeBuffers.back(); - freeBuffers.pop_back(); - assert(i >= 0 && i < int(sendBuffers.size())); - Buffer* b = &sendBuffers[i]; - b->dataCount(0); - return b; - } - - void QueuePair::returnSendBuffer(Buffer* b) { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(bufferLock); - int i = b - &sendBuffers[0]; - assert(i >= 0 && i < int(sendBuffers.size())); - freeBuffers.push_back(i); - } - - void QueuePair::allocateRecvBuffers(int recvBufferCount, int bufferSize) - { - assert(!rmr); - - // Round up buffersize to cacheline (64 bytes) - bufferSize = (bufferSize+63) & (~63); - - // Allocate memory block for all receive buffers - char* mem = new char [recvBufferCount * bufferSize]; - rmr = regMr(pd.get(), mem, recvBufferCount * bufferSize, ::IBV_ACCESS_LOCAL_WRITE); - recvBuffers.reserve(recvBufferCount); - for (int i = 0; i<recvBufferCount; ++i) { - // Allocate recv buffer - recvBuffers.push_back(Buffer(rmr->lkey, &mem[i*bufferSize], bufferSize)); - postRecv(&recvBuffers[i]); - } - } - - // Make channel non-blocking by making - // associated fd nonblocking - void QueuePair::nonblocking() { - ::fcntl(cchannel->fd, F_SETFL, O_NONBLOCK); - } - - // If we get EAGAIN because the channel has been set non blocking - // and we'd have to wait then return an empty event - QueuePair::intrusive_ptr QueuePair::getNextChannelEvent() { - // First find out which cq has the event - ::ibv_cq* cq; - void* ctx; - int rc = ::ibv_get_cq_event(cchannel.get(), &cq, &ctx); - if (rc == -1 && errno == EAGAIN) - return 0; - CHECK(rc); - - // Batch acknowledge the event - if (cq == scq.get()) { - if (++outstandingSendEvents > DEFAULT_CQ_ENTRIES / 2) { - ::ibv_ack_cq_events(cq, outstandingSendEvents); - outstandingSendEvents = 0; - } - } else if (cq == rcq.get()) { - if (++outstandingRecvEvents > DEFAULT_CQ_ENTRIES / 2) { - ::ibv_ack_cq_events(cq, outstandingRecvEvents); - outstandingRecvEvents = 0; - } - } - - return static_cast<QueuePair*>(ctx); - } - - QueuePairEvent QueuePair::getNextEvent() { - ::ibv_wc w; - if (::ibv_poll_cq(scq.get(), 1, &w) == 1) - return QueuePairEvent(w, scq, SEND); - else if (::ibv_poll_cq(rcq.get(), 1, &w) == 1) - return QueuePairEvent(w, rcq, RECV); - else - return QueuePairEvent(); - } - - void QueuePair::notifyRecv() { - CHECK_IBV(ibv_req_notify_cq(rcq.get(), 0)); - } - - void QueuePair::notifySend() { - CHECK_IBV(ibv_req_notify_cq(scq.get(), 0)); - } - - void QueuePair::postRecv(Buffer* buf) { - ::ibv_recv_wr rwr = {}; - - rwr.wr_id = reinterpret_cast<uint64_t>(buf); - // We are given the whole buffer - buf->dataCount(buf->byteCount()); - rwr.sg_list = &buf->sge; - rwr.num_sge = 1; - - ::ibv_recv_wr* badrwr = 0; - CHECK(::ibv_post_recv(qp.get(), &rwr, &badrwr)); - if (badrwr) - throw std::logic_error("ibv_post_recv(): Bad rwr"); - } - - void QueuePair::postSend(Buffer* buf) { - ::ibv_send_wr swr = {}; - - swr.wr_id = reinterpret_cast<uint64_t>(buf); - swr.opcode = IBV_WR_SEND; - swr.send_flags = IBV_SEND_SIGNALED; - swr.sg_list = &buf->sge; - swr.num_sge = 1; - - ::ibv_send_wr* badswr = 0; - CHECK(::ibv_post_send(qp.get(), &swr, &badswr)); - if (badswr) - throw std::logic_error("ibv_post_send(): Bad swr"); - } - - void QueuePair::postSend(uint32_t imm, Buffer* buf) { - ::ibv_send_wr swr = {}; - - swr.wr_id = reinterpret_cast<uint64_t>(buf); - swr.imm_data = htonl(imm); - swr.opcode = IBV_WR_SEND_WITH_IMM; - swr.send_flags = IBV_SEND_SIGNALED; - swr.sg_list = &buf->sge; - swr.num_sge = 1; - - ::ibv_send_wr* badswr = 0; - CHECK(::ibv_post_send(qp.get(), &swr, &badswr)); - if (badswr) - throw std::logic_error("ibv_post_send(): Bad swr"); - } - - ConnectionEvent::ConnectionEvent(::rdma_cm_event* e) : - id((e->event != RDMA_CM_EVENT_CONNECT_REQUEST) ? - Connection::find(e->id) : new Connection(e->id)), - listen_id(Connection::find(e->listen_id)), - event(mkEvent(e)) - {} - - ConnectionEvent::operator bool() const { - return event; - } - - ::rdma_cm_event_type ConnectionEvent::getEventType() const { - return event->event; - } - - ::rdma_conn_param ConnectionEvent::getConnectionParam() const { - // It's badly documented, but it seems from the librdma source code that all the following - // event types have a valid param.conn - switch (event->event) { - case RDMA_CM_EVENT_CONNECT_REQUEST: - case RDMA_CM_EVENT_ESTABLISHED: - case RDMA_CM_EVENT_REJECTED: - case RDMA_CM_EVENT_DISCONNECTED: - case RDMA_CM_EVENT_CONNECT_ERROR: - return event->param.conn; - default: - ::rdma_conn_param p = {}; - return p; - } - } - - boost::intrusive_ptr<Connection> ConnectionEvent::getConnection () const { - return id; - } - - boost::intrusive_ptr<Connection> ConnectionEvent::getListenId() const { - return listen_id; - } - - // Wrap the passed in rdma_cm_id with a Connection - // this basically happens only on connection request - Connection::Connection(::rdma_cm_id* i) : - qpid::sys::IOHandle(new qpid::sys::IOHandlePrivate), - id(mkId(i)), - context(0) - { - impl->fd = id->channel->fd; - - // Just overwrite the previous context as it will - // have come from the listening connection - if (i) - i->context = this; - } - - Connection::Connection() : - qpid::sys::IOHandle(new qpid::sys::IOHandlePrivate), - channel(mkEChannel()), - id(mkId(channel.get(), this, RDMA_PS_TCP)), - context(0) - { - impl->fd = channel->fd; - } - - Connection::~Connection() { - // Reset the id context in case someone else has it - id->context = 0; - } - - void Connection::ensureQueuePair() { - assert(id.get()); - - // Only allocate a queue pair if there isn't one already - if (qp) - return; - - qp = new QueuePair(id); - } - - Connection::intrusive_ptr Connection::make() { - return new Connection(); - } - - Connection::intrusive_ptr Connection::find(::rdma_cm_id* i) { - if (!i) - return 0; - Connection* id = static_cast< Connection* >(i->context); - if (!id) - throw std::logic_error("Couldn't find existing Connection"); - return id; - } - - // Make channel non-blocking by making - // associated fd nonblocking - void Connection::nonblocking() { - assert(id.get()); - ::fcntl(id->channel->fd, F_SETFL, O_NONBLOCK); - } - - // If we get EAGAIN because the channel has been set non blocking - // and we'd have to wait then return an empty event - ConnectionEvent Connection::getNextEvent() { - assert(id.get()); - ::rdma_cm_event* e; - int rc = ::rdma_get_cm_event(id->channel, &e); - if (GETERR(rc) == EAGAIN) - return ConnectionEvent(); - CHECK(rc); - return ConnectionEvent(e); - } - - void Connection::bind(const qpid::sys::SocketAddress& src_addr) const { - assert(id.get()); - CHECK(::rdma_bind_addr(id.get(), getAddrInfo(src_addr).ai_addr)); - } - - void Connection::listen(int backlog) const { - assert(id.get()); - CHECK(::rdma_listen(id.get(), backlog)); - } - - void Connection::resolve_addr( - const qpid::sys::SocketAddress& dst_addr, - int timeout_ms) const - { - assert(id.get()); - CHECK(::rdma_resolve_addr(id.get(), 0, getAddrInfo(dst_addr).ai_addr, timeout_ms)); - } - - void Connection::resolve_route(int timeout_ms) const { - assert(id.get()); - CHECK(::rdma_resolve_route(id.get(), timeout_ms)); - } - - void Connection::disconnect() const { - assert(id.get()); - int rc = ::rdma_disconnect(id.get()); - // iWarp doesn't let you disconnect a disconnected connection - // but Infiniband can do so it's okay to call rdma_disconnect() - // in response to a disconnect event, but we may get an error - if (GETERR(rc) == EINVAL) - return; - CHECK(rc); - } - - // TODO: Currently you can only connect with the default connection parameters - void Connection::connect(const void* data, size_t len) { - assert(id.get()); - // Need to have a queue pair before we can connect - ensureQueuePair(); - - ::rdma_conn_param p = DEFAULT_CONNECT_PARAM; - p.private_data = data; - p.private_data_len = len; - CHECK(::rdma_connect(id.get(), &p)); - } - - void Connection::connect() { - connect(0, 0); - } - - void Connection::accept(const ::rdma_conn_param& param, const void* data, size_t len) { - assert(id.get()); - // Need to have a queue pair before we can accept - ensureQueuePair(); - - ::rdma_conn_param p = param; - p.private_data = data; - p.private_data_len = len; - CHECK(::rdma_accept(id.get(), &p)); - } - - void Connection::accept(const ::rdma_conn_param& param) { - accept(param, 0, 0); - } - - void Connection::reject(const void* data, size_t len) const { - assert(id.get()); - CHECK(::rdma_reject(id.get(), data, len)); - } - - void Connection::reject() const { - assert(id.get()); - CHECK(::rdma_reject(id.get(), 0, 0)); - } - - QueuePair::intrusive_ptr Connection::getQueuePair() { - assert(id.get()); - - ensureQueuePair(); - - return qp; - } - - std::string Connection::getLocalName() const { - ::sockaddr* addr = ::rdma_get_local_addr(id.get()); - char hostName[NI_MAXHOST]; - char portName[NI_MAXSERV]; - CHECK_IBV(::getnameinfo( - addr, sizeof(::sockaddr_storage), - hostName, sizeof(hostName), - portName, sizeof(portName), - NI_NUMERICHOST | NI_NUMERICSERV)); - std::string r(hostName); - r += ":"; - r += portName; - return r; - } - - std::string Connection::getPeerName() const { - ::sockaddr* addr = ::rdma_get_peer_addr(id.get()); - char hostName[NI_MAXHOST]; - char portName[NI_MAXSERV]; - CHECK_IBV(::getnameinfo( - addr, sizeof(::sockaddr_storage), - hostName, sizeof(hostName), - portName, sizeof(portName), - NI_NUMERICHOST | NI_NUMERICSERV)); - std::string r(hostName); - r += ":"; - r += portName; - return r; - } -} - -std::ostream& operator<<(std::ostream& o, ::rdma_cm_event_type t) { -# define CHECK_TYPE(t) case t: o << #t; break; - switch(t) { - CHECK_TYPE(RDMA_CM_EVENT_ADDR_RESOLVED) - CHECK_TYPE(RDMA_CM_EVENT_ADDR_ERROR) - CHECK_TYPE(RDMA_CM_EVENT_ROUTE_RESOLVED) - CHECK_TYPE(RDMA_CM_EVENT_ROUTE_ERROR) - CHECK_TYPE(RDMA_CM_EVENT_CONNECT_REQUEST) - CHECK_TYPE(RDMA_CM_EVENT_CONNECT_RESPONSE) - CHECK_TYPE(RDMA_CM_EVENT_CONNECT_ERROR) - CHECK_TYPE(RDMA_CM_EVENT_UNREACHABLE) - CHECK_TYPE(RDMA_CM_EVENT_REJECTED) - CHECK_TYPE(RDMA_CM_EVENT_ESTABLISHED) - CHECK_TYPE(RDMA_CM_EVENT_DISCONNECTED) - CHECK_TYPE(RDMA_CM_EVENT_DEVICE_REMOVAL) - CHECK_TYPE(RDMA_CM_EVENT_MULTICAST_JOIN) - CHECK_TYPE(RDMA_CM_EVENT_MULTICAST_ERROR) - default: - o << "UNKNOWN_EVENT"; - } -# undef CHECK_TYPE - return o; -} diff --git a/cpp/src/qpid/sys/rdma/rdma_wrap.h b/cpp/src/qpid/sys/rdma/rdma_wrap.h deleted file mode 100644 index 8e3429027b..0000000000 --- a/cpp/src/qpid/sys/rdma/rdma_wrap.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef RDMA_WRAP_H -#define RDMA_WRAP_H - -#include <rdma/rdma_cma.h> - -#include "qpid/RefCounted.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/Mutex.h" - -#include <boost/shared_ptr.hpp> -#include <boost/intrusive_ptr.hpp> -#include <boost/ptr_container/ptr_deque.hpp> - -#include <vector> - -namespace qpid { -namespace sys { - class SocketAddress; -}} - -namespace Rdma { - const int DEFAULT_TIMEOUT = 2000; // 2 secs - const int DEFAULT_BACKLOG = 100; - const int DEFAULT_CQ_ENTRIES = 256; - const int DEFAULT_WR_ENTRIES = 64; - extern const ::rdma_conn_param DEFAULT_CONNECT_PARAM; - - int deviceCount(); - - struct Buffer { - friend class QueuePair; - friend class QueuePairEvent; - - char* bytes() const; - int32_t byteCount() const; - int32_t dataCount() const; - void dataCount(int32_t); - - private: - Buffer(uint32_t lkey, char* bytes, const int32_t byteCount, const int32_t reserve=0); - int32_t bufferSize; - int32_t reserved; // for framing header - ::ibv_sge sge; - }; - - inline char* Buffer::bytes() const { - return (char*) sge.addr; - } - - /** return the number of bytes available for application data */ - inline int32_t Buffer::byteCount() const { - return bufferSize - reserved; - } - - inline int32_t Buffer::dataCount() const { - return sge.length; - } - - inline void Buffer::dataCount(int32_t s) { - // catch any attempt to overflow a buffer - assert(s <= bufferSize + reserved); - sge.length = s; - } - - class Connection; - - enum QueueDirection { - NONE, - SEND, - RECV - }; - - class QueuePairEvent { - boost::shared_ptr< ::ibv_cq > cq; - ::ibv_wc wc; - QueueDirection dir; - - friend class QueuePair; - - QueuePairEvent(); - QueuePairEvent( - const ::ibv_wc& w, - boost::shared_ptr< ::ibv_cq > c, - QueueDirection d); - - public: - operator bool() const; - bool immPresent() const; - uint32_t getImm() const; - QueueDirection getDirection() const; - ::ibv_wc_opcode getEventType() const; - ::ibv_wc_status getEventStatus() const; - Buffer* getBuffer() const; - }; - - // Wrapper for a queue pair - this has the functionality for - // putting buffers on the receive queue and for sending buffers - // to the other end of the connection. - class QueuePair : public qpid::sys::IOHandle, public qpid::RefCounted { - friend class Connection; - - boost::shared_ptr< ::ibv_pd > pd; - boost::shared_ptr< ::ibv_mr > smr; - boost::shared_ptr< ::ibv_mr > rmr; - boost::shared_ptr< ::ibv_comp_channel > cchannel; - boost::shared_ptr< ::ibv_cq > scq; - boost::shared_ptr< ::ibv_cq > rcq; - boost::shared_ptr< ::ibv_qp > qp; - int outstandingSendEvents; - int outstandingRecvEvents; - std::vector<Buffer> sendBuffers; - std::vector<Buffer> recvBuffers; - qpid::sys::Mutex bufferLock; - std::vector<int> freeBuffers; - - QueuePair(boost::shared_ptr< ::rdma_cm_id > id); - ~QueuePair(); - - public: - typedef boost::intrusive_ptr<QueuePair> intrusive_ptr; - - // Create a buffers to use for writing - void createSendBuffers(int sendBufferCount, int dataSize, int headerSize); - - // Get a send buffer - Buffer* getSendBuffer(); - - // Return buffer to pool after use - void returnSendBuffer(Buffer* b); - - // Create and post recv buffers - void allocateRecvBuffers(int recvBufferCount, int bufferSize); - - // Make channel non-blocking by making - // associated fd nonblocking - void nonblocking(); - - // If we get EAGAIN because the channel has been set non blocking - // and we'd have to wait then return an empty event - QueuePair::intrusive_ptr getNextChannelEvent(); - - QueuePairEvent getNextEvent(); - - void postRecv(Buffer* buf); - void postSend(Buffer* buf); - void postSend(uint32_t imm, Buffer* buf); - void notifyRecv(); - void notifySend(); - }; - - class ConnectionEvent { - friend class Connection; - - // The order of the members is important as we have to acknowledge - // the event before destroying the ids on destruction - boost::intrusive_ptr<Connection> id; - boost::intrusive_ptr<Connection> listen_id; - boost::shared_ptr< ::rdma_cm_event > event; - - ConnectionEvent() {} - ConnectionEvent(::rdma_cm_event* e); - - // Default copy, assignment and destructor ok - public: - operator bool() const; - ::rdma_cm_event_type getEventType() const; - ::rdma_conn_param getConnectionParam() const; - boost::intrusive_ptr<Connection> getConnection () const; - boost::intrusive_ptr<Connection> getListenId() const; - }; - - // For the moment this is a fairly simple wrapper for rdma_cm_id. - // - // NB: It allocates a protection domain (pd) per connection which means that - // registered buffers can't be shared between different connections - // (this can only happen between connections on the same controller in any case, - // so needs careful management if used) - class Connection : public qpid::sys::IOHandle, public qpid::RefCounted { - boost::shared_ptr< ::rdma_event_channel > channel; - boost::shared_ptr< ::rdma_cm_id > id; - QueuePair::intrusive_ptr qp; - - void* context; - - friend class ConnectionEvent; - friend class QueuePair; - - // Wrap the passed in rdma_cm_id with a Connection - // this basically happens only on connection request - Connection(::rdma_cm_id* i); - Connection(); - ~Connection(); - - void ensureQueuePair(); - - public: - typedef boost::intrusive_ptr<Connection> intrusive_ptr; - - static intrusive_ptr make(); - static intrusive_ptr find(::rdma_cm_id* i); - - template <typename T> - void addContext(T* c) { - // Don't allow replacing context - if (!context) - context = c; - } - - void removeContext() { - context = 0; - } - - template <typename T> - T* getContext() { - return static_cast<T*>(context); - } - - // Make channel non-blocking by making - // associated fd nonblocking - void nonblocking(); - - // If we get EAGAIN because the channel has been set non blocking - // and we'd have to wait then return an empty event - ConnectionEvent getNextEvent(); - - void bind(const qpid::sys::SocketAddress& src_addr) const; - void listen(int backlog = DEFAULT_BACKLOG) const; - void resolve_addr( - const qpid::sys::SocketAddress& dst_addr, - int timeout_ms = DEFAULT_TIMEOUT) const; - void resolve_route(int timeout_ms = DEFAULT_TIMEOUT) const; - void disconnect() const; - - // TODO: Currently you can only connect with the default connection parameters - void connect(const void* data, size_t len); - void connect(); - template <typename T> - void connect(const T* data) { - connect(data, sizeof(T)); - } - - // TODO: Not sure how to default accept params - they come from the connection request - // event - void accept(const ::rdma_conn_param& param, const void* data, size_t len); - void accept(const ::rdma_conn_param& param); - template <typename T> - void accept(const ::rdma_conn_param& param, const T* data) { - accept(param, data, sizeof(T)); - } - - void reject(const void* data, size_t len) const; - void reject() const; - template <typename T> - void reject(const T* data) const { - reject(data, sizeof(T)); - } - - QueuePair::intrusive_ptr getQueuePair(); - std::string getLocalName() const; - std::string getPeerName() const; - std::string getFullName() const { return getLocalName()+"-"+getPeerName(); } - }; -} - -std::ostream& operator<<(std::ostream& o, ::rdma_cm_event_type t); - -#endif // RDMA_WRAP_H diff --git a/cpp/src/qpid/sys/solaris/ECFPoller.cpp b/cpp/src/qpid/sys/solaris/ECFPoller.cpp deleted file mode 100644 index 06d542c938..0000000000 --- a/cpp/src/qpid/sys/solaris/ECFPoller.cpp +++ /dev/null @@ -1,444 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/log/Logger.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/DeletionManager.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" - -#include <port.h> -#include <poll.h> -#include <errno.h> -#include <pthread.h> -#include <signal.h> - -#include <assert.h> -#include <queue> -#include <exception> - - -//TODO: Remove this -#include "qpid/sys/Dispatcher.h" - -namespace qpid { -namespace sys { - -// Deletion manager to handle deferring deletion of PollerHandles to when they definitely aren't being used -DeletionManager<PollerHandlePrivate> PollerHandleDeletionManager; - -// Instantiate (and define) class static for DeletionManager -template <> -DeletionManager<PollerHandlePrivate>::AllThreadsStatuses DeletionManager<PollerHandlePrivate>::allThreadsStatuses(0); - -class PollerHandlePrivate { - friend class Poller; - friend class PollerHandle; - - enum FDStat { - ABSENT, - MONITORED, - INACTIVE, - HUNGUP, - MONITORED_HUNGUP, - DELETED - }; - - int fd; - uint32_t events; - FDStat stat; - Mutex lock; - - PollerHandlePrivate(int f) : - fd(f), - events(0), - stat(ABSENT) { - } - - bool isActive() const { - return stat == MONITORED || stat == MONITORED_HUNGUP; - } - - void setActive() { - stat = (stat == HUNGUP) ? MONITORED_HUNGUP : MONITORED; - } - - bool isInactive() const { - return stat == INACTIVE || stat == HUNGUP; - } - - void setInactive() { - stat = INACTIVE; - } - - bool isIdle() const { - return stat == ABSENT; - } - - void setIdle() { - stat = ABSENT; - } - - bool isHungup() const { - return stat == MONITORED_HUNGUP || stat == HUNGUP; - } - - void setHungup() { - assert(stat == MONITORED); - stat = HUNGUP; - } - - bool isDeleted() const { - return stat == DELETED; - } - - void setDeleted() { - stat = DELETED; - } -}; - -PollerHandle::PollerHandle(const IOHandle& h) : - impl(new PollerHandlePrivate(toFd(h.impl))) -{} - -PollerHandle::~PollerHandle() { - { - ScopedLock<Mutex> l(impl->lock); - if (impl->isDeleted()) { - return; - } - if (impl->isActive()) { - impl->setDeleted(); - } - } - PollerHandleDeletionManager.markForDeletion(impl); -} - -/** - * Concrete implementation of Poller to use the Solaris Event Completion - * Framework interface - */ -class PollerPrivate { - friend class Poller; - - class InterruptHandle: public PollerHandle { - std::queue<PollerHandle*> handles; - - void processEvent(Poller::EventType) { - PollerHandle* handle = handles.front(); - handles.pop(); - assert(handle); - - //Synthesise event - Poller::Event event(handle, Poller::INTERRUPTED); - - //Process synthesised event - event.process(); - } - - public: - InterruptHandle() : PollerHandle(DummyIOHandle) {} - - void addHandle(PollerHandle& h) { - handles.push(&h); - } - - PollerHandle *getHandle() { - PollerHandle* handle = handles.front(); - handles.pop(); - return handle; - } - - bool queuedHandles() { - return handles.size() > 0; - } - }; - - const int portId; - bool isShutdown; - InterruptHandle interruptHandle; - - static uint32_t directionToPollEvent(Poller::Direction dir) { - switch (dir) { - case Poller::INPUT: return POLLIN; - case Poller::OUTPUT: return POLLOUT; - case Poller::INOUT: return POLLIN | POLLOUT; - default: return 0; - } - } - - static Poller::EventType pollToDirection(uint32_t events) { - uint32_t e = events & (POLLIN | POLLOUT); - switch (e) { - case POLLIN: return Poller::READABLE; - case POLLOUT: return Poller::WRITABLE; - case POLLIN | POLLOUT: return Poller::READ_WRITABLE; - default: - return (events & (POLLHUP | POLLERR)) ? - Poller::DISCONNECTED : Poller::INVALID; - } - } - - PollerPrivate() : - portId(::port_create()), - isShutdown(false) { - QPID_POSIX_CHECK(portId); - QPID_LOG(trace, "port_create returned port Id: " << portId); - } - - ~PollerPrivate() { - } - - void interrupt() { - //Send an Alarm to the port - //We need to send a nonzero event mask, using POLLHUP, - //nevertheless the wait method will only look for a PORT_ALERT_SET - QPID_LOG(trace, "Sending a port_alert to " << portId); - QPID_POSIX_CHECK(::port_alert(portId, PORT_ALERT_SET, POLLHUP, - &static_cast<PollerHandle&>(interruptHandle))); - } -}; - -void Poller::addFd(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock<Mutex> l(eh.lock); - - uint32_t events = 0; - - if (eh.isIdle()) { - events = PollerPrivate::directionToPollEvent(dir); - } else { - assert(eh.isActive()); - events = eh.events | PollerPrivate::directionToPollEvent(dir); - } - - //port_associate can be used to add an association or modify an - //existing one - QPID_POSIX_CHECK(::port_associate(impl->portId, PORT_SOURCE_FD, (uintptr_t) eh.fd, events, &handle)); - eh.events = events; - eh.setActive(); - QPID_LOG(trace, "Poller::addFd(handle=" << &handle - << "[" << typeid(&handle).name() - << "], fd=" << eh.fd << ")"); -} - -void Poller::delFd(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock<Mutex> l(eh.lock); - assert(!eh.isIdle()); - int rc = ::port_dissociate(impl->portId, PORT_SOURCE_FD, (uintptr_t) eh.fd); - //Allow closing an invalid fd, allowing users to close fd before - //doing delFd() - if (rc == -1 && errno != EBADFD) { - QPID_POSIX_CHECK(rc); - } - eh.setIdle(); - QPID_LOG(trace, "Poller::delFd(handle=" << &handle - << ", fd=" << eh.fd << ")"); -} - -// modFd is equivalent to delFd followed by addFd -void Poller::modFd(PollerHandle& handle, Direction dir) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock<Mutex> l(eh.lock); - assert(!eh.isIdle()); - - eh.events = PollerPrivate::directionToPollEvent(dir); - - //If fd is already associated, events and user arguments are updated - //So, no need to check if fd is already associated - QPID_POSIX_CHECK(::port_associate(impl->portId, PORT_SOURCE_FD, (uintptr_t) eh.fd, eh.events, &handle)); - eh.setActive(); - QPID_LOG(trace, "Poller::modFd(handle=" << &handle - << ", fd=" << eh.fd << ")"); -} - -void Poller::rearmFd(PollerHandle& handle) { - PollerHandlePrivate& eh = *handle.impl; - ScopedLock<Mutex> l(eh.lock); - assert(eh.isInactive()); - - QPID_POSIX_CHECK(::port_associate(impl->portId, PORT_SOURCE_FD, (uintptr_t) eh.fd, eh.events, &handle)); - eh.setActive(); - QPID_LOG(trace, "Poller::rearmdFd(handle=" << &handle - << ", fd=" << eh.fd << ")"); -} - -void Poller::shutdown() { - //Allow sloppy code to shut us down more than once - if (impl->isShutdown) - return; - - impl->isShutdown = true; - impl->interrupt(); -} - -bool Poller::hasShutdown() -{ - return impl->isShutdown; -} - -bool Poller::interrupt(PollerHandle& handle) { - PollerPrivate::InterruptHandle& ih = impl->interruptHandle; - PollerHandlePrivate& eh = *static_cast<PollerHandle&>(ih).impl; - ScopedLock<Mutex> l(eh.lock); - ih.addHandle(handle); - impl->interrupt(); - eh.setActive(); - return true; -} - -void Poller::run() { - // Make sure we can't be interrupted by signals at a bad time - ::sigset_t ss; - ::sigfillset(&ss); - ::pthread_sigmask(SIG_SETMASK, &ss, 0); - - do { - Event event = wait(); - - // If can read/write then dispatch appropriate callbacks - if (event.handle) { - event.process(); - } else { - // Handle shutdown - switch (event.type) { - case SHUTDOWN: - return; - default: - // This should be impossible - assert(false); - } - } - } while (true); -} - -Poller::Event Poller::wait(Duration timeout) { - timespec_t tout; - timespec_t* ptout = NULL; - port_event_t pe; - - AbsTime targetTimeout = (timeout == TIME_INFINITE) ? FAR_FUTURE : - AbsTime(now(), timeout); - - if (timeout != TIME_INFINITE) { - tout.tv_sec = 0; - tout.tv_nsec = timeout; - ptout = &tout; - } - - do { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - QPID_LOG(trace, "About to enter port_get on " << impl->portId - << ". Thread " << pthread_self() - << ", timeout=" << timeout); - - - int rc = ::port_get(impl->portId, &pe, ptout); - - QPID_LOG(trace, "port_get on " << impl->portId - << " returned " << rc); - - if (impl->isShutdown) { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - return Event(0, SHUTDOWN); - } - - if (rc < 0) { - switch (errno) { - case EINTR: - continue; - case ETIME: - return Event(0, TIMEOUT); - default: - QPID_POSIX_CHECK(rc); - } - } else { - PollerHandle* handle = static_cast<PollerHandle*>(pe.portev_user); - PollerHandlePrivate& eh = *handle->impl; - ScopedLock<Mutex> l(eh.lock); - - if (eh.isActive()) { - QPID_LOG(trace, "Handle is active"); - //We use alert mode to notify interrupts - if (pe.portev_source == PORT_SOURCE_ALERT && - handle == &impl->interruptHandle) { - QPID_LOG(trace, "Interrupt notified"); - - PollerHandle* wrappedHandle = impl->interruptHandle.getHandle(); - - if (impl->interruptHandle.queuedHandles()) { - impl->interrupt(); - eh.setActive(); - } else { - eh.setInactive(); - } - return Event(wrappedHandle, INTERRUPTED); - } - - if (pe.portev_source == PORT_SOURCE_FD) { - QPID_LOG(trace, "About to send handle: " << handle); - if (pe.portev_events & POLLHUP) { - if (eh.isHungup()) { - return Event(handle, DISCONNECTED); - } - eh.setHungup(); - } else { - eh.setInactive(); - } - QPID_LOG(trace, "Sending event (thread: " - << pthread_self() << ") for handle " << handle - << ", direction= " - << PollerPrivate::pollToDirection(pe.portev_events)); - return Event(handle, PollerPrivate::pollToDirection(pe.portev_events)); - } - } else if (eh.isDeleted()) { - //Remove the handle from the poller - int rc = ::port_dissociate(impl->portId, PORT_SOURCE_FD, - (uintptr_t) eh.fd); - if (rc == -1 && errno != EBADFD) { - QPID_POSIX_CHECK(rc); - } - } - } - - if (timeout == TIME_INFINITE) { - continue; - } - if (rc == 0 && now() > targetTimeout) { - PollerHandleDeletionManager.markAllUnusedInThisThread(); - return Event(0, TIMEOUT); - } - } while (true); -} - -// Concrete constructors -Poller::Poller() : - impl(new PollerPrivate()) -{} - -Poller::~Poller() { - delete impl; -} - -}} diff --git a/cpp/src/qpid/sys/solaris/SystemInfo.cpp b/cpp/src/qpid/sys/solaris/SystemInfo.cpp deleted file mode 100755 index 765e5a7eb0..0000000000 --- a/cpp/src/qpid/sys/solaris/SystemInfo.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/SystemInfo.h" - -#define BSD_COMP -#include <sys/ioctl.h> -#include <netdb.h> -#undef BDS_COMP - - -#include <unistd.h> -#include <net/if.h> -#include <sys/types.h> -#include <sys/utsname.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <stdio.h> -#include <errno.h> -#include <limits.h> -#include <procfs.h> -#include <fcntl.h> -#include <sys/types.h> - -using namespace std; - -namespace qpid { -namespace sys { - -long SystemInfo::concurrency() { - return sysconf(_SC_NPROCESSORS_ONLN); -} - -bool SystemInfo::getLocalHostname(Address &address) { - char name[MAXHOSTNAMELEN]; - if (::gethostname(name, sizeof(name)) != 0) - return false; - address.host = name; - return true; -} - -static const string LOCALHOST("127.0.0.1"); -static const string TCP("tcp"); - -void SystemInfo::getLocalIpAddresses(uint16_t port, - std::vector<Address> &addrList) { - int s = socket(PF_INET, SOCK_STREAM, 0); - for (int i=1;;i++) { - struct lifreq ifr; - ifr.lifr_index = i; - if (::ioctl(s, SIOCGIFADDR, &ifr) < 0) { - break; - } - struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.lifr_addr; - std::string addr(inet_ntoa(sin->sin_addr)); - if (addr != LOCALHOST) - addrList.push_back(Address(TCP, addr, port)); - } - if (addrList.empty()) { - addrList.push_back(Address(TCP, LOCALHOST, port)); - } - close (s); -} - -void SystemInfo::getSystemId(std::string &osName, - std::string &nodeName, - std::string &release, - std::string &version, - std::string &machine) { - struct utsname _uname; - if (uname (&_uname) == 0) { - osName = _uname.sysname; - nodeName = _uname.nodename; - release = _uname.release; - version = _uname.version; - machine = _uname.machine; - } -} - -uint32_t SystemInfo::getProcessId() -{ - return (uint32_t) ::getpid(); -} - -uint32_t SystemInfo::getParentProcessId() -{ - return (uint32_t) ::getppid(); -} - -string SystemInfo::getProcessName() -{ - psinfo processInfo; - char procfile[PATH_MAX]; - int fd; - string value; - - snprintf(procfile, PATH_MAX, "/proc/%d/psinfo", getProcessId()); - if ((fd = open(procfile, O_RDONLY)) >= 0) { - if (read(fd, (void *) &processInfo, sizeof(processInfo)) == sizeof(processInfo)) { - value = processInfo.pr_fname; - } - } - return value; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/ssl/SslHandler.cpp b/cpp/src/qpid/sys/ssl/SslHandler.cpp deleted file mode 100644 index 5516d72065..0000000000 --- a/cpp/src/qpid/sys/ssl/SslHandler.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/ssl/SslHandler.h" - -#include "qpid/sys/ssl/SslIo.h" -#include "qpid/sys/ssl/SslSocket.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/log/Statement.h" - -#include <boost/bind.hpp> - -namespace qpid { -namespace sys { -namespace ssl { - - -// Buffer definition -struct Buff : public SslIO::BufferBase { - Buff() : - SslIO::BufferBase(new char[65536], 65536) - {} - ~Buff() - { delete [] bytes;} -}; - -SslHandler::SslHandler(std::string id, ConnectionCodec::Factory* f, bool _nodict) : - identifier(id), - aio(0), - factory(f), - codec(0), - readError(false), - isClient(false), - nodict(_nodict) -{} - -SslHandler::~SslHandler() { - if (codec) - codec->closed(); - delete codec; -} - -void SslHandler::init(SslIO* a, int numBuffs) { - aio = a; - - // Give connection some buffers to use - for (int i = 0; i < numBuffs; i++) { - aio->queueReadBuffer(new Buff); - } -} - -void SslHandler::write(const framing::ProtocolInitiation& data) -{ - QPID_LOG(debug, "SENT [" << identifier << "] INIT(" << data << ")"); - SslIO::BufferBase* buff = aio->getQueuedBuffer(); - if (!buff) - buff = new Buff; - framing::Buffer out(buff->bytes, buff->byteCount); - data.encode(out); - buff->dataCount = data.encodedSize(); - aio->queueWrite(buff); -} - -void SslHandler::abort() { - // TODO: can't implement currently as underlying functionality not implemented - // aio->requestCallback(boost::bind(&SslHandler::eof, this, _1)); -} -void SslHandler::activateOutput() { - aio->notifyPendingWrite(); -} - -void SslHandler::giveReadCredit(int32_t) { - // FIXME aconway 2008-12-05: not yet implemented. -} - -// Input side -void SslHandler::readbuff(SslIO& , SslIO::BufferBase* buff) { - if (readError) { - return; - } - size_t decoded = 0; - if (codec) { // Already initiated - try { - decoded = codec->decode(buff->bytes+buff->dataStart, buff->dataCount); - }catch(const std::exception& e){ - QPID_LOG(error, e.what()); - readError = true; - aio->queueWriteClose(); - } - }else{ - framing::Buffer in(buff->bytes+buff->dataStart, buff->dataCount); - framing::ProtocolInitiation protocolInit; - if (protocolInit.decode(in)) { - decoded = in.getPosition(); - QPID_LOG(debug, "RECV [" << identifier << "] INIT(" << protocolInit << ")"); - try { - codec = factory->create(protocolInit.getVersion(), *this, identifier, getSecuritySettings(aio)); - if (!codec) { - //TODO: may still want to revise this... - //send valid version header & close connection. - write(framing::ProtocolInitiation(framing::highestProtocolVersion)); - readError = true; - aio->queueWriteClose(); - } - } catch (const std::exception& e) { - QPID_LOG(error, e.what()); - readError = true; - aio->queueWriteClose(); - } - } - } - // TODO: unreading needs to go away, and when we can cope - // with multiple sub-buffers in the general buffer scheme, it will - if (decoded != size_t(buff->dataCount)) { - // Adjust buffer for used bytes and then "unread them" - buff->dataStart += decoded; - buff->dataCount -= decoded; - aio->unread(buff); - } else { - // Give whole buffer back to aio subsystem - aio->queueReadBuffer(buff); - } -} - -void SslHandler::eof(SslIO&) { - QPID_LOG(debug, "DISCONNECTED [" << identifier << "]"); - if (codec) codec->closed(); - aio->queueWriteClose(); -} - -void SslHandler::closedSocket(SslIO&, const SslSocket& s) { - // If we closed with data still to send log a warning - if (!aio->writeQueueEmpty()) { - QPID_LOG(warning, "CLOSING [" << identifier << "] unsent data (probably due to client disconnect)"); - } - delete &s; - aio->queueForDeletion(); - delete this; -} - -void SslHandler::disconnect(SslIO& a) { - // treat the same as eof - eof(a); -} - -// Notifications -void SslHandler::nobuffs(SslIO&) { -} - -void SslHandler::idle(SslIO&){ - if (isClient && codec == 0) { - codec = factory->create(*this, identifier, getSecuritySettings(aio)); - write(framing::ProtocolInitiation(codec->getVersion())); - return; - } - if (codec == 0) return; - if (codec->canEncode()) { - // Try and get a queued buffer if not then construct new one - SslIO::BufferBase* buff = aio->getQueuedBuffer(); - if (!buff) buff = new Buff; - size_t encoded=codec->encode(buff->bytes, buff->byteCount); - buff->dataCount = encoded; - aio->queueWrite(buff); - } - if (codec->isClosed()) - aio->queueWriteClose(); -} - -SecuritySettings SslHandler::getSecuritySettings(SslIO* aio) -{ - SecuritySettings settings = aio->getSecuritySettings(); - settings.nodict = nodict; - return settings; -} - - -}}} // namespace qpid::sys::ssl diff --git a/cpp/src/qpid/sys/ssl/SslHandler.h b/cpp/src/qpid/sys/ssl/SslHandler.h deleted file mode 100644 index 400fa317fd..0000000000 --- a/cpp/src/qpid/sys/ssl/SslHandler.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_SYS_SSL_SSLHANDLER_H -#define QPID_SYS_SSL_SSLHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/OutputControl.h" - -namespace qpid { - -namespace framing { - class ProtocolInitiation; -} - -namespace sys { -namespace ssl { - -class SslIO; -struct SslIOBufferBase; -class SslSocket; - -class SslHandler : public OutputControl { - std::string identifier; - SslIO* aio; - ConnectionCodec::Factory* factory; - ConnectionCodec* codec; - bool readError; - bool isClient; - bool nodict; - - void write(const framing::ProtocolInitiation&); - qpid::sys::SecuritySettings getSecuritySettings(SslIO* aio); - - public: - SslHandler(std::string id, ConnectionCodec::Factory* f, bool nodict); - ~SslHandler(); - void init(SslIO* a, int numBuffs); - - void setClient() { isClient = true; } - - // Output side - void abort(); - void activateOutput(); - void giveReadCredit(int32_t); - - // Input side - void readbuff(SslIO& aio, SslIOBufferBase* buff); - void eof(SslIO& aio); - void disconnect(SslIO& aio); - - // Notifications - void nobuffs(SslIO& aio); - void idle(SslIO& aio); - void closedSocket(SslIO& aio, const SslSocket& s); -}; - -}}} // namespace qpid::sys::ssl - -#endif /*!QPID_SYS_SSL_SSLHANDLER_H*/ diff --git a/cpp/src/qpid/sys/ssl/SslIo.cpp b/cpp/src/qpid/sys/ssl/SslIo.cpp deleted file mode 100644 index a58a137473..0000000000 --- a/cpp/src/qpid/sys/ssl/SslIo.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ssl/SslIo.h" -#include "qpid/sys/ssl/SslSocket.h" -#include "qpid/sys/ssl/check.h" - -#include "qpid/sys/Time.h" -#include "qpid/sys/posix/check.h" -#include "qpid/log/Statement.h" - -// TODO The basic algorithm here is not really POSIX specific and with a bit more abstraction -// could (should) be promoted to be platform portable -#include <unistd.h> -#include <sys/socket.h> -#include <signal.h> -#include <errno.h> -#include <string.h> - -#include <boost/bind.hpp> - -using namespace qpid::sys; -using namespace qpid::sys::ssl; - -namespace { - -/* - * Make *process* not generate SIGPIPE when writing to closed - * pipe/socket (necessary as default action is to terminate process) - */ -void ignoreSigpipe() { - ::signal(SIGPIPE, SIG_IGN); -} - -/* - * We keep per thread state to avoid locking overhead. The assumption is that - * on average all the connections are serviced by all the threads so the state - * recorded in each thread is about the same. If this turns out not to be the - * case we could rebalance the info occasionally. - */ -__thread int threadReadTotal = 0; -__thread int threadMaxRead = 0; -__thread int threadReadCount = 0; -__thread int threadWriteTotal = 0; -__thread int threadWriteCount = 0; -__thread int64_t threadMaxReadTimeNs = 2 * 1000000; // start at 2ms -} - -/* - * Asynch Acceptor - */ - -SslAcceptor::SslAcceptor(const SslSocket& s, Callback callback) : - acceptedCallback(callback), - handle(s, boost::bind(&SslAcceptor::readable, this, _1), 0, 0), - socket(s) { - - s.setNonblocking(); - ignoreSigpipe(); -} - -SslAcceptor::~SslAcceptor() -{ - handle.stopWatch(); -} - -void SslAcceptor::start(Poller::shared_ptr poller) { - handle.startWatch(poller); -} - -/* - * We keep on accepting as long as there is something to accept - */ -void SslAcceptor::readable(DispatchHandle& h) { - SslSocket* s; - do { - errno = 0; - // TODO: Currently we ignore the peers address, perhaps we should - // log it or use it for connection acceptance. - try { - s = socket.accept(); - if (s) { - acceptedCallback(*s); - } else { - break; - } - } catch (const std::exception& e) { - QPID_LOG(error, "Could not accept socket: " << e.what()); - } - } while (true); - - h.rewatch(); -} - -/* - * Asynch Connector - */ - -SslConnector::SslConnector(const SslSocket& s, - Poller::shared_ptr poller, - std::string hostname, - uint16_t port, - ConnectedCallback connCb, - FailedCallback failCb) : - DispatchHandle(s, - 0, - boost::bind(&SslConnector::connComplete, this, _1), - boost::bind(&SslConnector::connComplete, this, _1)), - connCallback(connCb), - failCallback(failCb), - socket(s) -{ - //TODO: would be better for connect to be performed on a - //non-blocking socket, but that doesn't work at present so connect - //blocks until complete - try { - socket.connect(hostname, port); - socket.setNonblocking(); - startWatch(poller); - } catch(std::exception& e) { - failure(-1, std::string(e.what())); - } -} - -void SslConnector::connComplete(DispatchHandle& h) -{ - int errCode = socket.getError(); - - h.stopWatch(); - if (errCode == 0) { - connCallback(socket); - DispatchHandle::doDelete(); - } else { - // TODO: This need to be fixed as strerror isn't thread safe - failure(errCode, std::string(::strerror(errCode))); - } -} - -void SslConnector::failure(int errCode, std::string message) -{ - if (failCallback) - failCallback(errCode, message); - - socket.close(); - delete &socket; - - DispatchHandle::doDelete(); -} - -/* - * Asynch reader/writer - */ -SslIO::SslIO(const SslSocket& s, - ReadCallback rCb, EofCallback eofCb, DisconnectCallback disCb, - ClosedCallback cCb, BuffersEmptyCallback eCb, IdleCallback iCb) : - - DispatchHandle(s, - boost::bind(&SslIO::readable, this, _1), - boost::bind(&SslIO::writeable, this, _1), - boost::bind(&SslIO::disconnected, this, _1)), - readCallback(rCb), - eofCallback(eofCb), - disCallback(disCb), - closedCallback(cCb), - emptyCallback(eCb), - idleCallback(iCb), - socket(s), - queuedClose(false), - writePending(false) { - - s.setNonblocking(); -} - -struct deleter -{ - template <typename T> - void operator()(T *ptr){ delete ptr;} -}; - -SslIO::~SslIO() { - std::for_each( bufferQueue.begin(), bufferQueue.end(), deleter()); - std::for_each( writeQueue.begin(), writeQueue.end(), deleter()); -} - -void SslIO::queueForDeletion() { - DispatchHandle::doDelete(); -} - -void SslIO::start(Poller::shared_ptr poller) { - DispatchHandle::startWatch(poller); -} - -void SslIO::queueReadBuffer(BufferBase* buff) { - assert(buff); - buff->dataStart = 0; - buff->dataCount = 0; - bufferQueue.push_back(buff); - DispatchHandle::rewatchRead(); -} - -void SslIO::unread(BufferBase* buff) { - assert(buff); - if (buff->dataStart != 0) { - memmove(buff->bytes, buff->bytes+buff->dataStart, buff->dataCount); - buff->dataStart = 0; - } - bufferQueue.push_front(buff); - DispatchHandle::rewatchRead(); -} - -void SslIO::queueWrite(BufferBase* buff) { - assert(buff); - // If we've already closed the socket then throw the write away - if (queuedClose) { - bufferQueue.push_front(buff); - return; - } else { - writeQueue.push_front(buff); - } - writePending = false; - DispatchHandle::rewatchWrite(); -} - -void SslIO::notifyPendingWrite() { - writePending = true; - DispatchHandle::rewatchWrite(); -} - -void SslIO::queueWriteClose() { - queuedClose = true; - DispatchHandle::rewatchWrite(); -} - -/** Return a queued buffer if there are enough - * to spare - */ -SslIO::BufferBase* SslIO::getQueuedBuffer() { - // Always keep at least one buffer (it might have data that was "unread" in it) - if (bufferQueue.size()<=1) - return 0; - BufferBase* buff = bufferQueue.back(); - assert(buff); - buff->dataStart = 0; - buff->dataCount = 0; - bufferQueue.pop_back(); - return buff; -} - -/* - * We keep on reading as long as we have something to read and a buffer to put - * it in - */ -void SslIO::readable(DispatchHandle& h) { - int readTotal = 0; - AbsTime readStartTime = AbsTime::now(); - do { - // (Try to) get a buffer - if (!bufferQueue.empty()) { - // Read into buffer - BufferBase* buff = bufferQueue.front(); - assert(buff); - bufferQueue.pop_front(); - errno = 0; - int readCount = buff->byteCount-buff->dataCount; - int rc = socket.read(buff->bytes + buff->dataCount, readCount); - if (rc > 0) { - buff->dataCount += rc; - threadReadTotal += rc; - readTotal += rc; - - readCallback(*this, buff); - if (rc != readCount) { - // If we didn't fill the read buffer then time to stop reading - break; - } - - // Stop reading if we've overrun our timeslot - if (Duration(readStartTime, AbsTime::now()) > threadMaxReadTimeNs) { - break; - } - - } else { - // Put buffer back (at front so it doesn't interfere with unread buffers) - bufferQueue.push_front(buff); - assert(buff); - - // Eof or other side has gone away - if (rc == 0 || errno == ECONNRESET) { - eofCallback(*this); - h.unwatchRead(); - break; - } else if (errno == EAGAIN) { - // We have just put a buffer back so we know - // we can carry on watching for reads - break; - } else { - // Report error then just treat as a socket disconnect - QPID_LOG(error, "Error reading socket: " << getErrorString(PR_GetError())); - eofCallback(*this); - h.unwatchRead(); - break; - } - } - } else { - // Something to read but no buffer - if (emptyCallback) { - emptyCallback(*this); - } - // If we still have no buffers we can't do anything more - if (bufferQueue.empty()) { - h.unwatchRead(); - break; - } - - } - } while (true); - - ++threadReadCount; - threadMaxRead = std::max(threadMaxRead, readTotal); - return; -} - -/* - * We carry on writing whilst we have data to write and we can write - */ -void SslIO::writeable(DispatchHandle& h) { - int writeTotal = 0; - do { - // See if we've got something to write - if (!writeQueue.empty()) { - // Write buffer - BufferBase* buff = writeQueue.back(); - writeQueue.pop_back(); - errno = 0; - assert(buff->dataStart+buff->dataCount <= buff->byteCount); - int rc = socket.write(buff->bytes+buff->dataStart, buff->dataCount); - if (rc >= 0) { - threadWriteTotal += rc; - writeTotal += rc; - - // If we didn't write full buffer put rest back - if (rc != buff->dataCount) { - buff->dataStart += rc; - buff->dataCount -= rc; - writeQueue.push_back(buff); - break; - } - - // Recycle the buffer - queueReadBuffer(buff); - - // If we've already written more than the max for reading then stop - // (this is to stop writes dominating reads) - if (writeTotal > threadMaxRead) - break; - } else { - // Put buffer back - writeQueue.push_back(buff); - if (errno == ECONNRESET || errno == EPIPE) { - // Just stop watching for write here - we'll get a - // disconnect callback soon enough - h.unwatchWrite(); - break; - } else if (errno == EAGAIN) { - // We have just put a buffer back so we know - // we can carry on watching for writes - break; - } else { - QPID_LOG(error, "Error writing to socket: " << getErrorString(PR_GetError())); - h.unwatchWrite(); - break; - } - } - } else { - // If we're waiting to close the socket then can do it now as there is nothing to write - if (queuedClose) { - close(h); - break; - } - // Fd is writable, but nothing to write - if (idleCallback) { - writePending = false; - idleCallback(*this); - } - // If we still have no buffers to write we can't do anything more - if (writeQueue.empty() && !writePending && !queuedClose) { - h.unwatchWrite(); - // The following handles the case where writePending is - // set to true after the test above; in this case its - // possible that the unwatchWrite overwrites the - // desired rewatchWrite so we correct that here - if (writePending) - h.rewatchWrite(); - break; - } - } - } while (true); - - ++threadWriteCount; - return; -} - -void SslIO::disconnected(DispatchHandle& h) { - // If we've already queued close do it instead of disconnected callback - if (queuedClose) { - close(h); - } else if (disCallback) { - disCallback(*this); - h.unwatch(); - } -} - -/* - * Close the socket and callback to say we've done it - */ -void SslIO::close(DispatchHandle& h) { - h.stopWatch(); - socket.close(); - if (closedCallback) { - closedCallback(*this, socket); - } -} - -SecuritySettings SslIO::getSecuritySettings() { - SecuritySettings settings; - settings.ssf = socket.getKeyLen(); - settings.authid = socket.getClientAuthId(); - return settings; -} diff --git a/cpp/src/qpid/sys/ssl/SslIo.h b/cpp/src/qpid/sys/ssl/SslIo.h deleted file mode 100644 index 53ac69d8d6..0000000000 --- a/cpp/src/qpid/sys/ssl/SslIo.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef _sys_ssl_SslIO -#define _sys_ssl_SslIO -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/DispatchHandle.h" -#include "qpid/sys/SecuritySettings.h" - -#include <boost/function.hpp> -#include <deque> - -namespace qpid { -namespace sys { -namespace ssl { - -class SslSocket; - -/* - * Asynchronous ssl acceptor: accepts connections then does a callback - * with the accepted fd - */ -class SslAcceptor { -public: - typedef boost::function1<void, const SslSocket&> Callback; - -private: - Callback acceptedCallback; - qpid::sys::DispatchHandle handle; - const SslSocket& socket; - -public: - SslAcceptor(const SslSocket& s, Callback callback); - ~SslAcceptor(); - void start(qpid::sys::Poller::shared_ptr poller); - -private: - void readable(qpid::sys::DispatchHandle& handle); -}; - -/* - * Asynchronous ssl connector: starts the process of initiating a - * connection and invokes a callback when completed or failed. - */ -class SslConnector : private qpid::sys::DispatchHandle { -public: - typedef boost::function1<void, const SslSocket&> ConnectedCallback; - typedef boost::function2<void, int, std::string> FailedCallback; - -private: - ConnectedCallback connCallback; - FailedCallback failCallback; - const SslSocket& socket; - -public: - SslConnector(const SslSocket& socket, - Poller::shared_ptr poller, - std::string hostname, - uint16_t port, - ConnectedCallback connCb, - FailedCallback failCb = 0); - -private: - void connComplete(DispatchHandle& handle); - void failure(int, std::string); -}; - -struct SslIOBufferBase { - char* const bytes; - const int32_t byteCount; - int32_t dataStart; - int32_t dataCount; - - SslIOBufferBase(char* const b, const int32_t s) : - bytes(b), - byteCount(s), - dataStart(0), - dataCount(0) - {} - - virtual ~SslIOBufferBase() - {} -}; - -/* - * Asychronous reader/writer: - * Reader accepts buffers to read into; reads into the provided buffers - * and then does a callback with the buffer and amount read. Optionally it can callback - * when there is something to read but no buffer to read it into. - * - * Writer accepts a buffer and queues it for writing; can also be given - * a callback for when writing is "idle" (ie fd is writable, but nothing to write) - * - * The class is implemented in terms of DispatchHandle to allow it to be deleted by deleting - * the contained DispatchHandle - */ -class SslIO : private qpid::sys::DispatchHandle { -public: - typedef SslIOBufferBase BufferBase; - - typedef boost::function2<void, SslIO&, BufferBase*> ReadCallback; - typedef boost::function1<void, SslIO&> EofCallback; - typedef boost::function1<void, SslIO&> DisconnectCallback; - typedef boost::function2<void, SslIO&, const SslSocket&> ClosedCallback; - typedef boost::function1<void, SslIO&> BuffersEmptyCallback; - typedef boost::function1<void, SslIO&> IdleCallback; - - -private: - ReadCallback readCallback; - EofCallback eofCallback; - DisconnectCallback disCallback; - ClosedCallback closedCallback; - BuffersEmptyCallback emptyCallback; - IdleCallback idleCallback; - const SslSocket& socket; - std::deque<BufferBase*> bufferQueue; - std::deque<BufferBase*> writeQueue; - bool queuedClose; - /** - * This flag is used to detect and handle concurrency between - * calls to notifyPendingWrite() (which can be made from any thread) and - * the execution of the writeable() method (which is always on the - * thread processing this handle. - */ - volatile bool writePending; - -public: - SslIO(const SslSocket& s, - ReadCallback rCb, EofCallback eofCb, DisconnectCallback disCb, - ClosedCallback cCb = 0, BuffersEmptyCallback eCb = 0, IdleCallback iCb = 0); - void queueForDeletion(); - - void start(qpid::sys::Poller::shared_ptr poller); - void queueReadBuffer(BufferBase* buff); - void unread(BufferBase* buff); - void queueWrite(BufferBase* buff); - void notifyPendingWrite(); - void queueWriteClose(); - bool writeQueueEmpty() { return writeQueue.empty(); } - BufferBase* getQueuedBuffer(); - - qpid::sys::SecuritySettings getSecuritySettings(); - -private: - ~SslIO(); - void readable(qpid::sys::DispatchHandle& handle); - void writeable(qpid::sys::DispatchHandle& handle); - void disconnected(qpid::sys::DispatchHandle& handle); - void close(qpid::sys::DispatchHandle& handle); -}; - -}}} - -#endif // _sys_ssl_SslIO diff --git a/cpp/src/qpid/sys/ssl/SslSocket.cpp b/cpp/src/qpid/sys/ssl/SslSocket.cpp deleted file mode 100644 index 01e2658877..0000000000 --- a/cpp/src/qpid/sys/ssl/SslSocket.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ssl/SslSocket.h" -#include "qpid/sys/ssl/check.h" -#include "qpid/sys/ssl/util.h" -#include "qpid/Exception.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" - -#include <fcntl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/errno.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <netdb.h> -#include <cstdlib> -#include <string.h> -#include <iostream> - -#include <private/pprio.h> -#include <nss.h> -#include <pk11pub.h> -#include <ssl.h> -#include <key.h> - -#include <boost/format.hpp> - -namespace qpid { -namespace sys { -namespace ssl { - -namespace { -std::string getName(int fd, bool local, bool includeService = false) -{ - ::sockaddr_storage name; // big enough for any socket address - ::socklen_t namelen = sizeof(name); - - int result = -1; - if (local) { - result = ::getsockname(fd, (::sockaddr*)&name, &namelen); - } else { - result = ::getpeername(fd, (::sockaddr*)&name, &namelen); - } - - QPID_POSIX_CHECK(result); - - char servName[NI_MAXSERV]; - char dispName[NI_MAXHOST]; - if (includeService) { - if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName), - servName, sizeof(servName), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw QPID_POSIX_ERROR(rc); - return std::string(dispName) + ":" + std::string(servName); - - } else { - if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName), 0, 0, NI_NUMERICHOST) != 0) - throw QPID_POSIX_ERROR(rc); - return dispName; - } -} - -std::string getService(int fd, bool local) -{ - ::sockaddr_storage name; // big enough for any socket address - ::socklen_t namelen = sizeof(name); - - int result = -1; - if (local) { - result = ::getsockname(fd, (::sockaddr*)&name, &namelen); - } else { - result = ::getpeername(fd, (::sockaddr*)&name, &namelen); - } - - QPID_POSIX_CHECK(result); - - char servName[NI_MAXSERV]; - if (int rc=::getnameinfo((::sockaddr*)&name, namelen, 0, 0, - servName, sizeof(servName), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw QPID_POSIX_ERROR(rc); - return servName; -} - -const std::string DOMAIN_SEPARATOR("@"); -const std::string DC_SEPARATOR("."); -const std::string DC("DC"); -const std::string DN_DELIMS(" ,="); - -std::string getDomainFromSubject(std::string subject) -{ - std::string::size_type last = subject.find_first_not_of(DN_DELIMS, 0); - std::string::size_type i = subject.find_first_of(DN_DELIMS, last); - - std::string domain; - bool nextTokenIsDC = false; - while (std::string::npos != i || std::string::npos != last) - { - std::string token = subject.substr(last, i - last); - if (nextTokenIsDC) { - if (domain.size()) domain += DC_SEPARATOR; - domain += token; - nextTokenIsDC = false; - } else if (token == DC) { - nextTokenIsDC = true; - } - last = subject.find_first_not_of(DN_DELIMS, i); - i = subject.find_first_of(DN_DELIMS, last); - } - return domain; -} - -} - -SslSocket::SslSocket() : IOHandle(new IOHandlePrivate()), socket(0), prototype(0) -{ - impl->fd = ::socket (PF_INET, SOCK_STREAM, 0); - if (impl->fd < 0) throw QPID_POSIX_ERROR(errno); - socket = SSL_ImportFD(0, PR_ImportTCPSocket(impl->fd)); -} - -/** - * This form of the constructor is used with the server-side sockets - * returned from accept. Because we use posix accept rather than - * PR_Accept, we have to reset the handshake. - */ -SslSocket::SslSocket(IOHandlePrivate* ioph, PRFileDesc* model) : IOHandle(ioph), socket(0), prototype(0) -{ - socket = SSL_ImportFD(model, PR_ImportTCPSocket(impl->fd)); - NSS_CHECK(SSL_ResetHandshake(socket, true)); -} - -void SslSocket::setNonblocking() const -{ - PRSocketOptionData option; - option.option = PR_SockOpt_Nonblocking; - option.value.non_blocking = true; - PR_SetSocketOption(socket, &option); -} - -void SslSocket::connect(const std::string& host, uint16_t port) const -{ - std::stringstream namestream; - namestream << host << ":" << port; - connectname = namestream.str(); - - void* arg; - // Use the connection's cert-name if it has one; else use global cert-name - if (certname != "") { - arg = const_cast<char*>(certname.c_str()); - } else if (SslOptions::global.certName.empty()) { - arg = 0; - } else { - arg = const_cast<char*>(SslOptions::global.certName.c_str()); - } - NSS_CHECK(SSL_GetClientAuthDataHook(socket, NSS_GetClientAuthData, arg)); - NSS_CHECK(SSL_SetURL(socket, host.data())); - - char hostBuffer[PR_NETDB_BUF_SIZE]; - PRHostEnt hostEntry; - PR_CHECK(PR_GetHostByName(host.data(), hostBuffer, PR_NETDB_BUF_SIZE, &hostEntry)); - PRNetAddr address; - int value = PR_EnumerateHostEnt(0, &hostEntry, port, &address); - if (value < 0) { - throw Exception(QPID_MSG("Error getting address for host: " << ErrorString())); - } else if (value == 0) { - throw Exception(QPID_MSG("Could not resolve address for host.")); - } - PR_CHECK(PR_Connect(socket, &address, PR_INTERVAL_NO_TIMEOUT)); - NSS_CHECK(SSL_ForceHandshake(socket)); -} - -void SslSocket::close() const -{ - if (impl->fd > 0) { - PR_Close(socket); - impl->fd = -1; - } -} - -int SslSocket::listen(uint16_t port, int backlog, const std::string& certName, bool clientAuth) const -{ - //configure prototype socket: - prototype = SSL_ImportFD(0, PR_NewTCPSocket()); - if (clientAuth) { - NSS_CHECK(SSL_OptionSet(prototype, SSL_REQUEST_CERTIFICATE, PR_TRUE)); - NSS_CHECK(SSL_OptionSet(prototype, SSL_REQUIRE_CERTIFICATE, PR_TRUE)); - } - - //get certificate and key (is this the correct way?) - CERTCertificate *cert = PK11_FindCertFromNickname(const_cast<char*>(certName.c_str()), 0); - if (!cert) throw Exception(QPID_MSG("Failed to load certificate '" << certName << "'")); - SECKEYPrivateKey *key = PK11_FindKeyByAnyCert(cert, 0); - if (!key) throw Exception(QPID_MSG("Failed to retrieve private key from certificate")); - NSS_CHECK(SSL_ConfigSecureServer(prototype, cert, key, NSS_FindCertKEAType(cert))); - SECKEY_DestroyPrivateKey(key); - CERT_DestroyCertificate(cert); - - //bind and listen - const int& socket = impl->fd; - int yes=1; - QPID_POSIX_CHECK(setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes))); - struct sockaddr_in name; - name.sin_family = AF_INET; - name.sin_port = htons(port); - name.sin_addr.s_addr = 0; - if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) < 0) - throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(errno))); - if (::listen(socket, backlog) < 0) - throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(errno))); - - socklen_t namelen = sizeof(name); - if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0) - throw QPID_POSIX_ERROR(errno); - - return ntohs(name.sin_port); -} - -SslSocket* SslSocket::accept() const -{ - int afd = ::accept(impl->fd, 0, 0); - if ( afd >= 0) { - return new SslSocket(new IOHandlePrivate(afd), prototype); - } else if (errno == EAGAIN) { - return 0; - } else { - throw QPID_POSIX_ERROR(errno); - } -} - -int SslSocket::read(void *buf, size_t count) const -{ - return PR_Read(socket, buf, count); -} - -int SslSocket::write(const void *buf, size_t count) const -{ - return PR_Write(socket, buf, count); -} - -std::string SslSocket::getSockname() const -{ - return getName(impl->fd, true); -} - -std::string SslSocket::getPeername() const -{ - return getName(impl->fd, false); -} - -std::string SslSocket::getPeerAddress() const -{ - if (!connectname.empty()) - return connectname; - return getName(impl->fd, false, true); -} - -std::string SslSocket::getLocalAddress() const -{ - return getName(impl->fd, true, true); -} - -uint16_t SslSocket::getLocalPort() const -{ - return std::atoi(getService(impl->fd, true).c_str()); -} - -uint16_t SslSocket::getRemotePort() const -{ - return atoi(getService(impl->fd, true).c_str()); -} - -int SslSocket::getError() const -{ - int result; - socklen_t rSize = sizeof (result); - - if (::getsockopt(impl->fd, SOL_SOCKET, SO_ERROR, &result, &rSize) < 0) - throw QPID_POSIX_ERROR(errno); - - return result; -} - -void SslSocket::setTcpNoDelay(bool nodelay) const -{ - if (nodelay) { - PRSocketOptionData option; - option.option = PR_SockOpt_NoDelay; - option.value.no_delay = true; - PR_SetSocketOption(socket, &option); - } -} - -void SslSocket::setCertName(const std::string& name) -{ - certname = name; -} - - -/** get the bit length of the current cipher's key */ -int SslSocket::getKeyLen() const -{ - int enabled = 0; - int keySize = 0; - SECStatus rc; - - rc = SSL_SecurityStatus( socket, - &enabled, - NULL, - NULL, - &keySize, - NULL, NULL ); - if (rc == SECSuccess && enabled) { - return keySize; - } - return 0; -} - -std::string SslSocket::getClientAuthId() const -{ - std::string authId; - CERTCertificate* cert = SSL_PeerCertificate(socket); - if (cert) { - authId = CERT_GetCommonName(&(cert->subject)); - /* - * The NSS function CERT_GetDomainComponentName only returns - * the last component of the domain name, so we have to parse - * the subject manually to extract the full domain. - */ - std::string domain = getDomainFromSubject(cert->subjectName); - if (!domain.empty()) { - authId += DOMAIN_SEPARATOR; - authId += domain; - } - CERT_DestroyCertificate(cert); - } - return authId; -} - -}}} // namespace qpid::sys::ssl diff --git a/cpp/src/qpid/sys/ssl/SslSocket.h b/cpp/src/qpid/sys/ssl/SslSocket.h deleted file mode 100644 index 25712c98d5..0000000000 --- a/cpp/src/qpid/sys/ssl/SslSocket.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef _sys_ssl_Socket_h -#define _sys_ssl_Socket_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IOHandle.h" -#include <nspr.h> - -#include <string> - -struct sockaddr; - -namespace qpid { -namespace sys { - -class Duration; - -namespace ssl { - -class SslSocket : public qpid::sys::IOHandle -{ -public: - /** Create a socket wrapper for descriptor. */ - SslSocket(); - - /** Set socket non blocking */ - void setNonblocking() const; - - /** Set tcp-nodelay */ - void setTcpNoDelay(bool nodelay) const; - - /** Set SSL cert-name. Allows the cert-name to be set per - * connection, overriding global cert-name settings from - * NSSInit().*/ - void setCertName(const std::string& certName); - - void connect(const std::string& host, uint16_t port) const; - - void close() const; - - /** Bind to a port and start listening. - *@param port 0 means choose an available port. - *@param backlog maximum number of pending connections. - *@param certName name of certificate to use to identify the server - *@return The bound port. - */ - int listen(uint16_t port = 0, int backlog = 10, const std::string& certName = "localhost.localdomain", bool clientAuth = false) const; - - /** - * Accept a connection from a socket that is already listening - * and has an incoming connection - */ - SslSocket* accept() const; - - // TODO The following are raw operations, maybe they need better wrapping? - int read(void *buf, size_t count) const; - int write(const void *buf, size_t count) const; - - /** Returns the "socket name" ie the address bound to - * the near end of the socket - */ - std::string getSockname() const; - - /** Returns the "peer name" ie the address bound to - * the remote end of the socket - */ - std::string getPeername() const; - - /** - * Returns an address (host and port) for the remote end of the - * socket - */ - std::string getPeerAddress() const; - /** - * Returns an address (host and port) for the local end of the - * socket - */ - std::string getLocalAddress() const; - - /** - * Returns the full address of the connection: local and remote host and port. - */ - std::string getFullAddress() const { return getLocalAddress()+"-"+getPeerAddress(); } - - uint16_t getLocalPort() const; - uint16_t getRemotePort() const; - - /** - * Returns the error code stored in the socket. This may be used - * to determine the result of a non-blocking connect. - */ - int getError() const; - - int getKeyLen() const; - std::string getClientAuthId() const; - -private: - mutable std::string connectname; - mutable PRFileDesc* socket; - std::string certname; - - /** - * 'model' socket, with configuration to use when importing - * accepted sockets for use as ssl sockets. Set on listen(), used - * in accept to pass through to newly created socket instances. - */ - mutable PRFileDesc* prototype; - - SslSocket(IOHandlePrivate* ioph, PRFileDesc* model); -}; - -}}} -#endif /*!_sys_ssl_Socket_h*/ diff --git a/cpp/src/qpid/sys/ssl/check.cpp b/cpp/src/qpid/sys/ssl/check.cpp deleted file mode 100644 index 72a2e265bd..0000000000 --- a/cpp/src/qpid/sys/ssl/check.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/ssl/check.h" -#include <secerr.h> -#include <sslerr.h> -#include <boost/format.hpp> - -using boost::format; -using boost::str; - -namespace qpid { -namespace sys { -namespace ssl { - -ErrorString::ErrorString() : code(PR_GetError()), buffer(new char[PR_GetErrorTextLength()]), used(PR_GetErrorText(buffer)) {} - -ErrorString::~ErrorString() -{ - delete[] buffer; -} - -std::string ErrorString::getString() const -{ - std::string msg = std::string(buffer, used); - if (!used) { - //seems most of the NSPR/NSS errors don't have text set for - //them, add a few specific ones in here. (TODO: more complete - //list?): - return getErrorString(code); - } else { - return str(format("%1% [%2%]") % msg % code); - } -} - -std::string getErrorString(int code) -{ - std::string msg; - switch (code) { - case SSL_ERROR_EXPORT_ONLY_SERVER: msg = "Unable to communicate securely. Peer does not support high-grade encryption."; break; - case SSL_ERROR_US_ONLY_SERVER: msg = "Unable to communicate securely. Peer requires high-grade encryption which is not supported."; break; - case SSL_ERROR_NO_CYPHER_OVERLAP: msg = "Cannot communicate securely with peer: no common encryption algorithm(s)."; break; - case SSL_ERROR_NO_CERTIFICATE: msg = "Unable to find the certificate or key necessary for authentication."; break; - case SSL_ERROR_BAD_CERTIFICATE: msg = "Unable to communicate securely with peer: peers's certificate was rejected."; break; - case SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE: msg = "Unsupported certificate type."; break; - case SSL_ERROR_WRONG_CERTIFICATE: msg = "Client authentication failed: private key in key database does not correspond to public key in certificate database."; break; - case SSL_ERROR_BAD_CERT_DOMAIN: msg = "Unable to communicate securely with peer: requested domain name does not match the server's certificate."; break; - case SSL_ERROR_BAD_CERT_ALERT: msg = "SSL peer cannot verify your certificate."; break; - case SSL_ERROR_REVOKED_CERT_ALERT: msg = "SSL peer rejected your certificate as revoked."; break; - case SSL_ERROR_EXPIRED_CERT_ALERT: msg = "SSL peer rejected your certificate as expired."; break; - - case PR_DIRECTORY_LOOKUP_ERROR: msg = "A directory lookup on a network address has failed"; break; - case PR_CONNECT_RESET_ERROR: msg = "TCP connection reset by peer"; break; - case PR_END_OF_FILE_ERROR: msg = "Encountered end of file"; break; - case SEC_ERROR_EXPIRED_CERTIFICATE: msg = "Peer's certificate has expired"; break; - default: msg = (code < -6000) ? "NSS error" : "NSPR error"; break; - } - return str(format("%1% [%2%]") % msg % code); -} - -std::ostream& operator<<(std::ostream& out, const ErrorString& err) -{ - out << err.getString(); - return out; -} - - -}}} // namespace qpid::sys::ssl diff --git a/cpp/src/qpid/sys/ssl/check.h b/cpp/src/qpid/sys/ssl/check.h deleted file mode 100644 index 28d3c74ad0..0000000000 --- a/cpp/src/qpid/sys/ssl/check.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QPID_SYS_SSL_CHECK_H -#define QPID_SYS_SSL_CHECK_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/Msg.h" - -#include <iostream> -#include <string> -#include <nspr.h> -#include <nss.h> - -namespace qpid { -namespace sys { -namespace ssl { - -std::string getErrorString(int code); - -class ErrorString -{ - public: - ErrorString(); - ~ErrorString(); - std::string getString() const; - private: - const int code; - char* const buffer; - const size_t used; -}; - -std::ostream& operator<<(std::ostream& out, const ErrorString& err); - -}}} // namespace qpid::sys::ssl - - -#define NSS_CHECK(value) if (value != SECSuccess) { throw Exception(QPID_MSG("Failed: " << qpid::sys::ssl::ErrorString())); } -#define PR_CHECK(value) if (value != PR_SUCCESS) { throw Exception(QPID_MSG("Failed: " << qpid::sys::ssl::ErrorString())); } - -#endif /*!QPID_SYS_SSL_CHECK_H*/ diff --git a/cpp/src/qpid/sys/ssl/util.cpp b/cpp/src/qpid/sys/ssl/util.cpp deleted file mode 100644 index 3078e894df..0000000000 --- a/cpp/src/qpid/sys/ssl/util.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/ssl/util.h" -#include "qpid/sys/ssl/check.h" -#include "qpid/Exception.h" -#include "qpid/sys/SystemInfo.h" - -#include <unistd.h> -#include <nspr.h> -#include <nss.h> -#include <pk11pub.h> -#include <ssl.h> - -#include <iostream> -#include <fstream> -#include <boost/filesystem/operations.hpp> -#include <boost/filesystem/path.hpp> - -namespace qpid { -namespace sys { -namespace ssl { - -static const std::string LOCALHOST("127.0.0.1"); - -std::string defaultCertName() -{ - Address address; - if (SystemInfo::getLocalHostname(address)) { - return address.host; - } else { - return LOCALHOST; - } -} - -SslOptions::SslOptions() : qpid::Options("SSL Settings"), - certName(defaultCertName()), - exportPolicy(false) -{ - addOptions() - ("ssl-use-export-policy", optValue(exportPolicy), "Use NSS export policy") - ("ssl-cert-password-file", optValue(certPasswordFile, "PATH"), "File containing password to use for accessing certificate database") - ("ssl-cert-db", optValue(certDbPath, "PATH"), "Path to directory containing certificate database") - ("ssl-cert-name", optValue(certName, "NAME"), "Name of the certificate to use"); -} - -SslOptions& SslOptions::operator=(const SslOptions& o) -{ - certDbPath = o.certDbPath; - certName = o.certName; - certPasswordFile = o.certPasswordFile; - exportPolicy = o.exportPolicy; - return *this; -} - -char* promptForPassword(PK11SlotInfo*, PRBool retry, void*) -{ - if (retry) return 0; - //TODO: something else? - return PL_strdup(getpass("Please enter the password for accessing the certificate database:")); -} - -SslOptions SslOptions::global; - -char* readPasswordFromFile(PK11SlotInfo*, PRBool retry, void*) -{ - const std::string& passwordFile = SslOptions::global.certPasswordFile; - if (retry || passwordFile.empty() || !boost::filesystem::exists(passwordFile)) { - return 0; - } else { - std::ifstream file(passwordFile.c_str()); - std::string password; - file >> password; - return PL_strdup(password.c_str()); - } -} - -void initNSS(const SslOptions& options, bool server) -{ - SslOptions::global = options; - if (options.certPasswordFile.empty()) { - PK11_SetPasswordFunc(promptForPassword); - } else { - PK11_SetPasswordFunc(readPasswordFromFile); - } - NSS_CHECK(NSS_Init(options.certDbPath.c_str())); - if (options.exportPolicy) { - NSS_CHECK(NSS_SetExportPolicy()); - } else { - NSS_CHECK(NSS_SetDomesticPolicy()); - } - if (server) { - //use defaults for all args, TODO: may want to make this configurable - SSL_ConfigServerSessionIDCache(0, 0, 0, 0); - } -} - -void shutdownNSS() -{ - NSS_Shutdown(); -} - -}}} // namespace qpid::sys::ssl diff --git a/cpp/src/qpid/sys/ssl/util.h b/cpp/src/qpid/sys/ssl/util.h deleted file mode 100644 index f34adab7be..0000000000 --- a/cpp/src/qpid/sys/ssl/util.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_SYS_SSL_UTIL_H -#define QPID_SYS_SSL_UTIL_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Options.h" -#include <string> - -namespace qpid { -namespace sys { -namespace ssl { - -struct SslOptions : qpid::Options -{ - static SslOptions global; - - std::string certDbPath; - std::string certName; - std::string certPasswordFile; - bool exportPolicy; - - SslOptions(); - SslOptions& operator=(const SslOptions&); -}; - -void initNSS(const SslOptions& options, bool server = false); -void shutdownNSS(); - -}}} // namespace qpid::sys::ssl - -#endif /*!QPID_SYS_SSL_UTIL_H*/ diff --git a/cpp/src/qpid/sys/uuid.h b/cpp/src/qpid/sys/uuid.h deleted file mode 100644 index 804ab34463..0000000000 --- a/cpp/src/qpid/sys/uuid.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _sys_uuid_h -#define _sys_uuid_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifdef _WIN32 -# include "qpid/sys/windows/uuid.h" -#else -# include <uuid/uuid.h> -#endif /* _WIN32 */ - -#endif /* _sys_uuid_h */ diff --git a/cpp/src/qpid/sys/windows/AsynchIO.cpp b/cpp/src/qpid/sys/windows/AsynchIO.cpp deleted file mode 100644 index 71138757a5..0000000000 --- a/cpp/src/qpid/sys/windows/AsynchIO.cpp +++ /dev/null @@ -1,755 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/windows/AsynchIoResult.h" -#include "qpid/sys/windows/IoHandlePrivate.h" -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Time.h" -#include "qpid/log/Statement.h" - -#include "qpid/sys/windows/check.h" -#include "qpid/sys/windows/mingw32_compat.h" - -#include <boost/thread/once.hpp> - -#include <queue> -#include <winsock2.h> -#include <mswsock.h> -#include <windows.h> - -#include <boost/bind.hpp> - -namespace { - - typedef qpid::sys::ScopedLock<qpid::sys::Mutex> QLock; - -/* - * The function pointers for AcceptEx and ConnectEx need to be looked up - * at run time. Make sure this is done only once. - */ -boost::once_flag lookUpAcceptExOnce = BOOST_ONCE_INIT; -LPFN_ACCEPTEX fnAcceptEx = 0; -typedef void (*lookUpFunc)(const qpid::sys::Socket &); - -void lookUpAcceptEx() { - SOCKET h = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - GUID guidAcceptEx = WSAID_ACCEPTEX; - DWORD dwBytes = 0; - WSAIoctl(h, - SIO_GET_EXTENSION_FUNCTION_POINTER, - &guidAcceptEx, - sizeof(guidAcceptEx), - &fnAcceptEx, - sizeof(fnAcceptEx), - &dwBytes, - NULL, - NULL); - closesocket(h); - if (fnAcceptEx == 0) - throw qpid::Exception(QPID_MSG("Failed to look up AcceptEx")); -} - -} - -namespace qpid { -namespace sys { -namespace windows { - -/* - * Asynch Acceptor - * - */ -class AsynchAcceptor : public qpid::sys::AsynchAcceptor { - - friend class AsynchAcceptResult; - -public: - AsynchAcceptor(const Socket& s, AsynchAcceptor::Callback callback); - ~AsynchAcceptor(); - void start(Poller::shared_ptr poller); - -private: - void restart(void); - - AsynchAcceptor::Callback acceptedCallback; - const Socket& socket; -}; - -AsynchAcceptor::AsynchAcceptor(const Socket& s, Callback callback) - : acceptedCallback(callback), - socket(s) { - - s.setNonblocking(); -#if (BOOST_VERSION >= 103500) /* boost 1.35 or later reversed the args */ - boost::call_once(lookUpAcceptExOnce, lookUpAcceptEx); -#else - boost::call_once(lookUpAcceptEx, lookUpAcceptExOnce); -#endif -} - -AsynchAcceptor::~AsynchAcceptor() -{ - socket.close(); -} - -void AsynchAcceptor::start(Poller::shared_ptr poller) { - PollerHandle ph = PollerHandle(socket); - poller->monitorHandle(ph, Poller::INPUT); - restart (); -} - -void AsynchAcceptor::restart(void) { - DWORD bytesReceived = 0; // Not used, needed for AcceptEx API - AsynchAcceptResult *result = new AsynchAcceptResult(acceptedCallback, - this, - toSocketHandle(socket)); - BOOL status; - status = ::fnAcceptEx(toSocketHandle(socket), - toSocketHandle(*result->newSocket), - result->addressBuffer, - 0, - AsynchAcceptResult::SOCKADDRMAXLEN, - AsynchAcceptResult::SOCKADDRMAXLEN, - &bytesReceived, - result->overlapped()); - QPID_WINDOWS_CHECK_ASYNC_START(status); -} - - -AsynchAcceptResult::AsynchAcceptResult(AsynchAcceptor::Callback cb, - AsynchAcceptor *acceptor, - SOCKET listener) - : callback(cb), acceptor(acceptor), listener(listener) { - newSocket.reset (new Socket()); -} - -void AsynchAcceptResult::success(size_t /*bytesTransferred*/) { - ::setsockopt (toSocketHandle(*newSocket), - SOL_SOCKET, - SO_UPDATE_ACCEPT_CONTEXT, - (char*)&listener, - sizeof (listener)); - callback(*(newSocket.release())); - acceptor->restart (); - delete this; -} - -void AsynchAcceptResult::failure(int /*status*/) { - //if (status != WSA_OPERATION_ABORTED) - // Can there be anything else? ; - delete this; -} - -/* - * AsynchConnector does synchronous connects for now... to do asynch the - * IocpPoller will need some extension to register an event handle as a - * CONNECT-type "direction", the connect completion/result will need an - * event handle to associate with the connecting handle. But there's no - * time for that right now... - */ -class AsynchConnector : public qpid::sys::AsynchConnector { -private: - ConnectedCallback connCallback; - FailedCallback failCallback; - const Socket& socket; - const std::string hostname; - const uint16_t port; - -public: - AsynchConnector(const Socket& socket, - std::string hostname, - uint16_t port, - ConnectedCallback connCb, - FailedCallback failCb = 0); - void start(Poller::shared_ptr poller); -}; - -AsynchConnector::AsynchConnector(const Socket& sock, - std::string hname, - uint16_t p, - ConnectedCallback connCb, - FailedCallback failCb) : - connCallback(connCb), failCallback(failCb), socket(sock), - hostname(hname), port(p) -{ -} - -void AsynchConnector::start(Poller::shared_ptr) -{ - try { - socket.connect(hostname, port); - socket.setNonblocking(); - connCallback(socket); - } catch(std::exception& e) { - if (failCallback) - failCallback(socket, -1, std::string(e.what())); - socket.close(); - } -} - -} // namespace windows - -AsynchAcceptor* AsynchAcceptor::create(const Socket& s, - Callback callback) -{ - return new windows::AsynchAcceptor(s, callback); -} - -AsynchConnector* qpid::sys::AsynchConnector::create(const Socket& s, - std::string hostname, - uint16_t port, - ConnectedCallback connCb, - FailedCallback failCb) -{ - return new windows::AsynchConnector(s, - hostname, - port, - connCb, - failCb); -} - - -/* - * Asynch reader/writer - */ - -namespace windows { - -class AsynchIO : public qpid::sys::AsynchIO { -public: - AsynchIO(const Socket& s, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0); - ~AsynchIO(); - - // Methods inherited from qpid::sys::AsynchIO - - /** - * Notify the object is should delete itself as soon as possible. - */ - virtual void queueForDeletion(); - - /// Take any actions needed to prepare for working with the poller. - virtual void start(Poller::shared_ptr poller); - virtual void queueReadBuffer(BufferBase* buff); - virtual void unread(BufferBase* buff); - virtual void queueWrite(BufferBase* buff); - virtual void notifyPendingWrite(); - virtual void queueWriteClose(); - virtual bool writeQueueEmpty(); - virtual void startReading(); - virtual void stopReading(); - virtual void requestCallback(RequestCallback); - - /** - * getQueuedBuffer returns a buffer from the buffer queue, if one is - * available. - * - * @retval Pointer to BufferBase buffer; 0 if none is available. - */ - virtual BufferBase* getQueuedBuffer(); - -private: - ReadCallback readCallback; - EofCallback eofCallback; - DisconnectCallback disCallback; - ClosedCallback closedCallback; - BuffersEmptyCallback emptyCallback; - IdleCallback idleCallback; - const Socket& socket; - Poller::shared_ptr poller; - - std::deque<BufferBase*> bufferQueue; - std::deque<BufferBase*> writeQueue; - /* The MSVC-supplied deque is not thread-safe; keep locks to serialize - * access to the buffer queue and write queue. - */ - Mutex bufferQueueLock; - - // Number of outstanding I/O operations. - volatile LONG opsInProgress; - // Is there a write in progress? - volatile bool writeInProgress; - // Deletion requested, but there are callbacks in progress. - volatile bool queuedDelete; - // Socket close requested, but there are operations in progress. - volatile bool queuedClose; - -private: - // Dispatch events that have completed. - void notifyEof(void); - void notifyDisconnect(void); - void notifyClosed(void); - void notifyBuffersEmpty(void); - void notifyIdle(void); - - /** - * Initiate a write of the specified buffer. There's no callback for - * write completion to the AsynchIO object. - */ - void startWrite(AsynchIO::BufferBase* buff); - - void close(void); - - /** - * readComplete is called when a read request is complete. - * - * @param result Results of the operation. - */ - void readComplete(AsynchReadResult *result); - - /** - * writeComplete is called when a write request is complete. - * - * @param result Results of the operation. - */ - void writeComplete(AsynchWriteResult *result); - - /** - * Queue of completions to run. This queue enforces the requirement - * from upper layers that only one thread at a time is allowed to act - * on any given connection. Once a thread is busy processing a completion - * on this object, other threads that dispatch completions queue the - * completions here for the in-progress thread to handle when done. - * Thus, any threads can dispatch a completion from the IocpPoller, but - * this class ensures that actual processing at the connection level is - * only on one thread at a time. - */ - std::queue<AsynchIoResult *> completionQueue; - volatile bool working; - Mutex completionLock; - - /** - * Called when there's a completion to process. - */ - void completion(AsynchIoResult *result); -}; - -// This is used to encapsulate pure callbacks into a handle -class CallbackHandle : public IOHandle { -public: - CallbackHandle(AsynchIoResult::Completer completeCb, - AsynchIO::RequestCallback reqCb = 0) : - IOHandle(new IOHandlePrivate (INVALID_SOCKET, completeCb, reqCb)) - {} -}; - -AsynchIO::AsynchIO(const Socket& s, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb, - BuffersEmptyCallback eCb, - IdleCallback iCb) : - - readCallback(rCb), - eofCallback(eofCb), - disCallback(disCb), - closedCallback(cCb), - emptyCallback(eCb), - idleCallback(iCb), - socket(s), - opsInProgress(0), - writeInProgress(false), - queuedDelete(false), - queuedClose(false), - working(false) { -} - -struct deleter -{ - template <typename T> - void operator()(T *ptr){ delete ptr;} -}; - -AsynchIO::~AsynchIO() { - std::for_each( bufferQueue.begin(), bufferQueue.end(), deleter()); - std::for_each( writeQueue.begin(), writeQueue.end(), deleter()); -} - -void AsynchIO::queueForDeletion() { - queuedDelete = true; - if (opsInProgress > 0) { - QPID_LOG(info, "Delete AsynchIO queued; ops in progress"); - // AsynchIOHandler calls this then deletes itself; don't do any more - // callbacks. - readCallback = 0; - eofCallback = 0; - disCallback = 0; - closedCallback = 0; - emptyCallback = 0; - idleCallback = 0; - } - else { - delete this; - } -} - -void AsynchIO::start(Poller::shared_ptr poller0) { - PollerHandle ph = PollerHandle(socket); - poller = poller0; - poller->monitorHandle(ph, Poller::INPUT); - if (writeQueue.size() > 0) // Already have data queued for write - notifyPendingWrite(); - startReading(); -} - -void AsynchIO::queueReadBuffer(AsynchIO::BufferBase* buff) { - assert(buff); - buff->dataStart = 0; - buff->dataCount = 0; - QLock l(bufferQueueLock); - bufferQueue.push_back(buff); -} - -void AsynchIO::unread(AsynchIO::BufferBase* buff) { - assert(buff); - buff->squish(); - QLock l(bufferQueueLock); - bufferQueue.push_front(buff); -} - -void AsynchIO::queueWrite(AsynchIO::BufferBase* buff) { - assert(buff); - QLock l(bufferQueueLock); - writeQueue.push_back(buff); - if (!writeInProgress) - notifyPendingWrite(); -} - -void AsynchIO::notifyPendingWrite() { - // This method is generally called from a processing thread; transfer - // work on this to an I/O thread. Much of the upper layer code assumes - // that all I/O-related things happen in an I/O thread. - if (poller == 0) // Not really going yet... - return; - - InterlockedIncrement(&opsInProgress); - PollerHandle ph(CallbackHandle(boost::bind(&AsynchIO::completion, this, _1))); - poller->monitorHandle(ph, Poller::OUTPUT); -} - -void AsynchIO::queueWriteClose() { - queuedClose = true; - if (!writeInProgress) - notifyPendingWrite(); -} - -bool AsynchIO::writeQueueEmpty() { - QLock l(bufferQueueLock); - return writeQueue.size() == 0; -} - -/* - * Initiate a read operation. AsynchIO::readComplete() will be - * called when the read is complete and data is available. - */ -void AsynchIO::startReading() { - if (queuedDelete) - return; - - // (Try to) get a buffer; look on the front since there may be an - // "unread" one there with data remaining from last time. - AsynchIO::BufferBase *buff = 0; - { - QLock l(bufferQueueLock); - - if (!bufferQueue.empty()) { - buff = bufferQueue.front(); - assert(buff); - bufferQueue.pop_front(); - } - } - if (buff != 0) { - int readCount = buff->byteCount - buff->dataCount; - AsynchReadResult *result = - new AsynchReadResult(boost::bind(&AsynchIO::completion, this, _1), - buff, - readCount); - DWORD bytesReceived = 0, flags = 0; - InterlockedIncrement(&opsInProgress); - int status = WSARecv(toSocketHandle(socket), - const_cast<LPWSABUF>(result->getWSABUF()), 1, - &bytesReceived, - &flags, - result->overlapped(), - 0); - if (status != 0) { - int error = WSAGetLastError(); - if (error != WSA_IO_PENDING) { - result->failure(error); - result = 0; // result is invalid here - return; - } - } - // On status 0 or WSA_IO_PENDING, completion will handle the rest. - } - else { - notifyBuffersEmpty(); - } - return; -} - -// stopReading was added to prevent a race condition with read-credit on Linux. -// It may or may not be required on windows. -// -// AsynchIOHandler::readbuff() calls stopReading() inside the same -// critical section that protects startReading() in -// AsynchIOHandler::giveReadCredit(). -// -void AsynchIO::stopReading() {} - -// Queue the specified callback for invocation from an I/O thread. -void AsynchIO::requestCallback(RequestCallback callback) { - // This method is generally called from a processing thread; transfer - // work on this to an I/O thread. Much of the upper layer code assumes - // that all I/O-related things happen in an I/O thread. - if (poller == 0) // Not really going yet... - return; - - InterlockedIncrement(&opsInProgress); - PollerHandle ph(CallbackHandle( - boost::bind(&AsynchIO::completion, this, _1), - callback)); - poller->monitorHandle(ph, Poller::INPUT); -} - -/** - * Return a queued buffer if there are enough to spare. - */ -AsynchIO::BufferBase* AsynchIO::getQueuedBuffer() { - QLock l(bufferQueueLock); - // Always keep at least one buffer (it might have data that was - // "unread" in it). - if (bufferQueue.size() <= 1) - return 0; - BufferBase* buff = bufferQueue.back(); - assert(buff); - bufferQueue.pop_back(); - return buff; -} - -void AsynchIO::notifyEof(void) { - if (eofCallback) - eofCallback(*this); -} - -void AsynchIO::notifyDisconnect(void) { - if (disCallback) - disCallback(*this); -} - -void AsynchIO::notifyClosed(void) { - if (closedCallback) - closedCallback(*this, socket); -} - -void AsynchIO::notifyBuffersEmpty(void) { - if (emptyCallback) - emptyCallback(*this); -} - -void AsynchIO::notifyIdle(void) { - if (idleCallback) - idleCallback(*this); -} - -/* - * Asynch reader/writer using overlapped I/O - */ - -void AsynchIO::startWrite(AsynchIO::BufferBase* buff) { - writeInProgress = true; - InterlockedIncrement(&opsInProgress); - AsynchWriteResult *result = - new AsynchWriteResult(boost::bind(&AsynchIO::completion, this, _1), - buff, - buff->dataCount); - DWORD bytesSent = 0; - int status = WSASend(toSocketHandle(socket), - const_cast<LPWSABUF>(result->getWSABUF()), 1, - &bytesSent, - 0, - result->overlapped(), - 0); - if (status != 0) { - int error = WSAGetLastError(); - if (error != WSA_IO_PENDING) { - result->failure(error); // Also decrements in-progress count - result = 0; // result is invalid here - return; - } - } - // On status 0 or WSA_IO_PENDING, completion will handle the rest. - return; -} - -/* - * Close the socket and callback to say we've done it - */ -void AsynchIO::close(void) { - socket.close(); - notifyClosed(); -} - -void AsynchIO::readComplete(AsynchReadResult *result) { - int status = result->getStatus(); - size_t bytes = result->getTransferred(); - if (status == 0 && bytes > 0) { - bool restartRead = true; // May not if receiver doesn't want more - if (readCallback) - readCallback(*this, result->getBuff()); - if (restartRead) - startReading(); - } - else { - // No data read, so put the buffer back. It may be partially filled, - // so "unread" it back to the front of the queue. - unread(result->getBuff()); - notifyEof(); - if (status != 0) - { - notifyDisconnect(); - } - } -} - -/* - * NOTE - this completion is called for completed writes and also when - * a write is desired. The difference is in the buff - if a write is desired - * the buff is 0. - */ -void AsynchIO::writeComplete(AsynchWriteResult *result) { - int status = result->getStatus(); - size_t bytes = result->getTransferred(); - AsynchIO::BufferBase *buff = result->getBuff(); - if (buff != 0) { - writeInProgress = false; - if (status == 0 && bytes > 0) { - if (bytes < result->getRequested()) // Still more to go; resubmit - startWrite(buff); - else - queueReadBuffer(buff); // All done; back to the pool - } - else { - // An error... if it's a connection close, ignore it - it will be - // noticed and handled on a read completion any moment now. - // What to do with real error??? Save the Buffer? - } - } - - // If there are no writes outstanding, check for more writes to initiate - // (either queued or via idle). The opsInProgress count is handled in - // completion() - if (!writeInProgress) { - bool writing = false; - { - QLock l(bufferQueueLock); - if (writeQueue.size() > 0) { - buff = writeQueue.front(); - assert(buff); - writeQueue.pop_front(); - startWrite(buff); - writing = true; - } - } - if (!writing && !queuedClose) { - notifyIdle(); - } - } - return; -} - -void AsynchIO::completion(AsynchIoResult *result) { - { - ScopedLock<Mutex> l(completionLock); - if (working) { - completionQueue.push(result); - return; - } - - // First thread in with something to do; note we're working then keep - // handling completions. - working = true; - while (result != 0) { - // New scope to unlock temporarily. - { - ScopedUnlock<Mutex> ul(completionLock); - AsynchReadResult *r = dynamic_cast<AsynchReadResult*>(result); - if (r != 0) - readComplete(r); - else { - AsynchWriteResult *w = - dynamic_cast<AsynchWriteResult*>(result); - if (w != 0) - writeComplete(w); - else { - AsynchCallbackRequest *req = - dynamic_cast<AsynchCallbackRequest*>(result); - req->reqCallback(*this); - } - } - delete result; - result = 0; - InterlockedDecrement(&opsInProgress); - } - // Lock is held again. - if (completionQueue.empty()) - continue; - result = completionQueue.front(); - completionQueue.pop(); - } - working = false; - } - // Lock released; ok to close if ops are done and close requested. - // Layer above will call back to queueForDeletion() if it hasn't - // already been done. If it already has, go ahead and delete. - if (opsInProgress == 0) { - if (queuedClose) - // close() may cause a delete; don't trust 'this' on return - close(); - else if (queuedDelete) - delete this; - } -} - -} // namespace windows - -AsynchIO* qpid::sys::AsynchIO::create(const Socket& s, - AsynchIO::ReadCallback rCb, - AsynchIO::EofCallback eofCb, - AsynchIO::DisconnectCallback disCb, - AsynchIO::ClosedCallback cCb, - AsynchIO::BuffersEmptyCallback eCb, - AsynchIO::IdleCallback iCb) -{ - return new qpid::sys::windows::AsynchIO(s, rCb, eofCb, disCb, cCb, eCb, iCb); -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/windows/AsynchIoResult.h b/cpp/src/qpid/sys/windows/AsynchIoResult.h deleted file mode 100755 index b11324918b..0000000000 --- a/cpp/src/qpid/sys/windows/AsynchIoResult.h +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef _windows_asynchIoResult_h -#define _windows_asynchIoResult_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/Socket.h" -#include <memory.h> -#include <winsock2.h> -#include <ws2tcpip.h> - -namespace qpid { -namespace sys { -namespace windows { - -/* - * AsynchIoResult defines the class that receives the result of an - * asynchronous I/O operation, either send/recv or accept/connect. - * - * Operation factories should set one of these up before beginning the - * operation. Poller knows how to dispatch completion to this class. - * This class must be subclassed for needed operations; this class provides - * an interface only and cannot be instantiated. - * - * This class is tied to Windows; it inherits from OVERLAPPED so that the - * IocpPoller can cast OVERLAPPED pointers back to AsynchIoResult and call - * the completion handler. - */ -class AsynchResult : private OVERLAPPED { -public: - LPOVERLAPPED overlapped(void) { return this; } - static AsynchResult* from_overlapped(LPOVERLAPPED ol) { - return static_cast<AsynchResult*>(ol); - } - virtual void success (size_t bytesTransferred) { - bytes = bytesTransferred; - status = 0; - complete(); - } - virtual void failure (int error) { - bytes = 0; - status = error; - complete(); - } - size_t getTransferred(void) const { return bytes; } - int getStatus(void) const { return status; } - -protected: - AsynchResult() : bytes(0), status(0) - { memset(overlapped(), 0, sizeof(OVERLAPPED)); } - ~AsynchResult() {} - virtual void complete(void) = 0; - - size_t bytes; - int status; -}; - -class AsynchAcceptor; - -class AsynchAcceptResult : public AsynchResult { - - friend class AsynchAcceptor; - -public: - AsynchAcceptResult(qpid::sys::AsynchAcceptor::Callback cb, - AsynchAcceptor *acceptor, - SOCKET listener); - virtual void success (size_t bytesTransferred); - virtual void failure (int error); - -private: - virtual void complete(void) {} // No-op for this class. - - std::auto_ptr<qpid::sys::Socket> newSocket; - qpid::sys::AsynchAcceptor::Callback callback; - AsynchAcceptor *acceptor; - SOCKET listener; - - // AcceptEx needs a place to write the local and remote addresses - // when accepting the connection. Place those here; get enough for - // IPv6 addresses, even if the socket is IPv4. - enum { SOCKADDRMAXLEN = sizeof(sockaddr_in6) + 16, - SOCKADDRBUFLEN = 2 * SOCKADDRMAXLEN }; - char addressBuffer[SOCKADDRBUFLEN]; -}; - -class AsynchIoResult : public AsynchResult { -public: - typedef boost::function1<void, AsynchIoResult *> Completer; - - virtual ~AsynchIoResult() {} - qpid::sys::AsynchIO::BufferBase *getBuff(void) const { return iobuff; } - size_t getRequested(void) const { return requested; } - const WSABUF *getWSABUF(void) const { return &wsabuf; } - -protected: - void setBuff (qpid::sys::AsynchIO::BufferBase *buffer) { iobuff = buffer; } - -protected: - AsynchIoResult(Completer cb, - qpid::sys::AsynchIO::BufferBase *buff, size_t length) - : completionCallback(cb), iobuff(buff), requested(length) {} - - virtual void complete(void) = 0; - WSABUF wsabuf; - Completer completionCallback; - -private: - qpid::sys::AsynchIO::BufferBase *iobuff; - size_t requested; // Number of bytes in original I/O request -}; - -class AsynchReadResult : public AsynchIoResult { - - // complete() updates buffer then does completion callback. - virtual void complete(void) { - getBuff()->dataCount += bytes; - completionCallback(this); - } - -public: - AsynchReadResult(AsynchIoResult::Completer cb, - qpid::sys::AsynchIO::BufferBase *buff, - size_t length) - : AsynchIoResult(cb, buff, length) { - wsabuf.buf = buff->bytes + buff->dataCount; - wsabuf.len = length; - } -}; - -class AsynchWriteResult : public AsynchIoResult { - - // complete() updates buffer then does completion callback. - virtual void complete(void) { - qpid::sys::AsynchIO::BufferBase *b = getBuff(); - b->dataStart += bytes; - b->dataCount -= bytes; - completionCallback(this); - } - -public: - AsynchWriteResult(AsynchIoResult::Completer cb, - qpid::sys::AsynchIO::BufferBase *buff, - size_t length) - : AsynchIoResult(cb, buff, length) { - wsabuf.buf = buff ? buff->bytes : 0; - wsabuf.len = length; - } -}; - -class AsynchWriteWanted : public AsynchWriteResult { - - // complete() just does completion callback; no buffers used. - virtual void complete(void) { - completionCallback(this); - } - -public: - AsynchWriteWanted(AsynchIoResult::Completer cb) - : AsynchWriteResult(cb, 0, 0) { - wsabuf.buf = 0; - wsabuf.len = 0; - } -}; - -class AsynchCallbackRequest : public AsynchIoResult { - // complete() needs to simply call the completionCallback; no buffers. - virtual void complete(void) { - completionCallback(this); - } - -public: - AsynchCallbackRequest(AsynchIoResult::Completer cb, - qpid::sys::AsynchIO::RequestCallback reqCb) - : AsynchIoResult(cb, 0, 0), reqCallback(reqCb) { - wsabuf.buf = 0; - wsabuf.len = 0; - } - - qpid::sys::AsynchIO::RequestCallback reqCallback; -}; - -}}} // qpid::sys::windows - -#endif /*!_windows_asynchIoResult_h*/ diff --git a/cpp/src/qpid/sys/windows/FileSysDir.cpp b/cpp/src/qpid/sys/windows/FileSysDir.cpp deleted file mode 100644 index 88f1637d48..0000000000 --- a/cpp/src/qpid/sys/windows/FileSysDir.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/FileSysDir.h" -#include "qpid/sys/StrError.h" -#include "qpid/Exception.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <direct.h> -#include <errno.h> - -namespace qpid { -namespace sys { - -bool FileSysDir::exists (void) const -{ - const char *cpath = dirPath.c_str (); - struct _stat s; - if (::_stat(cpath, &s)) { - if (errno == ENOENT) { - return false; - } - throw qpid::Exception (strError(errno) + - ": Can't check directory: " + dirPath); - } - if (s.st_mode & _S_IFDIR) - return true; - throw qpid::Exception(dirPath + " is not a directory"); -} - -void FileSysDir::mkdir(void) -{ - if (::_mkdir(dirPath.c_str()) == -1) - throw Exception ("Can't create directory: " + dirPath); -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/windows/IOHandle.cpp b/cpp/src/qpid/sys/windows/IOHandle.cpp deleted file mode 100755 index 250737cb99..0000000000 --- a/cpp/src/qpid/sys/windows/IOHandle.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/windows/IoHandlePrivate.h" -#include <windows.h> - -namespace qpid { -namespace sys { - -SOCKET toFd(const IOHandlePrivate* h) -{ - return h->fd; -} - -IOHandle::IOHandle(IOHandlePrivate* h) : - impl(h) -{} - -IOHandle::~IOHandle() { - delete impl; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/windows/IoHandlePrivate.h b/cpp/src/qpid/sys/windows/IoHandlePrivate.h deleted file mode 100755 index 5943db5cc7..0000000000 --- a/cpp/src/qpid/sys/windows/IoHandlePrivate.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _sys_windows_IoHandlePrivate_h -#define _sys_windows_IoHandlePrivate_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/windows/AsynchIoResult.h" -#include "qpid/CommonImportExport.h" - -#include <winsock2.h> - -namespace qpid { -namespace sys { - -// Private fd related implementation details -// There should be either a valid socket handle or a completer callback. -// Handle is used to associate with poller's iocp; completer is used to -// inject a completion that will very quickly trigger a callback to the -// completer from an I/O thread. If the callback mechanism is used, there -// can be a RequestCallback set - this carries the callback object through -// from AsynchIO::requestCallback() through to the I/O completion processing. -class IOHandlePrivate { - friend QPID_COMMON_EXTERN SOCKET toSocketHandle(const Socket& s); - static IOHandlePrivate* getImpl(const IOHandle& h); - -public: - IOHandlePrivate(SOCKET f = INVALID_SOCKET, - windows::AsynchIoResult::Completer cb = 0, - AsynchIO::RequestCallback reqCallback = 0) : - fd(f), event(cb), cbRequest(reqCallback) - {} - - SOCKET fd; - windows::AsynchIoResult::Completer event; - AsynchIO::RequestCallback cbRequest; -}; - -QPID_COMMON_EXTERN SOCKET toSocketHandle(const Socket& s); - -}} - -#endif /* _sys_windows_IoHandlePrivate_h */ diff --git a/cpp/src/qpid/sys/windows/IocpPoller.cpp b/cpp/src/qpid/sys/windows/IocpPoller.cpp deleted file mode 100755 index 1805dd2cd8..0000000000 --- a/cpp/src/qpid/sys/windows/IocpPoller.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Poller.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Dispatcher.h" - -#include "qpid/sys/windows/AsynchIoResult.h" -#include "qpid/sys/windows/IoHandlePrivate.h" -#include "qpid/sys/windows/check.h" - -#include <winsock2.h> -#include <windows.h> - -#include <assert.h> -#include <vector> -#include <exception> - -namespace qpid { -namespace sys { - -class PollerHandlePrivate { - friend class Poller; - friend class PollerHandle; - - SOCKET fd; - windows::AsynchIoResult::Completer cb; - AsynchIO::RequestCallback cbRequest; - - PollerHandlePrivate(SOCKET f, - windows::AsynchIoResult::Completer cb0 = 0, - AsynchIO::RequestCallback rcb = 0) - : fd(f), cb(cb0), cbRequest(rcb) - { - } - -}; - -PollerHandle::PollerHandle(const IOHandle& h) : - impl(new PollerHandlePrivate(toSocketHandle(static_cast<const Socket&>(h)), h.impl->event, h.impl->cbRequest)) -{} - -PollerHandle::~PollerHandle() { - delete impl; -} - -/** - * Concrete implementation of Poller to use the Windows I/O Completion - * port (IOCP) facility. - */ -class PollerPrivate { - friend class Poller; - - const HANDLE iocp; - - // The number of threads running the event loop. - volatile LONG threadsRunning; - - // Shutdown request is handled by setting isShutdown and injecting a - // well-formed completion event into the iocp. - bool isShutdown; - - PollerPrivate() : - iocp(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)), - threadsRunning(0), - isShutdown(false) { - QPID_WINDOWS_CHECK_NULL(iocp); - } - - ~PollerPrivate() { - // It's probably okay to ignore any errors here as there can't be - // data loss - ::CloseHandle(iocp); - } -}; - -void Poller::shutdown() { - // Allow sloppy code to shut us down more than once. - if (impl->isShutdown) - return; - ULONG_PTR key = 1; // Tell wait() it's a shutdown, not I/O - PostQueuedCompletionStatus(impl->iocp, 0, key, 0); -} - -bool Poller::hasShutdown() -{ - return impl->isShutdown; -} - -bool Poller::interrupt(PollerHandle&) { - return false; // There's no concept of a registered handle. -} - -void Poller::run() { - do { - Poller::Event event = this->wait(); - - // Handle shutdown - switch (event.type) { - case Poller::SHUTDOWN: - return; - break; - case Poller::INVALID: // On any type of success or fail completion - break; - default: - // This should be impossible - assert(false); - } - } while (true); -} - -void Poller::monitorHandle(PollerHandle& handle, Direction dir) { - HANDLE h = (HANDLE)(handle.impl->fd); - if (h != INVALID_HANDLE_VALUE) { - HANDLE iocpHandle = ::CreateIoCompletionPort (h, impl->iocp, 0, 0); - QPID_WINDOWS_CHECK_NULL(iocpHandle); - } - else { - // INPUT is used to request a callback; OUTPUT to request a write - assert(dir == Poller::INPUT || dir == Poller::OUTPUT); - - if (dir == Poller::OUTPUT) { - windows::AsynchWriteWanted *result = - new windows::AsynchWriteWanted(handle.impl->cb); - PostQueuedCompletionStatus(impl->iocp, 0, 0, result->overlapped()); - } - else { - windows::AsynchCallbackRequest *result = - new windows::AsynchCallbackRequest(handle.impl->cb, - handle.impl->cbRequest); - PostQueuedCompletionStatus(impl->iocp, 0, 0, result->overlapped()); - } - } -} - -// All no-ops... -void Poller::unmonitorHandle(PollerHandle& /*handle*/, Direction /*dir*/) {} -void Poller::registerHandle(PollerHandle& /*handle*/) {} -void Poller::unregisterHandle(PollerHandle& /*handle*/) {} - -Poller::Event Poller::wait(Duration timeout) { - DWORD timeoutMs = 0; - DWORD numTransferred = 0; - ULONG_PTR completionKey = 0; - OVERLAPPED *overlapped = 0; - windows::AsynchResult *result = 0; - - // Wait for either an I/O operation to finish (thus signaling the - // IOCP handle) or a shutdown request to be made (thus signaling the - // shutdown event). - if (timeout == TIME_INFINITE) - timeoutMs = INFINITE; - else - timeoutMs = static_cast<DWORD>(timeout / TIME_MSEC); - - InterlockedIncrement(&impl->threadsRunning); - bool goodOp = ::GetQueuedCompletionStatus (impl->iocp, - &numTransferred, - &completionKey, - &overlapped, - timeoutMs); - LONG remainingThreads = InterlockedDecrement(&impl->threadsRunning); - if (goodOp) { - // Dequeued a successful completion. If it's a posted packet from - // shutdown() the overlapped ptr is 0 and key is 1. Else downcast - // the OVERLAPPED pointer to an AsynchIoResult and call the - // completion handler. - if (overlapped == 0 && completionKey == 1) { - // If there are other threads still running this wait, re-post - // the completion. - if (remainingThreads > 0) - PostQueuedCompletionStatus(impl->iocp, 0, completionKey, 0); - return Event(0, SHUTDOWN); - } - - result = windows::AsynchResult::from_overlapped(overlapped); - result->success (static_cast<size_t>(numTransferred)); - } - else { - if (overlapped != 0) { - // Dequeued a completion for a failed operation. Downcast back - // to the result object and inform it that the operation failed. - DWORD status = ::GetLastError(); - result = windows::AsynchResult::from_overlapped(overlapped); - result->failure (static_cast<int>(status)); - } - } - return Event(0, INVALID); // TODO - this may need to be changed. - -} - -// Concrete constructors -Poller::Poller() : - impl(new PollerPrivate()) -{} - -Poller::~Poller() { - delete impl; -} - -}} diff --git a/cpp/src/qpid/sys/windows/LockFile.cpp b/cpp/src/qpid/sys/windows/LockFile.cpp deleted file mode 100755 index 048c2d5b18..0000000000 --- a/cpp/src/qpid/sys/windows/LockFile.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Copyright (c) 2008 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/LockFile.h" -#include "qpid/sys/windows/check.h" - -#include <windows.h> - -namespace qpid { -namespace sys { - -class LockFilePrivate { - friend class LockFile; - - HANDLE fd; - -public: - LockFilePrivate(HANDLE f) : fd(f) {} -}; - -LockFile::LockFile(const std::string& path_, bool create) - : path(path_), created(create) { - - HANDLE h = ::CreateFile(path.c_str(), - create ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ, - FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, - 0, /* Default security */ - create ? OPEN_ALWAYS : OPEN_EXISTING, - FILE_FLAG_DELETE_ON_CLOSE, /* Delete file when closed */ - NULL); - if (h == INVALID_HANDLE_VALUE) - throw qpid::Exception(path + ": " + qpid::sys::strError(GetLastError())); - - // Lock up to 4Gb - if (!::LockFile(h, 0, 0, 0xffffffff, 0)) - throw qpid::Exception(path + ": " + qpid::sys::strError(GetLastError())); - impl.reset(new LockFilePrivate(h)); -} - -LockFile::~LockFile() { - if (impl) { - if (impl->fd != INVALID_HANDLE_VALUE) { - ::UnlockFile(impl->fd, 0, 0, 0xffffffff, 0); - ::CloseHandle(impl->fd); - } - } -} - -}} /* namespace qpid::sys */ diff --git a/cpp/src/qpid/sys/windows/PipeHandle.cpp b/cpp/src/qpid/sys/windows/PipeHandle.cpp deleted file mode 100755 index 062458ae5f..0000000000 --- a/cpp/src/qpid/sys/windows/PipeHandle.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/sys/PipeHandle.h" -#include "qpid/sys/windows/check.h" -#include <winsock2.h> - -namespace qpid { -namespace sys { - -PipeHandle::PipeHandle(bool nonBlocking) { - - SOCKET listener, pair[2]; - struct sockaddr_in addr; - int err; - int addrlen = sizeof(addr); - pair[0] = pair[1] = INVALID_SOCKET; - if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = 0; - - err = bind(listener, (const struct sockaddr*) &addr, sizeof(addr)); - if (err == SOCKET_ERROR) { - err = WSAGetLastError(); - closesocket(listener); - throw QPID_WINDOWS_ERROR(err); - } - - err = getsockname(listener, (struct sockaddr*) &addr, &addrlen); - if (err == SOCKET_ERROR) { - err = WSAGetLastError(); - closesocket(listener); - throw QPID_WINDOWS_ERROR(err); - } - - try { - if (listen(listener, 1) == SOCKET_ERROR) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - if ((pair[0] = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - if (connect(pair[0], (const struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - if ((pair[1] = accept(listener, NULL, NULL)) == INVALID_SOCKET) - throw QPID_WINDOWS_ERROR(WSAGetLastError()); - - closesocket(listener); - writeFd = pair[0]; - readFd = pair[1]; - } - catch (...) { - closesocket(listener); - if (pair[0] != INVALID_SOCKET) - closesocket(pair[0]); - throw; - } - - // Set the socket to non-blocking - if (nonBlocking) { - unsigned long nonblock = 1; - ioctlsocket(readFd, FIONBIO, &nonblock); - } -} - -PipeHandle::~PipeHandle() { - closesocket(readFd); - closesocket(writeFd); -} - -int PipeHandle::read(void* buf, size_t bufSize) { - return ::recv(readFd, (char *)buf, bufSize, 0); -} - -int PipeHandle::write(const void* buf, size_t bufSize) { - return ::send(writeFd, (const char *)buf, bufSize, 0); -} - -int PipeHandle::getReadHandle() { - return readFd; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/windows/PollableCondition.cpp b/cpp/src/qpid/sys/windows/PollableCondition.cpp deleted file mode 100644 index 6a1d9045b4..0000000000 --- a/cpp/src/qpid/sys/windows/PollableCondition.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef QPID_SYS_WINDOWS_POLLABLECONDITION_CPP -#define QPID_SYS_WINDOWS_POLLABLECONDITION_CPP - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/PollableCondition.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/windows/AsynchIoResult.h" -#include "qpid/sys/windows/IoHandlePrivate.h" - -#include <boost/bind.hpp> -#include <windows.h> - -namespace qpid { -namespace sys { - -// PollableConditionPrivate will reuse the IocpPoller's ability to queue -// a completion to the IOCP and have it dispatched to the completer callback -// noted in the IOHandlePrivate when the request is queued. The -// AsynchCallbackRequest object is not really used - we already have the -// desired callback for the user of PollableCondition. -class PollableConditionPrivate : private IOHandle { - friend class PollableCondition; - -private: - PollableConditionPrivate(const sys::PollableCondition::Callback& cb, - sys::PollableCondition& parent, - const boost::shared_ptr<sys::Poller>& poller); - ~PollableConditionPrivate(); - - void poke(); - void dispatch(windows::AsynchIoResult *result); - -private: - PollableCondition::Callback cb; - PollableCondition& parent; - boost::shared_ptr<sys::Poller> poller; - LONG isSet; -}; - -PollableConditionPrivate::PollableConditionPrivate(const sys::PollableCondition::Callback& cb, - sys::PollableCondition& parent, - const boost::shared_ptr<sys::Poller>& poller) - : IOHandle(new sys::IOHandlePrivate(INVALID_SOCKET, - boost::bind(&PollableConditionPrivate::dispatch, this, _1))), - cb(cb), parent(parent), poller(poller), isSet(0) -{ -} - -PollableConditionPrivate::~PollableConditionPrivate() -{ -} - -void PollableConditionPrivate::poke() -{ - // monitorHandle will queue a completion for the IOCP; when it's handled, a - // poller thread will call back to dispatch() below. - PollerHandle ph(*this); - poller->monitorHandle(ph, Poller::INPUT); -} - -void PollableConditionPrivate::dispatch(windows::AsynchIoResult *result) -{ - delete result; // Poller::monitorHandle() allocates this - cb(parent); - if (isSet) - poke(); -} - - /* PollableCondition */ - -PollableCondition::PollableCondition(const Callback& cb, - const boost::shared_ptr<sys::Poller>& poller) - : impl(new PollableConditionPrivate(cb, *this, poller)) -{ -} - -PollableCondition::~PollableCondition() -{ - delete impl; -} - -void PollableCondition::set() { - // Add one to the set count and poke it to provoke a callback - ::InterlockedIncrement(&impl->isSet); - impl->poke(); -} - -void PollableCondition::clear() { - ::InterlockedExchange(&impl->isSet, 0); -} - -}} // namespace qpid::sys - -#endif /*!QPID_SYS_WINDOWS_POLLABLECONDITION_CPP*/ diff --git a/cpp/src/qpid/sys/windows/Shlib.cpp b/cpp/src/qpid/sys/windows/Shlib.cpp deleted file mode 100644 index ba18747eb4..0000000000 --- a/cpp/src/qpid/sys/windows/Shlib.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Shlib.h" -#include "qpid/Exception.h" -#include "qpid/sys/windows/check.h" -#include <windows.h> - -namespace qpid { -namespace sys { - -void Shlib::load(const char* name) { - HMODULE h = LoadLibrary(name); - if (h == NULL) { - throw QPID_WINDOWS_ERROR(GetLastError()); - } - handle = static_cast<void*>(h); -} - -void Shlib::unload() { - if (handle) { - if (FreeLibrary(static_cast<HMODULE>(handle)) == 0) { - throw QPID_WINDOWS_ERROR(GetLastError()); - } - handle = 0; - } -} - -void* Shlib::getSymbol(const char* name) { - // Double cast avoids warning about casting function pointer to object - void *sym = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(GetProcAddress(static_cast<HMODULE>(handle), name))); - if (sym == NULL) - throw QPID_WINDOWS_ERROR(GetLastError()); - return sym; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/windows/Socket.cpp b/cpp/src/qpid/sys/windows/Socket.cpp deleted file mode 100755 index 2ce274acc9..0000000000 --- a/cpp/src/qpid/sys/windows/Socket.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// Ensure we get all of winsock2.h -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - -#include "qpid/sys/Socket.h" -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/windows/IoHandlePrivate.h" -#include "qpid/sys/windows/check.h" -#include "qpid/sys/Time.h" - -#include <cstdlib> -#include <string.h> - -#include <winsock2.h> - -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> - -// Need to initialize WinSock. Ideally, this would be a singleton or embedded -// in some one-time initialization function. I tried boost singleton and could -// not get it to compile (and others located in google had the same problem). -// So, this simple static with an interlocked increment will do for known -// use cases at this time. Since this will only shut down winsock at process -// termination, there may be some problems with client programs that also -// expect to load and unload winsock, but we'll see... -// If someone does get an easy-to-use singleton sometime, converting to it -// may be preferable. - -namespace { - -static LONG volatile initialized = 0; - -class WinSockSetup { - // : public boost::details::pool::singleton_default<WinSockSetup> { - -public: - WinSockSetup() { - LONG timesEntered = InterlockedIncrement(&initialized); - if (timesEntered > 1) - return; - err = 0; - WORD wVersionRequested; - WSADATA wsaData; - - /* Request WinSock 2.2 */ - wVersionRequested = MAKEWORD(2, 2); - err = WSAStartup(wVersionRequested, &wsaData); - } - - ~WinSockSetup() { - WSACleanup(); - } - -public: - int error(void) const { return err; } - -protected: - DWORD err; -}; - -static WinSockSetup setup; - -} /* namespace */ - -namespace qpid { -namespace sys { - -namespace { - -std::string getName(SOCKET fd, bool local, bool includeService = false) -{ - sockaddr_in name; // big enough for any socket address - socklen_t namelen = sizeof(name); - if (local) { - QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen)); - } else { - QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen)); - } - - char servName[NI_MAXSERV]; - char dispName[NI_MAXHOST]; - if (includeService) { - if (int rc = ::getnameinfo((sockaddr*)&name, namelen, - dispName, sizeof(dispName), - servName, sizeof(servName), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw qpid::Exception(QPID_MSG(gai_strerror(rc))); - return std::string(dispName) + ":" + std::string(servName); - } else { - if (int rc = ::getnameinfo((sockaddr*)&name, namelen, - dispName, sizeof(dispName), - 0, 0, - NI_NUMERICHOST) != 0) - throw qpid::Exception(QPID_MSG(gai_strerror(rc))); - return dispName; - } -} - -std::string getService(SOCKET fd, bool local) -{ - sockaddr_in name; // big enough for any socket address - socklen_t namelen = sizeof(name); - - if (local) { - QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen)); - } else { - QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen)); - } - - char servName[NI_MAXSERV]; - if (int rc = ::getnameinfo((sockaddr*)&name, namelen, - 0, 0, - servName, sizeof(servName), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw qpid::Exception(QPID_MSG(gai_strerror(rc))); - return servName; -} -} // namespace - -Socket::Socket() : - IOHandle(new IOHandlePrivate), - nonblocking(false), - nodelay(false) -{ - SOCKET& socket = impl->fd; - if (socket != INVALID_SOCKET) Socket::close(); - SOCKET s = ::socket (PF_INET, SOCK_STREAM, 0); - if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError()); - socket = s; -} - -Socket::Socket(IOHandlePrivate* h) : - IOHandle(h), - nonblocking(false), - nodelay(false) -{} - -void -Socket::createSocket(const SocketAddress& sa) const -{ - SOCKET& socket = impl->fd; - if (socket != INVALID_SOCKET) Socket::close(); - - SOCKET s = ::socket (getAddrInfo(sa).ai_family, - getAddrInfo(sa).ai_socktype, - 0); - if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError()); - socket = s; - - try { - if (nonblocking) setNonblocking(); - if (nodelay) setTcpNoDelay(); - } catch (std::exception&) { - closesocket(s); - socket = INVALID_SOCKET; - throw; - } -} - -void Socket::setTimeout(const Duration& interval) const -{ - const SOCKET& socket = impl->fd; - int64_t nanosecs = interval; - nanosecs /= (1000 * 1000); // nsecs -> usec -> msec - int msec = 0; - if (nanosecs > std::numeric_limits<int>::max()) - msec = std::numeric_limits<int>::max(); - else - msec = static_cast<int>(nanosecs); - setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&msec, sizeof(msec)); - setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&msec, sizeof(msec)); -} - -void Socket::setNonblocking() const { - u_long nonblock = 1; - QPID_WINSOCK_CHECK(ioctlsocket(impl->fd, FIONBIO, &nonblock)); -} - -void Socket::connect(const std::string& host, uint16_t port) const -{ - SocketAddress sa(host, boost::lexical_cast<std::string>(port)); - connect(sa); -} - -void -Socket::connect(const SocketAddress& addr) const -{ - const SOCKET& socket = impl->fd; - const addrinfo *addrs = &(getAddrInfo(addr)); - int error = 0; - WSASetLastError(0); - while (addrs != 0) { - if ((::connect(socket, addrs->ai_addr, addrs->ai_addrlen) == 0) || - (WSAGetLastError() == WSAEWOULDBLOCK)) - break; - // Error... save this error code and see if there are other address - // to try before throwing the exception. - error = WSAGetLastError(); - addrs = addrs->ai_next; - } - if (error) - throw qpid::Exception(QPID_MSG(strError(error) << ": " << connectname)); -} - -void -Socket::close() const -{ - SOCKET& socket = impl->fd; - if (socket == INVALID_SOCKET) return; - QPID_WINSOCK_CHECK(closesocket(socket)); - socket = INVALID_SOCKET; -} - - -int Socket::write(const void *buf, size_t count) const -{ - const SOCKET& socket = impl->fd; - int sent = ::send(socket, (const char *)buf, count, 0); - if (sent == SOCKET_ERROR) - return -1; - return sent; -} - -int Socket::read(void *buf, size_t count) const -{ - const SOCKET& socket = impl->fd; - int received = ::recv(socket, (char *)buf, count, 0); - if (received == SOCKET_ERROR) - return -1; - return received; -} - -int Socket::listen(uint16_t port, int backlog) const -{ - const SOCKET& socket = impl->fd; - BOOL yes=1; - QPID_WINSOCK_CHECK(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes))); - struct sockaddr_in name; - memset(&name, 0, sizeof(name)); - name.sin_family = AF_INET; - name.sin_port = htons(port); - name.sin_addr.s_addr = 0; - if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) == SOCKET_ERROR) - throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(WSAGetLastError()))); - if (::listen(socket, backlog) == SOCKET_ERROR) - throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(WSAGetLastError()))); - - socklen_t namelen = sizeof(name); - QPID_WINSOCK_CHECK(::getsockname(socket, (struct sockaddr*)&name, &namelen)); - return ntohs(name.sin_port); -} - -Socket* Socket::accept() const -{ - SOCKET afd = ::accept(impl->fd, 0, 0); - if (afd != INVALID_SOCKET) - return new Socket(new IOHandlePrivate(afd)); - else if (WSAGetLastError() == EAGAIN) - return 0; - else throw QPID_WINDOWS_ERROR(WSAGetLastError()); -} - -std::string Socket::getSockname() const -{ - return getName(impl->fd, true); -} - -std::string Socket::getPeername() const -{ - return getName(impl->fd, false); -} - -std::string Socket::getPeerAddress() const -{ - if (!connectname.empty()) - return std::string (connectname); - return getName(impl->fd, false, true); -} - -std::string Socket::getLocalAddress() const -{ - return getName(impl->fd, true, true); -} - -uint16_t Socket::getLocalPort() const -{ - return atoi(getService(impl->fd, true).c_str()); -} - -uint16_t Socket::getRemotePort() const -{ - return atoi(getService(impl->fd, true).c_str()); -} - -int Socket::getError() const -{ - int result; - socklen_t rSize = sizeof (result); - - QPID_WINSOCK_CHECK(::getsockopt(impl->fd, SOL_SOCKET, SO_ERROR, (char *)&result, &rSize)); - return result; -} - -void Socket::setTcpNoDelay() const -{ - int flag = 1; - int result = setsockopt(impl->fd, - IPPROTO_TCP, - TCP_NODELAY, - (char *)&flag, - sizeof(flag)); - QPID_WINSOCK_CHECK(result); - nodelay = true; -} - -inline IOHandlePrivate* IOHandlePrivate::getImpl(const qpid::sys::IOHandle &h) -{ - return h.impl; -} - -SOCKET toSocketHandle(const Socket& s) -{ - return IOHandlePrivate::getImpl(s)->fd; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/windows/SocketAddress.cpp b/cpp/src/qpid/sys/windows/SocketAddress.cpp deleted file mode 100644 index 5efdad0183..0000000000 --- a/cpp/src/qpid/sys/windows/SocketAddress.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// Ensure we get all of winsock2.h -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - -#include "qpid/sys/SocketAddress.h" - -#include "qpid/sys/windows/check.h" - -#include <winsock2.h> -#include <ws2tcpip.h> -#include <string.h> - -namespace qpid { -namespace sys { - -SocketAddress::SocketAddress(const std::string& host0, const std::string& port0) : - host(host0), - port(port0), - addrInfo(0) -{ - ::addrinfo hints; - ::memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; // In order to allow AF_INET6 we'd have to change createTcp() as well - hints.ai_socktype = SOCK_STREAM; - - const char* node = 0; - if (host.empty()) { - hints.ai_flags |= AI_PASSIVE; - } else { - node = host.c_str(); - } - const char* service = port.empty() ? "0" : port.c_str(); - - int n = ::getaddrinfo(node, service, &hints, &addrInfo); - if (n != 0) - throw Exception(QPID_MSG("Cannot resolve " << host << ": " << ::gai_strerror(n))); -} - -SocketAddress::~SocketAddress() -{ - ::freeaddrinfo(addrInfo); -} - -std::string SocketAddress::asString() const -{ - return host + ":" + port; -} - -const ::addrinfo& getAddrInfo(const SocketAddress& sa) -{ - return *sa.addrInfo; -} - -}} diff --git a/cpp/src/qpid/sys/windows/SslAsynchIO.cpp b/cpp/src/qpid/sys/windows/SslAsynchIO.cpp deleted file mode 100644 index 11a3389e45..0000000000 --- a/cpp/src/qpid/sys/windows/SslAsynchIO.cpp +++ /dev/null @@ -1,661 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "SslAsynchIO.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Time.h" -#include "qpid/log/Statement.h" - -#include "qpid/sys/windows/check.h" - -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include <security.h> -#include <Schnlsp.h> -#undef SECURITY_WIN32 - -#include <queue> -#include <boost/bind.hpp> - -namespace { - - /* - * To make the SSL encryption more efficient, set up a new BufferBase - * that leaves room for the SSL header to be prepended and the SSL - * trailer to be appended. - * - * This works by accepting a properly formed BufferBase, remembering it, - * and resetting the members of this struct to reflect the reserved - * header and trailer areas. It's only needed for giving buffers up to - * the frame layer for writing into. - */ - struct SslIoBuff : public qpid::sys::AsynchIO::BufferBase { - std::auto_ptr<qpid::sys::AsynchIO::BufferBase> aioBuff; - - SslIoBuff (qpid::sys::AsynchIO::BufferBase *base, - const SecPkgContext_StreamSizes &sizes) - : qpid::sys::AsynchIO::BufferBase(&base->bytes[sizes.cbHeader], - std::min(base->byteCount - sizes.cbHeader - sizes.cbTrailer, - sizes.cbMaximumMessage)), - aioBuff(base) - {} - - ~SslIoBuff() {} - qpid::sys::AsynchIO::BufferBase* release() { return aioBuff.release(); } - }; -} - -namespace qpid { -namespace sys { -namespace windows { - -SslAsynchIO::SslAsynchIO(const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb, - BuffersEmptyCallback eCb, - IdleCallback iCb, - NegotiateDoneCallback nCb) : - credHandle(hCred), - aio(0), - state(Negotiating), - readCallback(rCb), - idleCallback(iCb), - negotiateDoneCallback(nCb), - callbacksInProgress(0), - queuedDelete(false), - leftoverPlaintext(0) -{ - SecInvalidateHandle(&ctxtHandle); - peerAddress = s.getPeerAddress(); - aio = qpid::sys::AsynchIO::create(s, - boost::bind(&SslAsynchIO::sslDataIn, this, _1, _2), - eofCb, - disCb, - cCb, - eCb, - boost::bind(&SslAsynchIO::idle, this, _1)); -} - -SslAsynchIO::~SslAsynchIO() { - if (leftoverPlaintext) { - delete leftoverPlaintext; - leftoverPlaintext = 0; - } -} - -void SslAsynchIO::queueForDeletion() { - // This method effectively disconnects the layer above; pass it on the - // AsynchIO and delete. - aio->queueForDeletion(); - queuedDelete = true; - if (!callbacksInProgress) - delete this; -} - -void SslAsynchIO::start(qpid::sys::Poller::shared_ptr poller) { - aio->start(poller); - startNegotiate(); -} - -void SslAsynchIO::queueReadBuffer(AsynchIO::BufferBase* buff) { - aio->queueReadBuffer(buff); -} - -void SslAsynchIO::unread(AsynchIO::BufferBase* buff) { - // This is plaintext data being given back for more. Since it's already - // decrypted, don't give it back to the aio layer; keep it to append - // any new data for the upper layer. - assert(buff); - buff->squish(); - assert(leftoverPlaintext == 0); - leftoverPlaintext = buff; -} - -void SslAsynchIO::queueWrite(AsynchIO::BufferBase* buff) { - // @@TODO: Need to delay the write if the session is renegotiating. - - // Should not have gotten here without an SslIoBuff. This assert is - // primarily to catch any stray cases where write is called with a buffer - // not obtained via getQueuedBuffer. - SslIoBuff *sslBuff = dynamic_cast<SslIoBuff*>(buff); - assert(sslBuff != 0); - - // Encrypt and hand off to the io layer. Remember that the upper layer's - // encoding was working on, and adjusting counts for, the SslIoBuff. - // Update the count of the original BufferBase before handing off to - // the I/O layer. - buff = sslBuff->release(); - SecBuffer buffs[4]; - buffs[0].cbBuffer = schSizes.cbHeader; - buffs[0].BufferType = SECBUFFER_STREAM_HEADER; - buffs[0].pvBuffer = buff->bytes; // This space was left by SslIoBuff - buffs[1].cbBuffer = sslBuff->dataCount; - buffs[1].BufferType = SECBUFFER_DATA; - buffs[1].pvBuffer = sslBuff->bytes; - buffs[2].cbBuffer = schSizes.cbTrailer; - buffs[2].BufferType = SECBUFFER_STREAM_TRAILER; - buffs[2].pvBuffer = &sslBuff->bytes[sslBuff->dataCount]; - buffs[3].cbBuffer = 0; - buffs[3].BufferType = SECBUFFER_EMPTY; - buffs[3].pvBuffer = 0; - SecBufferDesc buffDesc; - buffDesc.ulVersion = SECBUFFER_VERSION; - buffDesc.cBuffers = 4; - buffDesc.pBuffers = buffs; - SECURITY_STATUS status = ::EncryptMessage(&ctxtHandle, 0, &buffDesc, 0); - - // EncryptMessage encrypts the data in place. The header and trailer - // areas were left previously and must now be included in the updated - // count of bytes to write to the peer. - delete sslBuff; - buff->dataCount = buffs[0].cbBuffer + buffs[1].cbBuffer + buffs[2].cbBuffer; - aio->queueWrite(buff); -} - -void SslAsynchIO::notifyPendingWrite() { - aio->notifyPendingWrite(); -} - -void SslAsynchIO::queueWriteClose() { - if (state == Negotiating) { - // Never got going, so don't bother trying to close SSL down orderly. - state = ShuttingDown; - aio->queueWriteClose(); - return; - } - - state = ShuttingDown; - - DWORD shutdown = SCHANNEL_SHUTDOWN; - SecBuffer shutBuff; - shutBuff.cbBuffer = sizeof(DWORD); - shutBuff.BufferType = SECBUFFER_TOKEN; - shutBuff.pvBuffer = &shutdown; - SecBufferDesc desc; - desc.ulVersion = SECBUFFER_VERSION; - desc.cBuffers = 1; - desc.pBuffers = &shutBuff; - ::ApplyControlToken(&ctxtHandle, &desc); - negotiateStep(0); - // When the shutdown sequence is done, negotiateDone() will handle - // shutting down aio. -} - -bool SslAsynchIO::writeQueueEmpty() { - return aio->writeQueueEmpty(); -} - -/* - * Initiate a read operation. AsynchIO::readComplete() will be - * called when the read is complete and data is available. - */ -void SslAsynchIO::startReading() { - aio->startReading(); -} - -void SslAsynchIO::stopReading() { - aio->stopReading(); -} - -// Queue the specified callback for invocation from an I/O thread. -void SslAsynchIO::requestCallback(RequestCallback callback) { - aio->requestCallback(callback); -} - -/** - * Return a queued buffer read to put new data in for writing. - * This method ALWAYS returns a SslIoBuff reflecting a BufferBase from - * the aio layer that has header and trailer space reserved. - */ -AsynchIO::BufferBase* SslAsynchIO::getQueuedBuffer() { - SslIoBuff *sslBuff = 0; - BufferBase* buff = aio->getQueuedBuffer(); - if (buff == 0) - return 0; - - sslBuff = new SslIoBuff(buff, schSizes); - return sslBuff; -} - -unsigned int SslAsynchIO::getSslKeySize() { - SecPkgContext_KeyInfo info; - memset(&info, 0, sizeof(info)); - ::QueryContextAttributes(&ctxtHandle, SECPKG_ATTR_KEY_INFO, &info); - return info.KeySize; -} - -void SslAsynchIO::negotiationDone() { - switch(state) { - case Negotiating: - ::QueryContextAttributes(&ctxtHandle, - SECPKG_ATTR_STREAM_SIZES, - &schSizes); - state = Running; - if (negotiateDoneCallback) - negotiateDoneCallback(SEC_E_OK); - break; - case Redo: - state = Running; - break; - case ShuttingDown: - aio->queueWriteClose(); - break; - default: - assert(0); - } -} - -void SslAsynchIO::negotiationFailed(SECURITY_STATUS status) { - QPID_LOG(notice, "SSL negotiation failed to " << peerAddress << ": " << - qpid::sys::strError(status)); - if (negotiateDoneCallback) - negotiateDoneCallback(status); - else - queueWriteClose(); -} - -void SslAsynchIO::sslDataIn(qpid::sys::AsynchIO& a, BufferBase *buff) { - if (state != Running) { - negotiateStep(buff); - return; - } - - // Decrypt the buffer; if there's legit data, pass it on through. - // However, it's also possible that the peer hasn't supplied enough - // data yet, or the session needs to be renegotiated, or the session - // is ending. - SecBuffer recvBuffs[4]; - recvBuffs[0].cbBuffer = buff->dataCount; - recvBuffs[0].BufferType = SECBUFFER_DATA; - recvBuffs[0].pvBuffer = &buff->bytes[buff->dataStart]; - recvBuffs[1].BufferType = SECBUFFER_EMPTY; - recvBuffs[2].BufferType = SECBUFFER_EMPTY; - recvBuffs[3].BufferType = SECBUFFER_EMPTY; - SecBufferDesc buffDesc; - buffDesc.ulVersion = SECBUFFER_VERSION; - buffDesc.cBuffers = 4; - buffDesc.pBuffers = recvBuffs; - SECURITY_STATUS status = ::DecryptMessage(&ctxtHandle, &buffDesc, 0, NULL); - if (status != SEC_E_OK) { - if (status == SEC_E_INCOMPLETE_MESSAGE) { - // Give the partially filled buffer back and get more data - a.unread(buff); - } - else { - // Don't need this any more... - a.queueReadBuffer(buff); - - if (status == SEC_I_RENEGOTIATE) { - state = Redo; - negotiateStep(0); - } - else if (status == SEC_I_CONTEXT_EXPIRED) { - queueWriteClose(); - } - else { - throw QPID_WINDOWS_ERROR(status); - } - } - return; - } - - // All decrypted and verified... continue with AMQP. The recvBuffs have - // been set up by DecryptMessage to demarcate the SSL header, data, and - // trailer, as well as any extra data left over. Walk through and find - // that info, adjusting the buff data accordingly to reflect only the - // actual decrypted data. - // If there's extra data, copy that out to a new buffer and run through - // this method again. - BufferBase *extraBuff = 0; - for (int i = 0; i < 4; i++) { - switch (recvBuffs[i].BufferType) { - case SECBUFFER_STREAM_HEADER: - buff->dataStart += recvBuffs[i].cbBuffer; - // Fall through - also don't count these bytes as data - case SECBUFFER_STREAM_TRAILER: - buff->dataCount -= recvBuffs[i].cbBuffer; - break; - case SECBUFFER_EXTRA: - // Very important to get this buffer from the downstream aio. - // The ones constructed from the local getQueuedBuffer() are - // restricted size for encrypting. However, data coming up from - // TCP may have a bunch of SSL segments coalesced and be much - // larger than the maximum single SSL segment. - extraBuff = a.getQueuedBuffer(); - if (0 == extraBuff) - throw QPID_WINDOWS_ERROR(WSAENOBUFS); - memmove(extraBuff->bytes, - recvBuffs[i].pvBuffer, - recvBuffs[i].cbBuffer); - extraBuff->dataCount = recvBuffs[i].cbBuffer; - break; - default: - break; - } - } - - // Since we've already taken (possibly) all the available bytes from the - // aio layer, need to be sure that everything that's processable is - // processed before returning back to aio. It could be that any - // leftoverPlaintext data plus new buff data won't fit in one buffer, so - // need to keep going around the input processing loop until either - // all the bytes are gone, or there's less than a full frame remaining - // (so we can count on more bytes being on the way via aio). - do { - BufferBase *temp = 0; - // Now that buff reflects only decrypted data, see if there was any - // partial data left over from last time. If so, append this new - // data to that and release the current buff back to aio. Assume that - // leftoverPlaintext was squished so the data starts at 0. - if (leftoverPlaintext != 0) { - // There is leftover data; append all the new data that will fit. - int32_t count = buff->dataCount; - if (leftoverPlaintext->dataCount + count > leftoverPlaintext->byteCount) - count = (leftoverPlaintext->byteCount - leftoverPlaintext->dataCount); - ::memmove(&leftoverPlaintext->bytes[leftoverPlaintext->dataCount], - &buff->bytes[buff->dataStart], - count); - leftoverPlaintext->dataCount += count; - buff->dataCount -= count; - buff->dataStart += count; - if (buff->dataCount == 0) { - a.queueReadBuffer(buff); - buff = 0; - } - // Prepare to pass the buffer up. Beware that the read callback - // may do an unread(), so move the leftoverPlaintext pointer - // out of the way. It also may release the buffer back to aio, - // so in either event, the pointer passed to the callback is not - // valid on return. - temp = leftoverPlaintext; - leftoverPlaintext = 0; - } - else { - temp = buff; - buff = 0; - } - if (readCallback) { - // The callback guard here is to prevent an upcall from deleting - // this out from under us via queueForDeletion(). - ++callbacksInProgress; - readCallback(*this, temp); - --callbacksInProgress; - } - else - a.queueReadBuffer(temp); // What else can we do with this??? - } while (buff != 0); - - // Ok, the current decrypted data is done. If there was any extra data, - // go back and handle that. - if (extraBuff != 0) - sslDataIn(a, extraBuff); - - // If the upper layer queued for delete, do that now that all the - // callbacks are done. - if (queuedDelete && callbacksInProgress == 0) - delete this; -} - -void SslAsynchIO::idle(qpid::sys::AsynchIO&) { - // Don't relay idle indication to layer above until SSL session is up. - if (state == Running) { - state = Running; - if (idleCallback) - idleCallback(*this); - } -} - - /**************************************************/ - -ClientSslAsynchIO::ClientSslAsynchIO(const std::string& brokerHost, - const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb, - BuffersEmptyCallback eCb, - IdleCallback iCb, - NegotiateDoneCallback nCb) : - SslAsynchIO(s, hCred, rCb, eofCb, disCb, cCb, eCb, iCb, nCb), - serverHost(brokerHost) -{ -} - -void ClientSslAsynchIO::startNegotiate() { - // SEC_CHAR is non-const, so do all the typing here. - SEC_CHAR *host = const_cast<SEC_CHAR *>(serverHost.c_str()); - - // Need a buffer to receive the token to send to the server. - BufferBase *buff = aio->getQueuedBuffer(); - ULONG ctxtRequested = ISC_REQ_STREAM; - ULONG ctxtAttrs; - // sendBuffs gets information to forward to the peer. - SecBuffer sendBuffs[2]; - sendBuffs[0].cbBuffer = buff->byteCount; - sendBuffs[0].BufferType = SECBUFFER_TOKEN; - sendBuffs[0].pvBuffer = buff->bytes; - sendBuffs[1].cbBuffer = 0; - sendBuffs[1].BufferType = SECBUFFER_EMPTY; - sendBuffs[1].pvBuffer = 0; - SecBufferDesc sendBuffDesc; - sendBuffDesc.ulVersion = SECBUFFER_VERSION; - sendBuffDesc.cBuffers = 2; - sendBuffDesc.pBuffers = sendBuffs; - SECURITY_STATUS status = ::InitializeSecurityContext(&credHandle, - NULL, - host, - ctxtRequested, - 0, - 0, - NULL, - 0, - &ctxtHandle, - &sendBuffDesc, - &ctxtAttrs, - NULL); - if (status == SEC_I_CONTINUE_NEEDED) { - buff->dataCount = sendBuffs[0].cbBuffer; - aio->queueWrite(buff); - } -} - -void ClientSslAsynchIO::negotiateStep(BufferBase* buff) { - // SEC_CHAR is non-const, so do all the typing here. - SEC_CHAR *host = const_cast<SEC_CHAR *>(serverHost.c_str()); - ULONG ctxtRequested = ISC_REQ_STREAM; - ULONG ctxtAttrs; - - // tokenBuffs describe the buffer that's coming in. It should have - // a token from the SSL server. - SecBuffer tokenBuffs[2]; - tokenBuffs[0].cbBuffer = buff ? buff->dataCount : 0; - tokenBuffs[0].BufferType = SECBUFFER_TOKEN; - tokenBuffs[0].pvBuffer = buff ? buff->bytes : 0; - tokenBuffs[1].cbBuffer = 0; - tokenBuffs[1].BufferType = SECBUFFER_EMPTY; - tokenBuffs[1].pvBuffer = 0; - SecBufferDesc tokenBuffDesc; - tokenBuffDesc.ulVersion = SECBUFFER_VERSION; - tokenBuffDesc.cBuffers = 2; - tokenBuffDesc.pBuffers = tokenBuffs; - - // Need a buffer to receive any token to send back to the server. - BufferBase *sendbuff = aio->getQueuedBuffer(); - // sendBuffs gets information to forward to the peer. - SecBuffer sendBuffs[2]; - sendBuffs[0].cbBuffer = sendbuff->byteCount; - sendBuffs[0].BufferType = SECBUFFER_TOKEN; - sendBuffs[0].pvBuffer = sendbuff->bytes; - sendBuffs[1].cbBuffer = 0; - sendBuffs[1].BufferType = SECBUFFER_EMPTY; - sendBuffs[1].pvBuffer = 0; - SecBufferDesc sendBuffDesc; - sendBuffDesc.ulVersion = SECBUFFER_VERSION; - sendBuffDesc.cBuffers = 2; - sendBuffDesc.pBuffers = sendBuffs; - - SECURITY_STATUS status = ::InitializeSecurityContext(&credHandle, - &ctxtHandle, - host, - ctxtRequested, - 0, - 0, - &tokenBuffDesc, - 0, - NULL, - &sendBuffDesc, - &ctxtAttrs, - NULL); - - if (status == SEC_E_INCOMPLETE_MESSAGE) { - // Not enough - get more data from the server then try again. - aio->unread(buff); - aio->queueReadBuffer(sendbuff); // Don't need this one for now... - return; - } - // Done with the buffer that came in... - if (buff) - aio->queueReadBuffer(buff); - if (status == SEC_I_CONTINUE_NEEDED) { - sendbuff->dataCount = sendBuffs[0].cbBuffer; - aio->queueWrite(sendbuff); - return; - } - // Nothing to send back to the server... - aio->queueReadBuffer(sendbuff); - // SEC_I_CONTEXT_EXPIRED means session stop complete; SEC_E_OK can be - // either session stop or negotiation done (session up). - if (status == SEC_E_OK || status == SEC_I_CONTEXT_EXPIRED) - negotiationDone(); - else - negotiationFailed(status); -} - -/*************************************************/ - -ServerSslAsynchIO::ServerSslAsynchIO(bool clientMustAuthenticate, - const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb, - BuffersEmptyCallback eCb, - IdleCallback iCb, - NegotiateDoneCallback nCb) : - SslAsynchIO(s, hCred, rCb, eofCb, disCb, cCb, eCb, iCb, nCb), - clientAuth(clientMustAuthenticate) -{ -} - -void ServerSslAsynchIO::startNegotiate() { - // Nothing... need the client to send a token first. -} - -void ServerSslAsynchIO::negotiateStep(BufferBase* buff) { - ULONG ctxtRequested = ASC_REQ_STREAM; - if (clientAuth) - ctxtRequested |= ASC_REQ_MUTUAL_AUTH; - ULONG ctxtAttrs; - - // tokenBuffs describe the buffer that's coming in. It should have - // a token from the SSL server except if shutting down or renegotiating. - SecBuffer tokenBuffs[2]; - tokenBuffs[0].cbBuffer = buff ? buff->dataCount : 0; - tokenBuffs[0].BufferType = SECBUFFER_TOKEN; - tokenBuffs[0].pvBuffer = buff ? buff->bytes : 0; - tokenBuffs[1].cbBuffer = 0; - tokenBuffs[1].BufferType = SECBUFFER_EMPTY; - tokenBuffs[1].pvBuffer = 0; - SecBufferDesc tokenBuffDesc; - tokenBuffDesc.ulVersion = SECBUFFER_VERSION; - tokenBuffDesc.cBuffers = 2; - tokenBuffDesc.pBuffers = tokenBuffs; - - // Need a buffer to receive any token to send back to the server. - BufferBase *sendbuff = aio->getQueuedBuffer(); - // sendBuffs gets information to forward to the peer. - SecBuffer sendBuffs[2]; - sendBuffs[0].cbBuffer = sendbuff->byteCount; - sendBuffs[0].BufferType = SECBUFFER_TOKEN; - sendBuffs[0].pvBuffer = sendbuff->bytes; - sendBuffs[1].cbBuffer = 0; - sendBuffs[1].BufferType = SECBUFFER_EMPTY; - sendBuffs[1].pvBuffer = 0; - SecBufferDesc sendBuffDesc; - sendBuffDesc.ulVersion = SECBUFFER_VERSION; - sendBuffDesc.cBuffers = 2; - sendBuffDesc.pBuffers = sendBuffs; - PCtxtHandle ctxtHandlePtr = (SecIsValidHandle(&ctxtHandle)) ? &ctxtHandle : 0; - SECURITY_STATUS status = ::AcceptSecurityContext(&credHandle, - ctxtHandlePtr, - &tokenBuffDesc, - ctxtRequested, - 0, - &ctxtHandle, - &sendBuffDesc, - &ctxtAttrs, - NULL); - if (status == SEC_E_INCOMPLETE_MESSAGE) { - // Not enough - get more data from the server then try again. - if (buff) - aio->unread(buff); - aio->queueReadBuffer(sendbuff); // Don't need this one for now... - return; - } - // Done with the buffer that came in... - if (buff) - aio->queueReadBuffer(buff); - if (status == SEC_I_CONTINUE_NEEDED) { - sendbuff->dataCount = sendBuffs[0].cbBuffer; - aio->queueWrite(sendbuff); - return; - } - // There may have been a token generated; if so, send it to the client. - if (sendBuffs[0].cbBuffer > 0) { - sendbuff->dataCount = sendBuffs[0].cbBuffer; - aio->queueWrite(sendbuff); - } - else - // Nothing to send back to the server... - aio->queueReadBuffer(sendbuff); - - // SEC_I_CONTEXT_EXPIRED means session stop complete; SEC_E_OK can be - // either session stop or negotiation done (session up). - if (status == SEC_E_OK || status == SEC_I_CONTEXT_EXPIRED) { - if (clientAuth) - QPID_LOG(warning, "DID WE CHECK FOR CLIENT AUTH???"); - - negotiationDone(); - } - else { - negotiationFailed(status); - } -} - -}}} // namespace qpid::sys::windows diff --git a/cpp/src/qpid/sys/windows/SslAsynchIO.h b/cpp/src/qpid/sys/windows/SslAsynchIO.h deleted file mode 100644 index 3cdf2c8f08..0000000000 --- a/cpp/src/qpid/sys/windows/SslAsynchIO.h +++ /dev/null @@ -1,191 +0,0 @@ -#ifndef _sys_windows_SslAsynchIO -#define _sys_windows_SslAsynchIO - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/AsynchIO.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/Poller.h" -#include "qpid/CommonImportExport.h" -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include <windows.h> -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include <security.h> -#include <Schnlsp.h> -#undef SECURITY_WIN32 - -namespace qpid { -namespace sys { -namespace windows { - -class Socket; -class Poller; - -/* - * SSL/Schannel shim between the frame-handling and AsynchIO layers. - * SslAsynchIO creates a regular AsynchIO object to handle I/O and this class - * gets involved for SSL negotiations and encrypt/decrypt. The details of - * how this all works are invisible to the layers on either side. The only - * change from normal AsynchIO usage is that there's an extra callback - * from SslAsynchIO to indicate that the initial session negotiation is - * complete. - * - * The details of session negotiation are different for client and server - * SSL roles. These differences are handled by deriving separate client - * and server role classes. - */ -class SslAsynchIO : public qpid::sys::AsynchIO { -public: - typedef boost::function1<void, SECURITY_STATUS> NegotiateDoneCallback; - - SslAsynchIO(const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0, - NegotiateDoneCallback nCb = 0); - ~SslAsynchIO(); - - virtual void queueForDeletion(); - - virtual void start(qpid::sys::Poller::shared_ptr poller); - virtual void queueReadBuffer(BufferBase* buff); - virtual void unread(BufferBase* buff); - virtual void queueWrite(BufferBase* buff); - virtual void notifyPendingWrite(); - virtual void queueWriteClose(); - virtual bool writeQueueEmpty(); - virtual void startReading(); - virtual void stopReading(); - virtual void requestCallback(RequestCallback); - virtual BufferBase* getQueuedBuffer(); - - QPID_COMMON_EXTERN unsigned int getSslKeySize(); - -protected: - CredHandle credHandle; - - // AsynchIO layer below that's actually doing the I/O - qpid::sys::AsynchIO *aio; - - // Track what the state of the SSL session is. Have to know when it's - // time to notify the upper layer that the session is up, and also to - // know when it's not legit to pass data through to either side. - enum { Negotiating, Running, Redo, ShuttingDown } state; - bool sessionUp; - CtxtHandle ctxtHandle; - TimeStamp credExpiry; - - // Client- and server-side SSL subclasses implement these to do the - // proper negotiation steps. negotiateStep() is called with a buffer - // just received from the peer. - virtual void startNegotiate() = 0; - virtual void negotiateStep(BufferBase *buff) = 0; - - // The negotiating steps call one of these when it's finalized: - void negotiationDone(); - void negotiationFailed(SECURITY_STATUS status); - -private: - // These are callbacks from AsynchIO to here. - void sslDataIn(qpid::sys::AsynchIO& a, BufferBase *buff); - void idle(qpid::sys::AsynchIO&); - - // These callbacks are to the layer above. - ReadCallback readCallback; - IdleCallback idleCallback; - NegotiateDoneCallback negotiateDoneCallback; - volatile unsigned int callbacksInProgress; // >0 if w/in callbacks - volatile bool queuedDelete; - - // Address of peer, in case it's needed for logging. - std::string peerAddress; - - // Partial buffer of decrypted plaintext given back by the layer above. - AsynchIO::BufferBase *leftoverPlaintext; - - SecPkgContext_StreamSizes schSizes; -}; - -/* - * SSL/Schannel client-side shim between the frame-handling and AsynchIO - * layers. - */ -class ClientSslAsynchIO : public SslAsynchIO { -public: - // Args same as for SslIoShim, with the addition of brokerHost which is - // the expected SSL name of the server. - QPID_COMMON_EXTERN ClientSslAsynchIO(const std::string& brokerHost, - const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0, - NegotiateDoneCallback nCb = 0); - -private: - std::string serverHost; - - // Client- and server-side SSL subclasses implement these to do the - // proper negotiation steps. negotiateStep() is called with a buffer - // just received from the peer. - void startNegotiate(); - void negotiateStep(BufferBase *buff); -}; -/* - * SSL/Schannel server-side shim between the frame-handling and AsynchIO - * layers. - */ -class ServerSslAsynchIO : public SslAsynchIO { -public: - QPID_COMMON_EXTERN ServerSslAsynchIO(bool clientMustAuthenticate, - const qpid::sys::Socket& s, - CredHandle hCred, - ReadCallback rCb, - EofCallback eofCb, - DisconnectCallback disCb, - ClosedCallback cCb = 0, - BuffersEmptyCallback eCb = 0, - IdleCallback iCb = 0, - NegotiateDoneCallback nCb = 0); - -private: - bool clientAuth; - - // Client- and server-side SSL subclasses implement these to do the - // proper negotiation steps. negotiateStep() is called with a buffer - // just received from the peer. - void startNegotiate(); - void negotiateStep(BufferBase *buff); -}; - -}}} // namespace qpid::sys::windows - -#endif // _sys_windows_SslAsynchIO diff --git a/cpp/src/qpid/sys/windows/StrError.cpp b/cpp/src/qpid/sys/windows/StrError.cpp deleted file mode 100755 index 546d399d16..0000000000 --- a/cpp/src/qpid/sys/windows/StrError.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/StrError.h" -#include <string> -#include <string.h> -#include <windows.h> - -namespace qpid { -namespace sys { - -std::string strError(int err) { - const size_t bufsize = 512; - char buf[bufsize]; - buf[0] = 0; - if (0 == FormatMessage (FORMAT_MESSAGE_MAX_WIDTH_MASK - | FORMAT_MESSAGE_FROM_SYSTEM, - 0, - err, - 0, // Default language - buf, - bufsize, - 0)) - { -#ifdef _MSC_VER - strerror_s(buf, bufsize, err); -#else - return std::string(strerror(err)); -#endif - } - return std::string(buf); -} - -}} diff --git a/cpp/src/qpid/sys/windows/SystemInfo.cpp b/cpp/src/qpid/sys/windows/SystemInfo.cpp deleted file mode 100755 index 4da440bdd4..0000000000 --- a/cpp/src/qpid/sys/windows/SystemInfo.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/* GetNativeSystemInfo call requires _WIN32_WINNT 0x0501 or higher */ -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -#endif - -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/SystemInfo.h" - -#include <winsock2.h> -#include <ws2tcpip.h> -#include <windows.h> -#include <tlhelp32.h> - -#ifndef HOST_NAME_MAX -# define HOST_NAME_MAX 256 -#endif - -namespace qpid { -namespace sys { - -long SystemInfo::concurrency() { - SYSTEM_INFO sys_info; - ::GetSystemInfo (&sys_info); - long activeProcessors = 0; - DWORD_PTR mask = sys_info.dwActiveProcessorMask; - while (mask != 0) { - if (mask & 1) - ++activeProcessors; - mask >>= 1; - } - return activeProcessors; -} - -bool SystemInfo::getLocalHostname (Address &address) { - char name[HOST_NAME_MAX]; - if (::gethostname(name, sizeof(name)) != 0) { - errno = WSAGetLastError(); - return false; - } - address.host = name; - return true; -} - -static const std::string LOCALHOST("127.0.0.1"); -static const std::string TCP("tcp"); - -void SystemInfo::getLocalIpAddresses (uint16_t port, - std::vector<Address> &addrList) { - enum { MAX_URL_INTERFACES = 100 }; - - SOCKET s = socket (PF_INET, SOCK_STREAM, 0); - if (s != INVALID_SOCKET) { - INTERFACE_INFO interfaces[MAX_URL_INTERFACES]; - DWORD filledBytes = 0; - WSAIoctl (s, - SIO_GET_INTERFACE_LIST, - 0, - 0, - interfaces, - sizeof (interfaces), - &filledBytes, - 0, - 0); - unsigned int interfaceCount = filledBytes / sizeof (INTERFACE_INFO); - for (unsigned int i = 0; i < interfaceCount; ++i) { - if (interfaces[i].iiFlags & IFF_UP) { - std::string addr(inet_ntoa(interfaces[i].iiAddress.AddressIn.sin_addr)); - if (addr != LOCALHOST) - addrList.push_back(Address(TCP, addr, port)); - } - } - closesocket (s); - } -} - -void SystemInfo::getSystemId (std::string &osName, - std::string &nodeName, - std::string &release, - std::string &version, - std::string &machine) -{ - osName = "Microsoft Windows"; - - char node[MAX_COMPUTERNAME_LENGTH + 1]; - DWORD nodelen = MAX_COMPUTERNAME_LENGTH + 1; - GetComputerName (node, &nodelen); - nodeName = node; - - OSVERSIONINFOEX vinfo; - vinfo.dwOSVersionInfoSize = sizeof(vinfo); - GetVersionEx ((OSVERSIONINFO *)&vinfo); - - SYSTEM_INFO sinfo; - GetNativeSystemInfo(&sinfo); - - switch(vinfo.dwMajorVersion) { - case 5: - switch(vinfo.dwMinorVersion) { - case 0: - release ="2000"; - break; - case 1: - release = "XP"; - break; - case 2: - if (sinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || - sinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) - release = "XP-64"; - else - release = "Server 2003"; - break; - default: - release = "Windows"; - } - break; - case 6: - if (vinfo.wProductType == VER_NT_SERVER) - release = "Server 2008"; - else - release = "Vista"; - break; - default: - release = "Microsoft Windows"; - } - version = vinfo.szCSDVersion; - - switch(sinfo.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_AMD64: - machine = "x86-64"; - break; - case PROCESSOR_ARCHITECTURE_IA64: - machine = "IA64"; - break; - case PROCESSOR_ARCHITECTURE_INTEL: - machine = "x86"; - break; - default: - machine = "unknown"; - break; - } -} - -uint32_t SystemInfo::getProcessId() -{ - return static_cast<uint32_t>(::GetCurrentProcessId()); -} - -uint32_t SystemInfo::getParentProcessId() -{ - // Only want info for the current process, so ask for something specific. - // The module info won't be used here but it keeps the snapshot limited to - // the current process so a search through all processes is not needed. - HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); - if (snap == INVALID_HANDLE_VALUE) - return 0; - PROCESSENTRY32 entry; - entry.dwSize = sizeof(entry); - if (!Process32First(snap, &entry)) - entry.th32ParentProcessID = 0; - CloseHandle(snap); - return static_cast<uint32_t>(entry.th32ParentProcessID); -} - -std::string SystemInfo::getProcessName() -{ - std::string name; - - // Only want info for the current process, so ask for something specific. - // The module info won't be used here but it keeps the snapshot limited to - // the current process so a search through all processes is not needed. - HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); - if (snap == INVALID_HANDLE_VALUE) - return name; - PROCESSENTRY32 entry; - entry.dwSize = sizeof(entry); - if (!Process32First(snap, &entry)) - entry.szExeFile[0] = '\0'; - CloseHandle(snap); - name = entry.szExeFile; - return name; -} - -}} // namespace qpid::sys diff --git a/cpp/src/qpid/sys/windows/Thread.cpp b/cpp/src/qpid/sys/windows/Thread.cpp deleted file mode 100755 index 583a9613a3..0000000000 --- a/cpp/src/qpid/sys/windows/Thread.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/windows/check.h" - -#include <process.h> -#include <windows.h> - -namespace { -unsigned __stdcall runRunnable(void* p) -{ - static_cast<qpid::sys::Runnable*>(p)->run(); - _endthreadex(0); - return 0; -} -} - -namespace qpid { -namespace sys { - -class ThreadPrivate { - friend class Thread; - - HANDLE threadHandle; - unsigned threadId; - - ThreadPrivate(Runnable* runnable) { - uintptr_t h = _beginthreadex(0, - 0, - runRunnable, - runnable, - 0, - &threadId); - QPID_WINDOWS_CHECK_CRT_NZ(h); - threadHandle = reinterpret_cast<HANDLE>(h); - } - - ThreadPrivate() - : threadHandle(GetCurrentThread()), threadId(GetCurrentThreadId()) {} -}; - -Thread::Thread() {} - -Thread::Thread(Runnable* runnable) : impl(new ThreadPrivate(runnable)) {} - -Thread::Thread(Runnable& runnable) : impl(new ThreadPrivate(&runnable)) {} - -Thread::operator bool() { - return impl; -} - -bool Thread::operator==(const Thread& t) const { - return impl->threadId == t.impl->threadId; -} - -bool Thread::operator!=(const Thread& t) const { - return !(*this==t); -} - -void Thread::join() { - if (impl) { - DWORD status = WaitForSingleObject (impl->threadHandle, INFINITE); - QPID_WINDOWS_CHECK_NOT(status, WAIT_FAILED); - CloseHandle (impl->threadHandle); - impl->threadHandle = 0; - } -} - -unsigned long Thread::logId() { - return GetCurrentThreadId(); -} - -/* static */ -Thread Thread::current() { - Thread t; - t.impl.reset(new ThreadPrivate()); - return t; -} - -}} /* qpid::sys */ diff --git a/cpp/src/qpid/sys/windows/Time.cpp b/cpp/src/qpid/sys/windows/Time.cpp deleted file mode 100644 index 25c50819cd..0000000000 --- a/cpp/src/qpid/sys/windows/Time.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Time.h" -#include <ostream> -#include <boost/date_time/posix_time/posix_time.hpp> -#include <boost/thread/thread_time.hpp> -#include <windows.h> - -using namespace boost::posix_time; - -namespace { - -// High-res timing support. This will display times since program start, -// more or less. Keep track of the start value and the conversion factor to -// seconds. -bool timeInitialized = false; -LARGE_INTEGER start; -double freq = 1.0; - -} - -namespace qpid { -namespace sys { - -AbsTime::AbsTime(const AbsTime& t, const Duration& d) { - if (d == Duration::max()) { - timepoint = ptime(max_date_time); - } - else { - time_duration td = microseconds(d.nanosecs / 1000); - timepoint = t.timepoint + td; - } -} - -AbsTime AbsTime::FarFuture() { - AbsTime ff; - ptime maxd(max_date_time); - ff.timepoint = maxd; - return ff; -} - -AbsTime AbsTime::Epoch() { - AbsTime time_epoch; - time_epoch.timepoint = boost::posix_time::from_time_t(0); - return time_epoch; -} - -AbsTime AbsTime::now() { - AbsTime time_now; - time_now.timepoint = boost::get_system_time(); - return time_now; -} - -Duration::Duration(const AbsTime& start, const AbsTime& finish) { - time_duration d = finish.timepoint - start.timepoint; - nanosecs = d.total_nanoseconds(); -} - -std::ostream& operator<<(std::ostream& o, const Duration& d) { - return o << int64_t(d) << "ns"; -} - -std::ostream& operator<<(std::ostream& o, const AbsTime& t) { - std::string time_string = to_simple_string(t.timepoint); - return o << time_string; -} - - -void sleep(int secs) { - ::Sleep(secs * 1000); -} - -void usleep(uint64_t usecs) { - DWORD msecs = usecs / 1000; - if (msecs == 0) - msecs = 1; - ::Sleep(msecs); -} - -void outputFormattedNow(std::ostream& o) { - ::time_t rawtime; - ::tm timeinfo; - char time_string[100]; - - ::time( &rawtime ); -#ifdef _MSC_VER - ::localtime_s(&timeinfo, &rawtime); -#else - timeinfo = *(::localtime(&rawtime)); -#endif - ::strftime(time_string, 100, - "%Y-%m-%d %H:%M:%S", - &timeinfo); - o << time_string << " "; -} - -void outputHiresNow(std::ostream& o) { - if (!timeInitialized) { - start.QuadPart = 0; - LARGE_INTEGER iFreq; - iFreq.QuadPart = 1; - QueryPerformanceCounter(&start); - QueryPerformanceFrequency(&iFreq); - freq = static_cast<double>(iFreq.QuadPart); - timeInitialized = true; - } - LARGE_INTEGER iNow; - iNow.QuadPart = 0; - QueryPerformanceCounter(&iNow); - iNow.QuadPart -= start.QuadPart; - if (iNow.QuadPart < 0) - iNow.QuadPart = 0; - double now = static_cast<double>(iNow.QuadPart); - now /= freq; // now is seconds after this - o << std::fixed << std::setprecision(8) << std::setw(16) << std::setfill('0') << now << "s "; -} -}} diff --git a/cpp/src/qpid/sys/windows/mingw32_compat.h b/cpp/src/qpid/sys/windows/mingw32_compat.h deleted file mode 100644 index 51f613cc25..0000000000 --- a/cpp/src/qpid/sys/windows/mingw32_compat.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _sys_windows_mingw32_compat -#define _sys_windows_mingw32_compat -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifdef WIN32 -#ifndef _MSC_VER - -// -// The following definitions for extension function GUIDs and signatures are taken from -// MswSock.h in the Windows32 SDK. These rightfully belong in the mingw32 version of -// mswsock.h, but are not included presently. -// - -#define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} -typedef BOOL (PASCAL *LPFN_ACCEPTEX)(SOCKET,SOCKET,PVOID,DWORD,DWORD,DWORD,LPDWORD,LPOVERLAPPED); - -#endif -#endif - -#endif diff --git a/cpp/src/qpid/sys/windows/uuid.cpp b/cpp/src/qpid/sys/windows/uuid.cpp deleted file mode 100644 index 3316ecbc00..0000000000 --- a/cpp/src/qpid/sys/windows/uuid.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <rpc.h> -#ifdef uuid_t /* Done in rpcdce.h */ -# undef uuid_t -#endif - -#include "qpid/sys/windows/uuid.h" - -#include <string.h> - -void uuid_clear (uuid_t uu) { - UuidCreateNil (reinterpret_cast<UUID*>(uu)); -} - -void uuid_copy (uuid_t dst, const uuid_t src) { - memcpy (dst, src, qpid::sys::UuidSize); -} - -void uuid_generate (uuid_t out) { - UuidCreate (reinterpret_cast<UUID*>(out)); -} - -int uuid_is_null (const uuid_t uu) { - RPC_STATUS unused; - return UuidIsNil ((UUID*)uu, &unused); -} - -int uuid_parse (const char *in, uuid_t uu) { - return UuidFromString ((unsigned char*)in, (UUID*)uu) == RPC_S_OK ? 0 : -1; -} - -void uuid_unparse (const uuid_t uu, char *out) { - unsigned char *formatted; - if (UuidToString((UUID*)uu, &formatted) == RPC_S_OK) { -#ifdef _MSC_VER - strncpy_s (out, 36+1, (char*)formatted, _TRUNCATE); -#else - strncpy (out, (char*)formatted, 36+1); -#endif - RpcStringFree(&formatted); - } -} - -int uuid_compare (const uuid_t a, const uuid_t b) { - RPC_STATUS unused; - return !UuidEqual((UUID*)a, (UUID*)b, &unused); -} diff --git a/cpp/src/qpid/sys/windows/uuid.h b/cpp/src/qpid/sys/windows/uuid.h deleted file mode 100644 index 8ab132e9ce..0000000000 --- a/cpp/src/qpid/sys/windows/uuid.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _sys_windows_uuid_h -#define _sys_windows_uuid_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/types/ImportExport.h" -#include <qpid/sys/IntegerTypes.h> - -namespace qpid { namespace sys { const size_t UuidSize = 16; }} -typedef uint8_t uuid_t[qpid::sys::UuidSize]; - -QPID_TYPES_EXTERN void uuid_clear (uuid_t uu); -QPID_TYPES_EXTERN void uuid_copy (uuid_t dst, const uuid_t src); -QPID_TYPES_EXTERN void uuid_generate (uuid_t out); -QPID_TYPES_EXTERN int uuid_is_null (const uuid_t uu); // Returns 1 if null, else 0 -QPID_TYPES_EXTERN int uuid_parse (const char *in, uuid_t uu); // Returns 0 on success, else -1 -QPID_TYPES_EXTERN void uuid_unparse (const uuid_t uu, char *out); -QPID_TYPES_EXTERN int uuid_compare (const uuid_t a, const uuid_t b); - -#endif /*!_sys_windows_uuid_h*/ diff --git a/cpp/src/qpid/types/Exception.cpp b/cpp/src/qpid/types/Exception.cpp deleted file mode 100644 index 71390e6abd..0000000000 --- a/cpp/src/qpid/types/Exception.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/types/Exception.h" - -namespace qpid { -namespace types { - -Exception::Exception(const std::string& msg) throw() : message(msg) {} -Exception::~Exception() throw() {} -const char* Exception::what() const throw() { return message.c_str(); } - -}} // namespace qpid::types diff --git a/cpp/src/qpid/types/Uuid.cpp b/cpp/src/qpid/types/Uuid.cpp deleted file mode 100644 index 9face4e5d2..0000000000 --- a/cpp/src/qpid/types/Uuid.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/types/Uuid.h" -#include "qpid/sys/uuid.h" -#include <sstream> -#include <iostream> -#include <string.h> - -namespace qpid { -namespace types { - -using namespace std; - -const size_t Uuid::SIZE=16; -static const size_t UNPARSED_SIZE=36; - -Uuid::Uuid(bool unique) -{ - if (unique) { - generate(); - } else { - clear(); - } -} - -Uuid::Uuid(const Uuid& other) -{ - ::memcpy(bytes, other.bytes, Uuid::SIZE); -} - -Uuid::Uuid(const unsigned char* uuid) -{ - ::memcpy(bytes, uuid, Uuid::SIZE); -} - -Uuid& Uuid::operator=(const Uuid& other) -{ - if (this == &other) return *this; - ::memcpy(bytes, other.bytes, Uuid::SIZE); - return *this; -} - -void Uuid::generate() -{ - uuid_generate(bytes); -} - -void Uuid::clear() -{ - uuid_clear(bytes); -} - -// Force int 0/!0 to false/true; avoids compile warnings. -bool Uuid::isNull() const -{ - return !!uuid_is_null(bytes); -} - -Uuid::operator bool() const { return !isNull(); } -bool Uuid::operator!() const { return isNull(); } - -size_t Uuid::size() const { return SIZE; } - -const unsigned char* Uuid::data() const -{ - return bytes; -} - -bool operator==(const Uuid& a, const Uuid& b) -{ - return uuid_compare(a.bytes, b.bytes) == 0; -} - -bool operator!=(const Uuid& a, const Uuid& b) -{ - return !(a == b); -} - -bool operator<(const Uuid& a, const Uuid& b) -{ - return uuid_compare(a.bytes, b.bytes) < 0; -} - -bool operator>(const Uuid& a, const Uuid& b) -{ - return uuid_compare(a.bytes, b.bytes) > 0; -} - -bool operator<=(const Uuid& a, const Uuid& b) -{ - return uuid_compare(a.bytes, b.bytes) <= 0; -} - -bool operator>=(const Uuid& a, const Uuid& b) -{ - return uuid_compare(a.bytes, b.bytes) >= 0; -} - -ostream& operator<<(ostream& out, Uuid uuid) -{ - char unparsed[UNPARSED_SIZE + 1]; - uuid_unparse(uuid.bytes, unparsed); - return out << unparsed; -} - -istream& operator>>(istream& in, Uuid& uuid) -{ - char unparsed[UNPARSED_SIZE + 1] = {0}; - in.get(unparsed, sizeof(unparsed)); - if (uuid_parse(unparsed, uuid.bytes) != 0) - in.setstate(ios::failbit); - return in; -} - -std::string Uuid::str() const -{ - std::ostringstream os; - os << *this; - return os.str(); -} - -}} // namespace qpid::types diff --git a/cpp/src/qpid/types/Variant.cpp b/cpp/src/qpid/types/Variant.cpp deleted file mode 100644 index 0b28234025..0000000000 --- a/cpp/src/qpid/types/Variant.cpp +++ /dev/null @@ -1,890 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/types/Variant.h" -#include "qpid/Msg.h" -#include "qpid/log/Statement.h" -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/algorithm/string.hpp> -#include <algorithm> -#include <limits> -#include <sstream> - -namespace qpid { -namespace types { - -namespace { -const std::string EMPTY; -const std::string PREFIX("invalid conversion: "); -} - -InvalidConversion::InvalidConversion(const std::string& msg) : Exception(PREFIX + msg) {} - -class VariantImpl -{ - public: - VariantImpl(); - VariantImpl(bool); - VariantImpl(uint8_t); - VariantImpl(uint16_t); - VariantImpl(uint32_t); - VariantImpl(uint64_t); - VariantImpl(int8_t); - VariantImpl(int16_t); - VariantImpl(int32_t); - VariantImpl(int64_t); - VariantImpl(float); - VariantImpl(double); - VariantImpl(const std::string&, const std::string& encoding=std::string()); - VariantImpl(const Variant::Map&); - VariantImpl(const Variant::List&); - VariantImpl(const Uuid&); - ~VariantImpl(); - - VariantType getType() const; - - bool asBool() const; - uint8_t asUint8() const; - uint16_t asUint16() const; - uint32_t asUint32() const; - uint64_t asUint64() const; - int8_t asInt8() const; - int16_t asInt16() const; - int32_t asInt32() const; - int64_t asInt64() const; - float asFloat() const; - double asDouble() const; - std::string asString() const; - Uuid asUuid() const; - - const Variant::Map& asMap() const; - Variant::Map& asMap(); - const Variant::List& asList() const; - Variant::List& asList(); - - const std::string& getString() const; - std::string& getString(); - - void setEncoding(const std::string&); - const std::string& getEncoding() const; - - bool isEqualTo(VariantImpl&) const; - bool isEquivalentTo(VariantImpl&) const; - - static VariantImpl* create(const Variant&); - private: - const VariantType type; - union { - bool b; - uint8_t ui8; - uint16_t ui16; - uint32_t ui32; - uint64_t ui64; - int8_t i8; - int16_t i16; - int32_t i32; - int64_t i64; - float f; - double d; - void* v;//variable width data - } value; - std::string encoding;//optional encoding for variable length data - - template<class T> T convertFromString() const - { - std::string* s = reinterpret_cast<std::string*>(value.v); - if (std::numeric_limits<T>::is_signed || s->find('-') != 0) { - //lexical_cast won't fail if string is a negative number and T is unsigned - try { - return boost::lexical_cast<T>(*s); - } catch(const boost::bad_lexical_cast&) { - //don't return, throw exception below - } - } else { - //T is unsigned and number starts with '-' - try { - //handle special case of negative zero - if (boost::lexical_cast<int>(*s) == 0) return 0; - //else its a non-zero negative number so throw exception at end of function - } catch(const boost::bad_lexical_cast&) { - //wasn't a valid int, therefore not a valid uint - } - } - throw InvalidConversion(QPID_MSG("Cannot convert " << *s)); - } -}; - - -VariantImpl::VariantImpl() : type(VAR_VOID) { value.i64 = 0; } -VariantImpl::VariantImpl(bool b) : type(VAR_BOOL) { value.b = b; } -VariantImpl::VariantImpl(uint8_t i) : type(VAR_UINT8) { value.ui8 = i; } -VariantImpl::VariantImpl(uint16_t i) : type(VAR_UINT16) { value.ui16 = i; } -VariantImpl::VariantImpl(uint32_t i) : type(VAR_UINT32) { value.ui32 = i; } -VariantImpl::VariantImpl(uint64_t i) : type(VAR_UINT64) { value.ui64 = i; } -VariantImpl::VariantImpl(int8_t i) : type(VAR_INT8) { value.i8 = i; } -VariantImpl::VariantImpl(int16_t i) : type(VAR_INT16) { value.i16 = i; } -VariantImpl::VariantImpl(int32_t i) : type(VAR_INT32) { value.i32 = i; } -VariantImpl::VariantImpl(int64_t i) : type(VAR_INT64) { value.i64 = i; } -VariantImpl::VariantImpl(float f) : type(VAR_FLOAT) { value.f = f; } -VariantImpl::VariantImpl(double d) : type(VAR_DOUBLE) { value.d = d; } -VariantImpl::VariantImpl(const std::string& s, const std::string& e) - : type(VAR_STRING), encoding(e) { value.v = new std::string(s); } -VariantImpl::VariantImpl(const Variant::Map& m) : type(VAR_MAP) { value.v = new Variant::Map(m); } -VariantImpl::VariantImpl(const Variant::List& l) : type(VAR_LIST) { value.v = new Variant::List(l); } -VariantImpl::VariantImpl(const Uuid& u) : type(VAR_UUID) { value.v = new Uuid(u); } - -VariantImpl::~VariantImpl() { - switch (type) { - case VAR_STRING: - delete reinterpret_cast<std::string*>(value.v); - break; - case VAR_MAP: - delete reinterpret_cast<Variant::Map*>(value.v); - break; - case VAR_LIST: - delete reinterpret_cast<Variant::List*>(value.v); - break; - case VAR_UUID: - delete reinterpret_cast<Uuid*>(value.v); - break; - default: - break; - } -} - -VariantType VariantImpl::getType() const { return type; } - -namespace { - -bool same_char(char a, char b) -{ - return toupper(a) == toupper(b); -} - -bool caseInsensitiveMatch(const std::string& a, const std::string& b) -{ - return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), &same_char); -} - -const std::string TRUE("True"); -const std::string FALSE("False"); - -bool toBool(const std::string& s) -{ - if (caseInsensitiveMatch(s, TRUE)) return true; - if (caseInsensitiveMatch(s, FALSE)) return false; - try { return boost::lexical_cast<int>(s); } catch(const boost::bad_lexical_cast&) {} - throw InvalidConversion(QPID_MSG("Cannot convert " << s << " to bool")); -} - -template <class T> std::string toString(const T& t) -{ - std::stringstream out; - out << t; - return out.str(); -} - -template <class T> bool equal(const T& a, const T& b) -{ - return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); -} - -} - -bool VariantImpl::asBool() const -{ - switch(type) { - case VAR_VOID: return false; - case VAR_BOOL: return value.b; - case VAR_UINT8: return value.ui8; - case VAR_UINT16: return value.ui16; - case VAR_UINT32: return value.ui32; - case VAR_UINT64: return value.ui64; - case VAR_INT8: return value.i8; - case VAR_INT16: return value.i16; - case VAR_INT32: return value.i32; - case VAR_INT64: return value.i64; - case VAR_STRING: return toBool(*reinterpret_cast<std::string*>(value.v)); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_BOOL))); - } -} -uint8_t VariantImpl::asUint8() const -{ - switch(type) { - case VAR_UINT8: return value.ui8; - case VAR_UINT16: - if (value.ui16 <= 0x00ff) - return uint8_t(value.ui16); - break; - case VAR_UINT32: - if (value.ui32 <= 0x000000ff) - return uint8_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= 0x00000000000000ff) - return uint8_t(value.ui64); - break; - case VAR_INT8: - if (value.i8 >= 0) - return uint8_t(value.i8); - break; - case VAR_INT16: - if (value.i16 >= 0 && value.i16 <= 0x00ff) - return uint8_t(value.i16); - break; - case VAR_INT32: - if (value.i32 >= 0 && value.i32 <= 0x000000ff) - return uint8_t(value.i32); - break; - case VAR_INT64: - if (value.i64 >= 0 && value.i64 <= 0x00000000000000ff) - return uint8_t(value.i64); - break; - case VAR_STRING: return convertFromString<uint8_t>(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT8))); -} -uint16_t VariantImpl::asUint16() const -{ - switch(type) { - case VAR_UINT8: return value.ui8; - case VAR_UINT16: return value.ui16; - case VAR_UINT32: - if (value.ui32 <= 0x0000ffff) - return uint16_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= 0x000000000000ffff) - return uint16_t(value.ui64); - break; - case VAR_INT8: - if (value.i8 >= 0) - return uint16_t(value.i8); - break; - case VAR_INT16: - if (value.i16 >= 0) - return uint16_t(value.i16); - break; - case VAR_INT32: - if (value.i32 >= 0 && value.i32 <= 0x0000ffff) - return uint16_t(value.i32); - break; - case VAR_INT64: - if (value.i64 >= 0 && value.i64 <= 0x000000000000ffff) - return uint16_t(value.i64); - break; - case VAR_STRING: return convertFromString<uint16_t>(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT16))); -} -uint32_t VariantImpl::asUint32() const -{ - switch(type) { - case VAR_UINT8: return value.ui8; - case VAR_UINT16: return value.ui16; - case VAR_UINT32: return value.ui32; - case VAR_UINT64: - if (value.ui64 <= 0x00000000ffffffff) - return uint32_t(value.ui64); - break; - case VAR_INT8: - if (value.i8 >= 0) - return uint32_t(value.i8); - break; - case VAR_INT16: - if (value.i16 >= 0) - return uint32_t(value.i16); - break; - case VAR_INT32: - if (value.i32 >= 0) - return uint32_t(value.i32); - break; - case VAR_INT64: - if (value.i64 >= 0 && value.i64 <= 0x00000000ffffffff) - return uint32_t(value.i64); - break; - case VAR_STRING: return convertFromString<uint32_t>(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT32))); -} -uint64_t VariantImpl::asUint64() const -{ - switch(type) { - case VAR_UINT8: return value.ui8; - case VAR_UINT16: return value.ui16; - case VAR_UINT32: return value.ui32; - case VAR_UINT64: return value.ui64; - case VAR_INT8: - if (value.i8 >= 0) - return uint64_t(value.i8); - break; - case VAR_INT16: - if (value.i16 >= 0) - return uint64_t(value.i16); - break; - case VAR_INT32: - if (value.i32 >= 0) - return uint64_t(value.i32); - break; - case VAR_INT64: - if (value.i64 >= 0) - return uint64_t(value.i64); - break; - case VAR_STRING: return convertFromString<uint64_t>(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UINT64))); -} - -int8_t VariantImpl::asInt8() const -{ - switch(type) { - case VAR_INT8: return value.i8; - case VAR_INT16: - if ((value.i16 >= std::numeric_limits<int8_t>::min()) && (value.i16 <= std::numeric_limits<int8_t>::max())) - return int8_t(value.i16); - break; - case VAR_INT32: - if ((value.i32 >= std::numeric_limits<int8_t>::min()) && (value.i32 <= std::numeric_limits<int8_t>::max())) - return int8_t(value.i32); - break; - case VAR_INT64: - if ((value.i64 >= std::numeric_limits<int8_t>::min()) && (value.i64 <= std::numeric_limits<int8_t>::max())) - return int8_t(value.i64); - break; - case VAR_UINT8: - if (value.ui8 <= std::numeric_limits<int8_t>::max()) - return int8_t(value.ui8); - break; - case VAR_UINT16: - if (value.ui16 <= std::numeric_limits<int8_t>::max()) - return int8_t(value.ui16); - break; - case VAR_UINT32: - if (value.ui32 <= (uint32_t) std::numeric_limits<int8_t>::max()) - return int8_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= (uint64_t) std::numeric_limits<int8_t>::max()) - return int8_t(value.ui64); - break; - case VAR_STRING: return convertFromString<int8_t>(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT8))); -} -int16_t VariantImpl::asInt16() const -{ - switch(type) { - case VAR_INT8: return value.i8; - case VAR_INT16: return value.i16; - case VAR_INT32: - if ((value.i32 >= std::numeric_limits<int16_t>::min()) && (value.i32 <= std::numeric_limits<int16_t>::max())) - return int16_t(value.i32); - break; - case VAR_INT64: - if ((value.i64 >= std::numeric_limits<int16_t>::min()) && (value.i64 <= std::numeric_limits<int16_t>::max())) - return int16_t(value.i64); - break; - case VAR_UINT8: return int16_t(value.ui8); - case VAR_UINT16: - if (value.ui16 <= std::numeric_limits<int16_t>::max()) - return int16_t(value.ui16); - break; - case VAR_UINT32: - if (value.ui32 <= (uint32_t) std::numeric_limits<int16_t>::max()) - return int16_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= (uint64_t) std::numeric_limits<int16_t>::max()) - return int16_t(value.ui64); - break; - case VAR_STRING: return convertFromString<int16_t>(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT16))); -} -int32_t VariantImpl::asInt32() const -{ - switch(type) { - case VAR_INT8: return value.i8; - case VAR_INT16: return value.i16; - case VAR_INT32: return value.i32; - case VAR_INT64: - if ((value.i64 >= std::numeric_limits<int32_t>::min()) && (value.i64 <= std::numeric_limits<int32_t>::max())) - return int32_t(value.i64); - break; - case VAR_UINT8: return int32_t(value.ui8); - case VAR_UINT16: return int32_t(value.ui16); - case VAR_UINT32: - if (value.ui32 <= (uint32_t) std::numeric_limits<int32_t>::max()) - return int32_t(value.ui32); - break; - case VAR_UINT64: - if (value.ui64 <= (uint64_t) std::numeric_limits<int32_t>::max()) - return int32_t(value.ui64); - break; - case VAR_STRING: return convertFromString<int32_t>(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT32))); -} -int64_t VariantImpl::asInt64() const -{ - switch(type) { - case VAR_INT8: return value.i8; - case VAR_INT16: return value.i16; - case VAR_INT32: return value.i32; - case VAR_INT64: return value.i64; - case VAR_UINT8: return int64_t(value.ui8); - case VAR_UINT16: return int64_t(value.ui16); - case VAR_UINT32: return int64_t(value.ui32); - case VAR_UINT64: - if (value.ui64 <= (uint64_t) std::numeric_limits<int64_t>::max()) - return int64_t(value.ui64); - break; - case VAR_STRING: return convertFromString<int64_t>(); - default: break; - } - throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_INT64))); -} -float VariantImpl::asFloat() const -{ - switch(type) { - case VAR_FLOAT: return value.f; - case VAR_STRING: return convertFromString<float>(); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_FLOAT))); - } -} -double VariantImpl::asDouble() const -{ - switch(type) { - case VAR_FLOAT: return value.f; - case VAR_DOUBLE: return value.d; - case VAR_STRING: return convertFromString<double>(); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_DOUBLE))); - } -} -std::string VariantImpl::asString() const -{ - switch(type) { - case VAR_VOID: return EMPTY; - case VAR_BOOL: return value.b ? TRUE : FALSE; - case VAR_UINT8: return boost::lexical_cast<std::string>((int) value.ui8); - case VAR_UINT16: return boost::lexical_cast<std::string>(value.ui16); - case VAR_UINT32: return boost::lexical_cast<std::string>(value.ui32); - case VAR_UINT64: return boost::lexical_cast<std::string>(value.ui64); - case VAR_INT8: return boost::lexical_cast<std::string>((int) value.i8); - case VAR_INT16: return boost::lexical_cast<std::string>(value.i16); - case VAR_INT32: return boost::lexical_cast<std::string>(value.i32); - case VAR_INT64: return boost::lexical_cast<std::string>(value.i64); - case VAR_DOUBLE: return boost::lexical_cast<std::string>(value.d); - case VAR_FLOAT: return boost::lexical_cast<std::string>(value.f); - case VAR_STRING: return *reinterpret_cast<std::string*>(value.v); - case VAR_UUID: return reinterpret_cast<Uuid*>(value.v)->str(); - case VAR_LIST: return toString(asList()); - case VAR_MAP: return toString(asMap()); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_STRING))); - } -} -Uuid VariantImpl::asUuid() const -{ - switch(type) { - case VAR_UUID: return *reinterpret_cast<Uuid*>(value.v); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_UUID))); - } -} - -bool VariantImpl::isEqualTo(VariantImpl& other) const -{ - if (type == other.type) { - switch(type) { - case VAR_VOID: return true; - case VAR_BOOL: return value.b == other.value.b; - case VAR_UINT8: return value.ui8 == other.value.ui8; - case VAR_UINT16: return value.ui16 == other.value.ui16; - case VAR_UINT32: return value.ui32 == other.value.ui32; - case VAR_UINT64: return value.ui64 == other.value.ui64; - case VAR_INT8: return value.i8 == other.value.i8; - case VAR_INT16: return value.i16 == other.value.i16; - case VAR_INT32: return value.i32 == other.value.i32; - case VAR_INT64: return value.i64 == other.value.i64; - case VAR_DOUBLE: return value.d == other.value.d; - case VAR_FLOAT: return value.f == other.value.f; - case VAR_STRING: return *reinterpret_cast<std::string*>(value.v) - == *reinterpret_cast<std::string*>(other.value.v); - case VAR_UUID: return *reinterpret_cast<Uuid*>(value.v) - == *reinterpret_cast<Uuid*>(other.value.v); - case VAR_LIST: return equal(asList(), other.asList()); - case VAR_MAP: return equal(asMap(), other.asMap()); - } - } - return false; -} - -const Variant::Map& VariantImpl::asMap() const -{ - switch(type) { - case VAR_MAP: return *reinterpret_cast<Variant::Map*>(value.v); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_MAP))); - } -} - -Variant::Map& VariantImpl::asMap() -{ - switch(type) { - case VAR_MAP: return *reinterpret_cast<Variant::Map*>(value.v); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_MAP))); - } -} - -const Variant::List& VariantImpl::asList() const -{ - switch(type) { - case VAR_LIST: return *reinterpret_cast<Variant::List*>(value.v); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_LIST))); - } -} - -Variant::List& VariantImpl::asList() -{ - switch(type) { - case VAR_LIST: return *reinterpret_cast<Variant::List*>(value.v); - default: throw InvalidConversion(QPID_MSG("Cannot convert from " << getTypeName(type) << " to " << getTypeName(VAR_LIST))); - } -} - -std::string& VariantImpl::getString() -{ - switch(type) { - case VAR_STRING: return *reinterpret_cast<std::string*>(value.v); - default: throw InvalidConversion(QPID_MSG("Variant is not a string; use asString() if conversion is required.")); - } -} - -const std::string& VariantImpl::getString() const -{ - switch(type) { - case VAR_STRING: return *reinterpret_cast<std::string*>(value.v); - default: throw InvalidConversion(QPID_MSG("Variant is not a string; use asString() if conversion is required.")); - } -} - -void VariantImpl::setEncoding(const std::string& s) { encoding = s; } -const std::string& VariantImpl::getEncoding() const { return encoding; } - -std::string getTypeName(VariantType type) -{ - switch (type) { - case VAR_VOID: return "void"; - case VAR_BOOL: return "bool"; - case VAR_UINT8: return "uint8"; - case VAR_UINT16: return "uint16"; - case VAR_UINT32: return "uint32"; - case VAR_UINT64: return "uint64"; - case VAR_INT8: return "int8"; - case VAR_INT16: return "int16"; - case VAR_INT32: return "int32"; - case VAR_INT64: return "int64"; - case VAR_FLOAT: return "float"; - case VAR_DOUBLE: return "double"; - case VAR_STRING: return "string"; - case VAR_MAP: return "map"; - case VAR_LIST: return "list"; - case VAR_UUID: return "uuid"; - } - return "<unknown>";//should never happen -} - -VariantImpl* VariantImpl::create(const Variant& v) -{ - switch (v.getType()) { - case VAR_BOOL: return new VariantImpl(v.asBool()); - case VAR_UINT8: return new VariantImpl(v.asUint8()); - case VAR_UINT16: return new VariantImpl(v.asUint16()); - case VAR_UINT32: return new VariantImpl(v.asUint32()); - case VAR_UINT64: return new VariantImpl(v.asUint64()); - case VAR_INT8: return new VariantImpl(v.asInt8()); - case VAR_INT16: return new VariantImpl(v.asInt16()); - case VAR_INT32: return new VariantImpl(v.asInt32()); - case VAR_INT64: return new VariantImpl(v.asInt64()); - case VAR_FLOAT: return new VariantImpl(v.asFloat()); - case VAR_DOUBLE: return new VariantImpl(v.asDouble()); - case VAR_STRING: return new VariantImpl(v.asString(), v.getEncoding()); - case VAR_MAP: return new VariantImpl(v.asMap()); - case VAR_LIST: return new VariantImpl(v.asList()); - case VAR_UUID: return new VariantImpl(v.asUuid()); - default: return new VariantImpl(); - } -} - -Variant::Variant() : impl(0) {} -Variant::Variant(bool b) : impl(new VariantImpl(b)) {} -Variant::Variant(uint8_t i) : impl(new VariantImpl(i)) {} -Variant::Variant(uint16_t i) : impl(new VariantImpl(i)) {} -Variant::Variant(uint32_t i) : impl(new VariantImpl(i)) {} -Variant::Variant(uint64_t i) : impl(new VariantImpl(i)) {} -Variant::Variant(int8_t i) : impl(new VariantImpl(i)) {} -Variant::Variant(int16_t i) : impl(new VariantImpl(i)) {} -Variant::Variant(int32_t i) : impl(new VariantImpl(i)) {} -Variant::Variant(int64_t i) : impl(new VariantImpl(i)) {} -Variant::Variant(float f) : impl(new VariantImpl(f)) {} -Variant::Variant(double d) : impl(new VariantImpl(d)) {} -Variant::Variant(const std::string& s) : impl(new VariantImpl(s)) {} -Variant::Variant(const char* s) : impl(new VariantImpl(std::string(s))) {} -Variant::Variant(const Map& m) : impl(new VariantImpl(m)) {} -Variant::Variant(const List& l) : impl(new VariantImpl(l)) {} -Variant::Variant(const Variant& v) : impl(VariantImpl::create(v)) {} -Variant::Variant(const Uuid& u) : impl(new VariantImpl(u)) {} - -Variant::~Variant() { if (impl) delete impl; } - -void Variant::reset() -{ - if (impl) delete impl; - impl = 0; -} - - -Variant& Variant::operator=(bool b) -{ - if (impl) delete impl; - impl = new VariantImpl(b); - return *this; -} - -Variant& Variant::operator=(uint8_t i) -{ - if (impl) delete impl; - impl = new VariantImpl(i); - return *this; -} -Variant& Variant::operator=(uint16_t i) -{ - if (impl) delete impl; - impl = new VariantImpl(i); - return *this; -} -Variant& Variant::operator=(uint32_t i) -{ - if (impl) delete impl; - impl = new VariantImpl(i); - return *this; -} -Variant& Variant::operator=(uint64_t i) -{ - if (impl) delete impl; - impl = new VariantImpl(i); - return *this; -} - -Variant& Variant::operator=(int8_t i) -{ - if (impl) delete impl; - impl = new VariantImpl(i); - return *this; -} -Variant& Variant::operator=(int16_t i) -{ - if (impl) delete impl; - impl = new VariantImpl(i); - return *this; -} -Variant& Variant::operator=(int32_t i) -{ - if (impl) delete impl; - impl = new VariantImpl(i); - return *this; -} -Variant& Variant::operator=(int64_t i) -{ - if (impl) delete impl; - impl = new VariantImpl(i); - return *this; -} - -Variant& Variant::operator=(float f) -{ - if (impl) delete impl; - impl = new VariantImpl(f); - return *this; -} -Variant& Variant::operator=(double d) -{ - if (impl) delete impl; - impl = new VariantImpl(d); - return *this; -} - -Variant& Variant::operator=(const std::string& s) -{ - if (impl) delete impl; - impl = new VariantImpl(s); - return *this; -} - -Variant& Variant::operator=(const char* s) -{ - if (impl) delete impl; - impl = new VariantImpl(std::string(s)); - return *this; -} - -Variant& Variant::operator=(const Uuid& u) -{ - if (impl) delete impl; - impl = new VariantImpl(u); - return *this; -} - -Variant& Variant::operator=(const Map& m) -{ - if (impl) delete impl; - impl = new VariantImpl(m); - return *this; -} - -Variant& Variant::operator=(const List& l) -{ - if (impl) delete impl; - impl = new VariantImpl(l); - return *this; -} - -Variant& Variant::operator=(const Variant& v) -{ - if (impl) delete impl; - impl = VariantImpl::create(v); - return *this; -} - -Variant& Variant::parse(const std::string& s) -{ - operator=(s); - try { - return operator=(asInt64()); - } catch (const InvalidConversion&) {} - try { - return operator=(asDouble()); - } catch (const InvalidConversion&) {} - try { - return operator=(asBool()); - } catch (const InvalidConversion&) {} - return *this; -} - - -VariantType Variant::getType() const { return impl ? impl->getType() : VAR_VOID; } -bool Variant::isVoid() const { return getType() == VAR_VOID; } -bool Variant::asBool() const { return impl && impl->asBool(); } -uint8_t Variant::asUint8() const { return impl ? impl->asUint8() : 0; } -uint16_t Variant::asUint16() const { return impl ? impl->asUint16() : 0; } -uint32_t Variant::asUint32() const { return impl ? impl->asUint32() : 0; } -uint64_t Variant::asUint64() const { return impl ? impl->asUint64() : 0; } -int8_t Variant::asInt8() const { return impl ? impl->asInt8() : 0; } -int16_t Variant::asInt16() const { return impl ? impl->asInt16() : 0; } -int32_t Variant::asInt32() const { return impl ? impl->asInt32(): 0; } -int64_t Variant::asInt64() const { return impl ? impl->asInt64() : 0; } -float Variant::asFloat() const { return impl ? impl->asFloat() : 0; } -double Variant::asDouble() const { return impl ? impl->asDouble() : 0; } -std::string Variant::asString() const { return impl ? impl->asString() : EMPTY; } -Uuid Variant::asUuid() const { return impl ? impl->asUuid() : Uuid(); } -const Variant::Map& Variant::asMap() const { if (!impl) throw InvalidConversion("Can't convert VOID to MAP"); return impl->asMap(); } -Variant::Map& Variant::asMap() { if (!impl) throw InvalidConversion("Can't convert VOID to MAP"); return impl->asMap(); } -const Variant::List& Variant::asList() const { if (!impl) throw InvalidConversion("Can't convert VOID to LIST"); return impl->asList(); } -Variant::List& Variant::asList() { if (!impl) throw InvalidConversion("Can't convert VOID to LIST"); return impl->asList(); } -const std::string& Variant::getString() const { if (!impl) throw InvalidConversion("Can't convert VOID to STRING"); return impl->getString(); } -std::string& Variant::getString() { if (!impl) throw InvalidConversion("Can't convert VOID to STRING"); return impl->getString(); } -void Variant::setEncoding(const std::string& s) { - if (!impl) impl = new VariantImpl(); - impl->setEncoding(s); -} -const std::string& Variant::getEncoding() const { return impl ? impl->getEncoding() : EMPTY; } - -Variant::operator bool() const { return asBool(); } -Variant::operator uint8_t() const { return asUint8(); } -Variant::operator uint16_t() const { return asUint16(); } -Variant::operator uint32_t() const { return asUint32(); } -Variant::operator uint64_t() const { return asUint64(); } -Variant::operator int8_t() const { return asInt8(); } -Variant::operator int16_t() const { return asInt16(); } -Variant::operator int32_t() const { return asInt32(); } -Variant::operator int64_t() const { return asInt64(); } -Variant::operator float() const { return asFloat(); } -Variant::operator double() const { return asDouble(); } -Variant::operator std::string() const { return asString(); } -Variant::operator Uuid() const { return asUuid(); } - -std::ostream& operator<<(std::ostream& out, const Variant::Map& map) -{ - out << "{"; - for (Variant::Map::const_iterator i = map.begin(); i != map.end(); ++i) { - if (i != map.begin()) out << ", "; - out << i->first << ":" << i->second; - } - out << "}"; - return out; -} - -std::ostream& operator<<(std::ostream& out, const Variant::List& list) -{ - out << "["; - for (Variant::List::const_iterator i = list.begin(); i != list.end(); ++i) { - if (i != list.begin()) out << ", "; - out << *i; - } - out << "]"; - return out; -} - -std::ostream& operator<<(std::ostream& out, const Variant& value) -{ - switch (value.getType()) { - case VAR_MAP: - out << value.asMap(); - break; - case VAR_LIST: - out << value.asList(); - break; - case VAR_VOID: - out << "<void>"; - break; - default: - out << value.asString(); - break; - } - return out; -} - -bool operator==(const Variant& a, const Variant& b) -{ - return a.isEqualTo(b); -} - -bool Variant::isEqualTo(const Variant& other) const -{ - return impl && impl->isEqualTo(*other.impl); -} - -}} // namespace qpid::types diff --git a/cpp/src/qpid/xml/XmlExchange.cpp b/cpp/src/qpid/xml/XmlExchange.cpp deleted file mode 100644 index b7ff5d211d..0000000000 --- a/cpp/src/qpid/xml/XmlExchange.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "config.h" - -#include "qpid/xml/XmlExchange.h" - -#include "qpid/broker/DeliverableMessage.h" - -#include "qpid/log/Statement.h" -#include "qpid/broker/FedOps.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" - -#include "qpid/Plugin.h" - -#include <xercesc/framework/MemBufInputSource.hpp> - -#ifdef XQ_EFFECTIVE_BOOLEAN_VALUE_HPP -#include <xqilla/ast/XQEffectiveBooleanValue.hpp> -#endif - -#include <xqilla/ast/XQGlobalVariable.hpp> - -#include <xqilla/context/ItemFactory.hpp> -#include <xqilla/xqilla-simple.hpp> - -#include <boost/bind.hpp> -#include <functional> -#include <algorithm> -#include <iostream> -#include <sstream> - -using namespace qpid::framing; -using namespace qpid::sys; -using qpid::management::Manageable; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -XQilla XmlBinding::xqilla; - -XmlBinding::XmlBinding(const std::string& key, const Queue::shared_ptr queue, const std::string& _fedOrigin, Exchange* parent, - const ::qpid::framing::FieldTable& _arguments, const std::string& queryText ) - : Binding(key, queue, parent, _arguments), - xquery(), - parse_message_content(true), - fedOrigin(_fedOrigin) -{ - startManagement(); - - QPID_LOG(trace, "Creating binding with query: " << queryText ); - - try { - Query q(xqilla.parse(X(queryText.c_str()))); - xquery = q; - - QPID_LOG(trace, "Bound successfully with query: " << queryText ); - - parse_message_content = false; - - if (xquery->getQueryBody()->getStaticAnalysis().areContextFlagsUsed()) { - parse_message_content = true; - } - else { - GlobalVariables &vars = const_cast<GlobalVariables&>(xquery->getVariables()); - for (GlobalVariables::iterator it = vars.begin(); it != vars.end(); ++it) { - if ((*it)->getStaticAnalysis().areContextFlagsUsed()) { - parse_message_content = true; - break; - } - } - } - } - catch (XQException& e) { - throw InternalErrorException(QPID_MSG("Could not parse xquery:"+ queryText)); - } - catch (...) { - throw InternalErrorException(QPID_MSG("Unexpected error - Could not parse xquery:"+ queryText)); - } -} - - -XmlExchange::XmlExchange(const string& _name, Manageable* _parent, Broker* b) : Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -XmlExchange::XmlExchange(const std::string& _name, bool _durable, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -bool XmlExchange::bind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable* args) -{ - - // Federation uses bind for unbind and reorigin comands as well as for binds. - // - // Both federated and local binds are done in this method. Other - // federated requests are done by calling the relevent methods. - - string fedOp; - string fedTags; - string fedOrigin; - - if (args) - fedOp = args->getAsString(qpidFedOp); - if (! fedOp.empty()) { - fedTags = args->getAsString(qpidFedTags); - fedOrigin = args->getAsString(qpidFedOrigin); - } - - if (fedOp == fedOpUnbind) { - return fedUnbind(fedOrigin, fedTags, queue, bindingKey, args); - } - else if (fedOp == fedOpReorigin) { - fedReorigin(); - return true; - } - - // OK, looks like we're really going to bind - - else if (fedOp.empty() || fedOp == fedOpBind) { - - string queryText = args->getAsString("xquery"); - - RWlock::ScopedWlock l(lock); - - XmlBinding::vector& bindings(bindingsMap[bindingKey]); - XmlBinding::vector::ConstPtr p = bindings.snapshot(); - - if (!p || std::find_if(p->begin(), p->end(), MatchQueueAndOrigin(queue, fedOrigin)) == p->end()) { - - XmlBinding::shared_ptr binding(new XmlBinding (bindingKey, queue, fedOrigin, this, *args, queryText)); - bindings.add(binding); - - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - return false; - } - } - else { - QPID_LOG(warning, "Unknown Federation Op: " << fedOp); - } - - routeIVE(); - propagateFedOp(bindingKey, fedTags, fedOp, fedOrigin, args); - - return true; -} - -bool XmlExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable* args) -{ - /* - * When called directly, no qpidFedOrigin argument will be - * present. When called from federation, it will be present. - * - * This is a bit of a hack - the binding needs the origin, but - * this interface, as originally defined, would not supply one. - */ - string fedOrigin; - if (args) fedOrigin = args->getAsString(qpidFedOrigin); - - RWlock::ScopedWlock l(lock); - if (bindingsMap[bindingKey].remove_if(MatchQueueAndOrigin(queue, fedOrigin))) { - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - return true; - } else { - return false; - } -} - -bool XmlExchange::matches(Query& query, Deliverable& msg, const qpid::framing::FieldTable* args, bool parse_message_content) -{ - string msgContent; - - try { - QPID_LOG(trace, "matches: query is [" << UTF8(query->getQueryText()) << "]"); - - boost::scoped_ptr<DynamicContext> context(query->createDynamicContext()); - if (!context.get()) { - throw InternalErrorException(QPID_MSG("Query context looks munged ...")); - } - - if (parse_message_content) { - - msg.getMessage().getFrames().getContent(msgContent); - - QPID_LOG(trace, "matches: message content is [" << msgContent << "]"); - - XERCES_CPP_NAMESPACE::MemBufInputSource xml((const XMLByte*) msgContent.c_str(), - msgContent.length(), "input" ); - - // This will parse the document using either Xerces or FastXDM, depending - // on your XQilla configuration. FastXDM can be as much as 10x faster. - - Sequence seq(context->parseDocument(xml)); - - if(!seq.isEmpty() && seq.first()->isNode()) { - context->setContextItem(seq.first()); - context->setContextPosition(1); - context->setContextSize(1); - } - } - - if (args) { - FieldTable::ValueMap::const_iterator v = args->begin(); - for(; v != args->end(); ++v) { - - if (v->second->convertsTo<double>()) { - QPID_LOG(trace, "XmlExchange, external variable (double): " << v->first << " = " << v->second->get<double>()); - Item::Ptr value = context->getItemFactory()->createDouble(v->second->get<double>(), context.get()); - context->setExternalVariable(X(v->first.c_str()), value); - } - else if (v->second->convertsTo<int>()) { - QPID_LOG(trace, "XmlExchange, external variable (int):" << v->first << " = " << v->second->getData().getInt()); - Item::Ptr value = context->getItemFactory()->createInteger(v->second->get<int>(), context.get()); - context->setExternalVariable(X(v->first.c_str()), value); - } - else if (v->second->convertsTo<std::string>()) { - QPID_LOG(trace, "XmlExchange, external variable (string):" << v->first << " = " << v->second->getData().getString().c_str()); - Item::Ptr value = context->getItemFactory()->createString(X(v->second->get<std::string>().c_str()), context.get()); - context->setExternalVariable(X(v->first.c_str()), value); - } - - } - } - - Result result = query->execute(context.get()); -#ifdef XQ_EFFECTIVE_BOOLEAN_VALUE_HPP - Item::Ptr first_ = result->next(context.get()); - Item::Ptr second_ = result->next(context.get()); - return XQEffectiveBooleanValue::get(first_, second_, context.get(), 0); -#else - return result->getEffectiveBooleanValue(context.get(), 0); -#endif - } - catch (XQException& e) { - QPID_LOG(warning, "Could not parse XML content (or message headers):" << msgContent); - } - catch (...) { - QPID_LOG(warning, "Unexpected error routing message: " << msgContent); - } - return 0; -} - -// Future optimization: If any query in a binding for a given routing key requires -// message content, parse the message once, and use that parsed form for all bindings. -// -// Future optimization: XQilla does not currently do document projection for data -// accessed via the context item. If there is a single query for a given routing key, -// and it accesses document data, this could be a big win. -// -// Document projection often is not a win if you have multiple queries on the same data. -// But for very large messages, if all these queries are on the first part of the data, -// it could still be a big win. - -void XmlExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* args) -{ - PreRoute pr(msg, this); - try { - XmlBinding::vector::ConstPtr p; - BindingList b(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >); - { - RWlock::ScopedRlock l(lock); - p = bindingsMap[routingKey].snapshot(); - if (!p.get()) return; - } - - for (std::vector<XmlBinding::shared_ptr>::const_iterator i = p->begin(); i != p->end(); i++) { - if (matches((*i)->xquery, msg, args, (*i)->parse_message_content)) { - b->push_back(*i); - } - } - doRoute(msg, b); - } catch (...) { - QPID_LOG(warning, "XMLExchange " << getName() << ": exception routing message with query " << routingKey); - } -} - - -bool XmlExchange::isBound(Queue::shared_ptr queue, const string* const bindingKey, const FieldTable* const) -{ - RWlock::ScopedRlock l(lock); - if (bindingKey) { - XmlBindingsMap::iterator i = bindingsMap.find(*bindingKey); - - if (i == bindingsMap.end()) - return false; - if (!queue) - return true; - XmlBinding::vector::ConstPtr p = i->second.snapshot(); - return p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end(); - } else if (!queue) { - //if no queue or routing key is specified, just report whether any bindings exist - return bindingsMap.size() > 0; - } else { - for (XmlBindingsMap::iterator i = bindingsMap.begin(); i != bindingsMap.end(); i++) { - XmlBinding::vector::ConstPtr p = i->second.snapshot(); - if (p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end()) return true; - } - return false; - } - -} - -XmlExchange::~XmlExchange() -{ - bindingsMap.clear(); -} - -void XmlExchange::propagateFedOp(const std::string& bindingKey, const std::string& fedTags, const std::string& fedOp, const std::string& fedOrigin, const qpid::framing::FieldTable* args) -{ - FieldTable nonFedArgs; - - if (args) { - for (qpid::framing::FieldTable::ValueMap::const_iterator i=args->begin(); i != args->end(); ++i) { - const string& name(i->first); - if (name != qpidFedOp && - name != qpidFedTags && - name != qpidFedOrigin) { - nonFedArgs.insert((*i)); - } - } - } - - FieldTable* propArgs = (nonFedArgs.count() > 0 ? &nonFedArgs : 0); - Exchange::propagateFedOp(bindingKey, fedTags, fedOp, fedOrigin, propArgs); -} - -bool XmlExchange::fedUnbind(const string& fedOrigin, const string& fedTags, Queue::shared_ptr queue, const string& bindingKey, const FieldTable* args) -{ - RWlock::ScopedRlock l(lock); - - if (unbind(queue, bindingKey, args)) { - propagateFedOp(bindingKey, fedTags, fedOpUnbind, fedOrigin); - return true; - } - return false; -} - -void XmlExchange::fedReorigin() -{ - std::vector<std::string> keys2prop; - { - RWlock::ScopedRlock l(lock); - for (XmlBindingsMap::iterator i = bindingsMap.begin(); i != bindingsMap.end(); ++i) { - XmlBinding::vector::ConstPtr p = i->second.snapshot(); - if (std::find_if(p->begin(), p->end(), MatchOrigin(string())) != p->end()) { - keys2prop.push_back(i->first); - } - } - } /* lock dropped */ - for (std::vector<std::string>::const_iterator key = keys2prop.begin(); - key != keys2prop.end(); key++) { - propagateFedOp( *key, string(), fedOpBind, string()); - } -} - - -XmlExchange::MatchOrigin::MatchOrigin(const string& _origin) : origin(_origin) {} - -bool XmlExchange::MatchOrigin::operator()(XmlBinding::shared_ptr b) -{ - return b->fedOrigin == origin; -} - - -XmlExchange::MatchQueueAndOrigin::MatchQueueAndOrigin(Queue::shared_ptr _queue, const string& _origin) : queue(_queue), origin(_origin) {} - -bool XmlExchange::MatchQueueAndOrigin::operator()(XmlBinding::shared_ptr b) -{ - return b->queue == queue and b->fedOrigin == origin; -} - - -const std::string XmlExchange::typeName("xml"); - -} -} diff --git a/cpp/src/qpid/xml/XmlExchange.h b/cpp/src/qpid/xml/XmlExchange.h deleted file mode 100644 index 958bad4931..0000000000 --- a/cpp/src/qpid/xml/XmlExchange.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _XmlExchange_ -#define _XmlExchange_ - -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/sys/Monitor.h" -#include "qpid/broker/Queue.h" - -#include <xqilla/xqilla-simple.hpp> - -#include <boost/scoped_ptr.hpp> - -#include <map> -#include <vector> -#include <string> - -using namespace std; - -namespace qpid { -namespace broker { - -class Broker; - -typedef boost::shared_ptr<XQQuery> Query; - -struct XmlBinding : public Exchange::Binding { - - static XQilla xqilla; - - typedef boost::shared_ptr<XmlBinding> shared_ptr; - typedef qpid::sys::CopyOnWriteArray<XmlBinding::shared_ptr> vector; - - Query xquery; - bool parse_message_content; - const std::string fedOrigin; // empty for local bindings - - XmlBinding(const std::string& key, const Queue::shared_ptr queue, const std::string& fedOrigin, Exchange* parent, - const ::qpid::framing::FieldTable& _arguments, const std::string& ); - -}; - -class XmlExchange : public virtual Exchange { - - typedef std::map<string, XmlBinding::vector> XmlBindingsMap; - XmlBindingsMap bindingsMap; - - qpid::sys::RWlock lock; - - bool matches(Query& query, Deliverable& msg, const qpid::framing::FieldTable* args, bool parse_message_content); - - public: - static const std::string typeName; - - XmlExchange(const std::string& name, management::Manageable* parent = 0, Broker* broker = 0); - XmlExchange(const std::string& _name, bool _durable, - const qpid::framing::FieldTable& _args, management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - virtual bool bind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual void route(Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args); - - virtual bool isBound(Queue::shared_ptr queue, const std::string* const routingKey, const qpid::framing::FieldTable* const args); - - virtual void propagateFedOp(const std::string& bindingKey, const std::string& fedTags, const std::string& fedOp, const std::string& fedOrigin, const qpid::framing::FieldTable* args=0); - - virtual bool fedUnbind(const std::string& fedOrigin, const std::string& fedTags, Queue::shared_ptr queue, const std::string& bindingKey, const qpid::framing::FieldTable* args); - - virtual void fedReorigin(); - - virtual bool supportsDynamicBinding() { return true; } - - virtual ~XmlExchange(); - - struct MatchOrigin { - const std::string origin; - MatchOrigin(const std::string& origin); - bool operator()(XmlBinding::shared_ptr b); - }; - - struct MatchQueueAndOrigin { - const Queue::shared_ptr queue; - const std::string origin; - MatchQueueAndOrigin(Queue::shared_ptr queue, const std::string& origin); - bool operator()(XmlBinding::shared_ptr b); - }; - -}; - - -} -} - - -#endif diff --git a/cpp/src/qpid/xml/XmlExchangePlugin.cpp b/cpp/src/qpid/xml/XmlExchangePlugin.cpp deleted file mode 100644 index 742b878e86..0000000000 --- a/cpp/src/qpid/xml/XmlExchangePlugin.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <sstream> -#include "qpid/acl/Acl.h" -#include "qpid/broker/Broker.h" -#include "qpid/Plugin.h" -#include "qpid/log/Statement.h" - -#include <boost/shared_ptr.hpp> -#include <boost/utility/in_place_factory.hpp> - -#include "qpid/xml/XmlExchange.h" - -namespace qpid { -namespace broker { // ACL uses the acl namespace here - should I? - -using namespace std; -class Broker; - -Exchange::shared_ptr create(const std::string& name, bool durable, - const framing::FieldTable& args, - management::Manageable* parent, - Broker* broker) -{ - Exchange::shared_ptr e(new XmlExchange(name, durable, args, parent, broker)); - return e; -} - - -class XmlExchangePlugin : public Plugin -{ -public: - void earlyInitialize(Plugin::Target& target); - void initialize(Plugin::Target& target); -}; - - -void XmlExchangePlugin::earlyInitialize(Plugin::Target& target) -{ - Broker* broker = dynamic_cast<broker::Broker*>(&target); - if (broker) { - broker->getExchanges().registerType(XmlExchange::typeName, &create); - QPID_LOG(info, "Registered xml exchange"); - } -} - -void XmlExchangePlugin::initialize(Target&) {} - - -static XmlExchangePlugin matchingPlugin; - - -}} // namespace qpid::acl diff --git a/cpp/src/qpidd.cpp b/cpp/src/qpidd.cpp deleted file mode 100644 index a7c1dbe8a6..0000000000 --- a/cpp/src/qpidd.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "./qpidd.h" -#include "qpid/Plugin.h" -#include "qpid/Version.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Statement.h" - -#include <iostream> -#include <memory> -using namespace std; - -auto_ptr<QpiddOptions> options; - -int main(int argc, char* argv[]) -{ - try - { - BootstrapOptions bootOptions(argv[0]); - string defaultPath (bootOptions.module.loadDir); - // Parse only the common, load, and log options to see which - // modules need to be loaded. Once the modules are loaded, - // the command line will be re-parsed with all of the - // module-supplied options. - try { - bootOptions.parse (argc, argv, bootOptions.common.config, true); - qpid::log::Logger::instance().configure(bootOptions.log); - } catch (const std::exception& e) { - // Couldn't configure logging so write the message direct to stderr. - cerr << "Unexpected error: " << e.what() << endl; - return 1; - } - - for (vector<string>::iterator iter = bootOptions.module.load.begin(); - iter != bootOptions.module.load.end(); - iter++) - qpid::tryShlib (iter->data(), false); - - if (!bootOptions.module.noLoad) { - bool isDefault = defaultPath == bootOptions.module.loadDir; - qpid::loadModuleDir (bootOptions.module.loadDir, isDefault); - } - - // Parse options - options.reset(new QpiddOptions(argv[0])); - options->parse(argc, argv, options->common.config); - - // Options that just print information. - if (options->common.help || options->common.version) { - if (options->common.version) - cout << "qpidd (" << qpid::product << ") version " - << qpid::version << endl; - else if (options->common.help) - options->usage(); - return 0; - } - - // Everything else is driven by the platform-specific broker - // logic. - QpiddBroker broker; - return broker.execute(options.get()); - } - catch(const exception& e) { - QPID_LOG(critical, "Unexpected error: " << e.what()); - } - return 1; -} diff --git a/cpp/src/qpidd.h b/cpp/src/qpidd.h deleted file mode 100644 index c702270e80..0000000000 --- a/cpp/src/qpidd.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef QPID_H -#define QPID_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/Modules.h" -#include "qpid/Options.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Options.h" - -#include <memory> - -// BootstrapOptions is a minimal subset of options used for a pre-parse -// of the command line to discover which plugin modules need to be loaded. -// The pre-parse is necessary because plugin modules may supply their own -// set of options. CommonOptions is needed to properly support loading -// from a configuration file. -struct BootstrapOptions : public qpid::Options { - qpid::CommonOptions common; - qpid::ModuleOptions module; - qpid::log::Options log; - - BootstrapOptions(const char *argv0); -}; - -// Each platform derives an options struct from QpiddOptionsPrivate, adding -// platform-specific option types. QpiddOptions needs to allocation one of -// these derived structs from its constructor. -struct QpiddOptions; -struct QpiddOptionsPrivate { - QpiddOptions *options; - QpiddOptionsPrivate(QpiddOptions *parent) : options(parent) {} - virtual ~QpiddOptionsPrivate() {} -protected: - QpiddOptionsPrivate() {} -}; - -struct QpiddOptions : public qpid::Options { - qpid::CommonOptions common; - qpid::ModuleOptions module; - qpid::broker::Broker::Options broker; - qpid::log::Options log; - std::auto_ptr<QpiddOptionsPrivate> platform; - - QpiddOptions(const char *argv0); - void usage() const; -}; - -class QpiddBroker { -public: - int execute (QpiddOptions *options); -}; - -#endif /*!QPID_H*/ diff --git a/cpp/src/rdma.cmake b/cpp/src/rdma.cmake deleted file mode 100644 index e020cb84a9..0000000000 --- a/cpp/src/rdma.cmake +++ /dev/null @@ -1,118 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# -# RDMA (Remote DMA) wrapper CMake fragment, to be included in CMakeLists.txt -# - -# Optional RDMA support. Requires ibverbs and rdma_cm. - -include(CheckIncludeFiles) -include(CheckLibraryExists) - -CHECK_LIBRARY_EXISTS (ibverbs ibv_create_qp "" HAVE_IBVERBS) -CHECK_LIBRARY_EXISTS (rdmacm rdma_create_id "" HAVE_RDMACM) -CHECK_INCLUDE_FILES (infiniband/verbs.h HAVE_IBVERBS_H) -CHECK_INCLUDE_FILES (rdma/rdma_cma.h HAVE_RDMACM_H) - -set (rdma_default ${rdma_force}) -if (HAVE_IBVERBS AND HAVE_IBVERBS_H) - if (HAVE_RDMACM AND HAVE_RDMACM_H) - set (rdma_default ON) - endif (HAVE_RDMACM AND HAVE_RDMACM_H) -endif (HAVE_IBVERBS AND HAVE_IBVERBS_H) - -option(BUILD_RDMA "Build with support for Remote DMA protocols" ${rdma_default}) -if (BUILD_RDMA) - if (NOT HAVE_IBVERBS) - message(FATAL_ERROR "libibverbs not found, required for RDMA support") - endif (NOT HAVE_IBVERBS) - if (NOT HAVE_RDMACM) - message(FATAL_ERROR "librdmacm not found, required for RDMA support") - endif (NOT HAVE_RDMACM) - if (NOT HAVE_IBVERBS_H) - message(FATAL_ERROR "ibverbs headers not found, required for RDMA support") - endif (NOT HAVE_IBVERBS_H) - if (NOT HAVE_RDMACM_H) - message(FATAL_ERROR "rdmacm headers not found, required for RDMA support") - endif (NOT HAVE_RDMACM_H) - - set (rdma_SOURCES - qpid/sys/rdma/rdma_exception.h - qpid/sys/rdma/rdma_factories.cpp - qpid/sys/rdma/rdma_factories.h - qpid/sys/rdma/RdmaIO.cpp - qpid/sys/rdma/RdmaIO.h - qpid/sys/rdma/rdma_wrap.cpp - qpid/sys/rdma/rdma_wrap.h - ) - - add_library (rdmawrap SHARED ${rdma_SOURCES}) - target_link_libraries (rdmawrap qpidcommon rdmacm ibverbs) - set_target_properties (rdmawrap PROPERTIES VERSION ${qpidc_version}) - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(rdmawrap PROPERTIES - COMPILE_FLAGS -Wno-missing-field-initializers - LINK_FLAGS -Wl,--no-undefined) - endif (CMAKE_COMPILER_IS_GNUCXX) - - install (TARGETS rdmawrap - DESTINATION ${QPID_INSTALL_LIBDIR} - COMPONENT ${QPID_COMPONENT_COMMON}) - - add_library (rdma MODULE qpid/sys/RdmaIOPlugin.cpp) - target_link_libraries (rdma qpidbroker rdmawrap) - set_target_properties (rdma PROPERTIES - PREFIX "") - - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(rdma PROPERTIES - COMPILE_FLAGS -Wno-missing-field-initializers - LINK_FLAGS -Wl,--no-undefined) - endif (CMAKE_COMPILER_IS_GNUCXX) - - install (TARGETS rdma - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - - add_library (rdmaconnector MODULE qpid/client/RdmaConnector.cpp) - target_link_libraries (rdmaconnector qpidclient rdmawrap) - set_target_properties (rdmaconnector PROPERTIES - PREFIX "") - - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(rdmaconnector PROPERTIES - COMPILE_FLAGS -Wno-missing-field-initializers - LINK_FLAGS -Wl,--no-undefined) - endif (CMAKE_COMPILER_IS_GNUCXX) - - install (TARGETS rdmaconnector - DESTINATION ${QPIDC_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_CLIENT}) - - # RDMA test/sample programs - add_executable (RdmaServer qpid/sys/rdma/RdmaServer.cpp) - target_link_libraries (RdmaServer rdmawrap qpidcommon) - add_executable (RdmaClient qpid/sys/rdma/RdmaClient.cpp) - target_link_libraries (RdmaClient rdmawrap qpidcommon) - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(RdmaClient PROPERTIES - COMPILE_FLAGS -Wno-missing-field-initializers) - endif (CMAKE_COMPILER_IS_GNUCXX) - -endif (BUILD_RDMA) diff --git a/cpp/src/replication.mk b/cpp/src/replication.mk deleted file mode 100644 index e5da32f88b..0000000000 --- a/cpp/src/replication.mk +++ /dev/null @@ -1,52 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# Make file for building two plugins for asynchronously replicating -# queues. - -dmoduleexec_LTLIBRARIES += replicating_listener.la replication_exchange.la - -# a queue event listener plugin that creates messages on a replication -# queue corresponding to enqueue and dequeue events: -replicating_listener_la_SOURCES = \ - qpid/replication/constants.h \ - qpid/replication/ReplicatingEventListener.cpp \ - qpid/replication/ReplicatingEventListener.h - -replicating_listener_la_LIBADD = libqpidbroker.la -if SUNOS - replicating_listener_la_LIBADD += libqpidcommon.la -lboost_program_options -luuid $(SUNCC_RUNTIME_LIBS) -endif -replicating_listener_la_LDFLAGS = $(PLUGINLDFLAGS) - -# a custom exchange plugin that allows an exchange to be created that -# can process the messages from a replication queue (populated on the -# source system by the replicating listener plugin above) and take the -# corresponding action on the local queues -replication_exchange_la_SOURCES = \ - qpid/replication/constants.h \ - qpid/replication/ReplicationExchange.cpp \ - qpid/replication/ReplicationExchange.h - -replication_exchange_la_LIBADD = libqpidbroker.la - -if SUNOS - replication_exchange_la_LIBADD += libqpidcommon.la -lboost_program_options $(SUNCC_RUNTIME_LIBS) -luuid -endif -replication_exchange_la_LDFLAGS = $(PLUGINLDFLAGS) - diff --git a/cpp/src/ssl.cmake b/cpp/src/ssl.cmake deleted file mode 100644 index c205845388..0000000000 --- a/cpp/src/ssl.cmake +++ /dev/null @@ -1,117 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# -# SSL/TLS CMake fragment, to be included in CMakeLists.txt -# - -# Optional SSL/TLS support. Requires Netscape Portable Runtime on Linux. - -include(FindPkgConfig) - -# According to some cmake docs this is not a reliable way to detect -# pkg-configed libraries, but it's no worse than what we did under -# autotools -pkg_check_modules(NSS nss) - -set (ssl_default ${ssl_force}) -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - set (ssl_default ON) -else (CMAKE_SYSTEM_NAME STREQUAL Windows) - if (NSS_FOUND) - set (ssl_default ON) - endif (NSS_FOUND) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -option(BUILD_SSL "Build with support for SSL" ${ssl_default}) -if (BUILD_SSL) - if (CMAKE_SYSTEM_NAME STREQUAL Windows) - set (sslclient_windows_SOURCES qpid/client/windows/SslConnector.cpp) - set (sslbroker_windows_SOURCES qpid/broker/windows/SslProtocolFactory.cpp) - set (sslcommon_windows_SOURCES - qpid/sys/windows/SslAsynchIO.cpp - ) - set (windows_ssl_libs Secur32.lib) - set (windows_ssl_server_libs Crypt32.lib) - else (CMAKE_SYSTEM_NAME STREQUAL Windows) - - if (NOT NSS_FOUND) - message(FATAL_ERROR "nss/nspr not found, required for ssl support") - endif (NOT NSS_FOUND) - - foreach(f ${NSS_CFLAGS}) - set (NSS_COMPILE_FLAGS "${NSS_COMPILE_FLAGS} ${f}") - endforeach(f) - - foreach(f ${NSS_LDFLAGS}) - set (NSS_LINK_FLAGS "${NSS_LINK_FLAGS} ${f}") - endforeach(f) - - set (sslcommon_SOURCES - qpid/sys/ssl/check.h - qpid/sys/ssl/check.cpp - qpid/sys/ssl/util.h - qpid/sys/ssl/util.cpp - qpid/sys/ssl/SslSocket.h - qpid/sys/ssl/SslSocket.cpp - qpid/sys/ssl/SslIo.h - qpid/sys/ssl/SslIo.cpp - ) - - add_library (sslcommon SHARED ${sslcommon_SOURCES}) - target_link_libraries (sslcommon qpidcommon) - set_target_properties (sslcommon PROPERTIES - VERSION ${qpidc_version} - COMPILE_FLAGS ${NSS_COMPILE_FLAGS} - LINK_FLAGS ${NSS_LINK_FLAGS}) - - set (ssl_SOURCES - qpid/sys/SslPlugin.cpp - qpid/sys/ssl/SslHandler.h - qpid/sys/ssl/SslHandler.cpp - ) - add_library (ssl MODULE ${ssl_SOURCES}) - target_link_libraries (ssl qpidbroker sslcommon ${Boost_PROGRAM_OPTIONS_LIBRARY}) - set_target_properties (ssl PROPERTIES - PREFIX "" - COMPILE_FLAGS ${NSS_COMPILE_FLAGS}) - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(ssl PROPERTIES - LINK_FLAGS -Wl,--no-undefined) - endif (CMAKE_COMPILER_IS_GNUCXX) - - install (TARGETS ssl - DESTINATION ${QPIDD_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_BROKER}) - - add_library (sslconnector MODULE qpid/client/SslConnector.cpp) - target_link_libraries (sslconnector qpidclient sslcommon) - set_target_properties (sslconnector PROPERTIES - PREFIX "" - COMPILE_FLAGS ${NSS_COMPILE_FLAGS}) - if (CMAKE_COMPILER_IS_GNUCXX) - set_target_properties(sslconnector PROPERTIES - LINK_FLAGS -Wl,--no-undefined) - endif (CMAKE_COMPILER_IS_GNUCXX) - - install (TARGETS sslconnector - DESTINATION ${QPIDC_MODULE_DIR} - COMPONENT ${QPID_COMPONENT_CLIENT}) - endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -endif (BUILD_SSL) diff --git a/cpp/src/ssl.mk b/cpp/src/ssl.mk deleted file mode 100644 index 4dba9bb61c..0000000000 --- a/cpp/src/ssl.mk +++ /dev/null @@ -1,64 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# -# Makefile fragment, conditionally included in Makefile.am -# -libsslcommon_la_SOURCES = \ - qpid/sys/ssl/check.h \ - qpid/sys/ssl/check.cpp \ - qpid/sys/ssl/util.h \ - qpid/sys/ssl/util.cpp \ - qpid/sys/ssl/SslSocket.h \ - qpid/sys/ssl/SslSocket.cpp \ - qpid/sys/ssl/SslIo.h \ - qpid/sys/ssl/SslIo.cpp - -SSLCOMMON_VERSION_INFO = 2:0:0 -libsslcommon_la_LDFLAGS = -version-info $(SSLCOMMON_VERSION_INFO) -libsslcommon_la_LIBADD= -lnss3 -lssl3 -lnspr4 libqpidcommon.la -libsslcommon_la_CXXFLAGS=$(AM_CXXFLAGS) $(SSL_CFLAGS) - -lib_LTLIBRARIES += libsslcommon.la - -ssl_la_SOURCES = \ - qpid/sys/SslPlugin.cpp \ - qpid/sys/ssl/SslHandler.h \ - qpid/sys/ssl/SslHandler.cpp - -ssl_la_LIBADD= libqpidbroker.la libsslcommon.la - -ssl_la_CXXFLAGS=$(AM_CXXFLAGS) $(SSL_CFLAGS) - -ssl_la_LDFLAGS = $(PLUGINLDFLAGS) - -dmoduleexec_LTLIBRARIES += ssl.la - -sslconnector_la_SOURCES = \ - qpid/client/SslConnector.cpp - -sslconnector_la_LIBADD = \ - libqpidclient.la \ - libsslcommon.la - -sslconnector_la_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.conf\" $(SSL_CFLAGS) - -sslconnector_la_LDFLAGS = $(PLUGINLDFLAGS) - -cmoduleexec_LTLIBRARIES += \ - sslconnector.la diff --git a/cpp/src/tests/.valgrind.supp b/cpp/src/tests/.valgrind.supp deleted file mode 100644 index 2c6a1509ff..0000000000 --- a/cpp/src/tests/.valgrind.supp +++ /dev/null @@ -1,202 +0,0 @@ -{ - Leak in TCPConnector: https://bugzilla.redhat.com/show_bug.cgi?id=520600 - Memcheck:Leak - fun:_vgrZU_libcZdsoZa_calloc - fun:_dl_allocate_tls - fun:* - fun:* - fun:* - fun:_ZN4qpid6client12TCPConnector7connectERKSsi -} - -{ - Leak in TCPConnector: https://bugzilla.redhat.com/show_bug.cgi?id=520600 - Memcheck:Leak - fun:_vgrZU_libcZdsoZa_calloc - fun:_dl_allocate_tls - fun:* - fun:* - fun:_ZN4qpid6client12TCPConnector7connectERKSsi -} - -{ - Reported on FC5 and RHEL5 when md5 sasl libs are installed - Memcheck:Leak - fun:* - fun:_dl_map_object_from_fd - fun:_dl_map_object - fun:openaux - fun:_dl_catch_error - fun:_dl_map_object_deps - fun:dl_open_worker - fun:_dl_catch_error - fun:_dl_open - fun:dlopen_doit - fun:_dl_catch_error - fun:_dlerror_run - fun:* - fun:_sasl_get_plugin - fun:_sasl_load_plugins - fun:sasl_client_init -} -{ - Benign leak in CPG - patched version. - Memcheck:Leak - fun:* - fun:openais_service_connect - fun:cpg_initialize -} - -{ - Benign error in libcpg. - Memcheck:Param - socketcall.sendmsg(msg.msg_iov[i]) - obj:*/libpthread-2.5.so - obj:*/libcpg.so.2.0.0 -} - -{ - Uninitialised value problem in _dl_relocate (F7, F8) - Memcheck:Cond - fun:_dl_relocate_object - fun:*dl_* -} - -{ - False "possibly leaked" in boost program_options - global std::string var. - Memcheck:Leak - fun:_Znwj - fun:_ZNSs4_Rep9_S_createEjjRKSaIcE - obj:/usr/lib/libstdc++.so.6.0.8 - fun:_ZNSsC1EPKcRKSaIcE - obj:/usr/lib/libboost_program_options.so.1.33.1 -} - -{ - INVESTIGATE - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls - fun:pthread_create@@GLIBC_2.2.5 - fun:_ZN4qpid6client9Connector4initEv - fun:_ZN4qpid6client14ConnectionImpl4openERKSsiS3_S3_S3_ -} - -{ - INVESTIGATE - Memcheck:Param - write(buf) - obj:/lib64/tls/libc-2.3.4.so - fun:_ZNK4qpid3sys6Socket5writeEPKvm - fun:_ZN4qpid3sys8AsynchIO9writeableERNS0_14DispatchHandleE -} - -{ - "Conditional jump or move depends on uninitialised value(s)" from Xerces parser - Memcheck:Cond - fun:_ZN11xercesc_2_717XMLUTF8Transcoder13transcodeFromEPKhjPtjRjPh - fun:_ZN11xercesc_2_79XMLReader14xcodeMoreCharsEPtPhj - fun:_ZN11xercesc_2_79XMLReader17refreshCharBufferEv -} - -{ - INVESTIGATE - Memcheck:Param - socketcall.sendto(msg) - fun:send - fun:get_mapping - fun:__nscd_get_map_ref - fun:nscd_gethst_r - fun:__nscd_gethostbyname_r - fun:gethostbyname_r@@GLIBC_2.2.5 - fun:gethostbyname - fun:_ZNK4qpid3sys6Socket7connectERKSsi -} - -{ - INVESTIGATE - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls - fun:pthread_create@@GLIBC_2.2.5 - fun:_ZN4qpid6broker5Timer5startEv - fun:_ZN4qpid6broker5TimerC1Ev - fun:_ZN4qpid6broker10DtxManagerC1Ev - fun:_ZN4qpid6broker6BrokerC1ERKNS1_7OptionsE - fun:_ZN4qpid6broker6Broker6createERKNS1_7OptionsE - fun:_ZN20ClientSessionFixtureC1Ev - fun:_Z14testQueueQueryv - fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor8functionEv - obj:/usr/lib64/libboost_unit_test_framework.so.1.32.0 - fun:_ZN5boost17execution_monitor7executeEbi - fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor21execute_and_translateEPNS0_9test_caseEMS3_FvvEi - fun:_ZN5boost9unit_test9test_case3runEv - fun:_ZN5boost9unit_test10test_suite6do_runEv - fun:_ZN5boost9unit_test9test_case3runEv - fun:main -} - -{ - INVESTIGATE - Memcheck:Leak - fun:calloc - fun:_dl_allocate_tls - fun:pthread_create@@GLIBC_2.2.5 - fun:_ZN4qpid6client9Connector4initEv -} - -{ - MICK -- FIX - Memcheck:Leak - fun:_Znam - fun:_ZN4qpid7Options5parseEiPPcRKSsb -} - -{ - MICK -- FIX - Memcheck:Leak - fun:malloc - fun:strdup - fun:_ZN4qpid7Options5parseEiPPcRKSsb -} - -{ - CPG error - seems benign. - Memcheck:Param - socketcall.sendmsg(msg.msg_iov[i]) - obj:* - obj:*/libcpg.so.2.0.0 -} - -{ - Known leak in boost.thread 1.33.1. Wildcards for 64/32 bit diffs. - Memcheck:Leak - fun:* - obj:/usr/*/libboost_thread.so.1.33.1 - fun:_ZN5boost6detail3tss3setEPv -} - -{ - Shows up on RHEL5: believed benign - Memcheck:Cond - fun:__strcpy_chk - fun:_sasl_load_plugins - fun:sasl_client_init -} - -{ - Seems like a use after delete issue in boost unit_test - Memcheck:Addr8 - fun:_ZN5boost9unit_test14framework_implD1Ev - fun:exit - fun:(below main) -} - -{ - Seems like a use after delete issue in boost unit_test - Memcheck:Addr4 - fun:_ZN5boost9unit_test14framework_implD1Ev - fun:exit - fun:(below main) -} - diff --git a/cpp/src/tests/AccumulatedAckTest.cpp b/cpp/src/tests/AccumulatedAckTest.cpp deleted file mode 100644 index c736a519d2..0000000000 --- a/cpp/src/tests/AccumulatedAckTest.cpp +++ /dev/null @@ -1,237 +0,0 @@ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/AccumulatedAck.h" -#include "unit_test.h" -#include <iostream> -#include <list> - -using std::list; -using namespace qpid::framing; - - -namespace qpid { -namespace tests { - -bool covers(const AccumulatedAck& ack, int i) -{ - return ack.covers(SequenceNumber(i)); -} - -void update(AccumulatedAck& ack, int start, int end) -{ - ack.update(SequenceNumber(start), SequenceNumber(end)); -} - -QPID_AUTO_TEST_SUITE(AccumulatedAckTestSuite) - -QPID_AUTO_TEST_CASE(testGeneral) -{ - AccumulatedAck ack(0); - ack.clear(); - update(ack, 3,3); - update(ack, 7,7); - update(ack, 9,9); - update(ack, 1,2); - update(ack, 4,5); - update(ack, 6,6); - - for(int i = 1; i <= 7; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(covers(ack, 9)); - - BOOST_CHECK(!covers(ack, 8)); - BOOST_CHECK(!covers(ack, 10)); - - ack.consolidate(); - - for(int i = 1; i <= 7; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(covers(ack, 9)); - - BOOST_CHECK(!covers(ack, 8)); - BOOST_CHECK(!covers(ack, 10)); -} - -QPID_AUTO_TEST_CASE(testCovers) -{ - AccumulatedAck ack(5); - update(ack, 7, 7); - update(ack, 9, 9); - - BOOST_CHECK(covers(ack, 1)); - BOOST_CHECK(covers(ack, 2)); - BOOST_CHECK(covers(ack, 3)); - BOOST_CHECK(covers(ack, 4)); - BOOST_CHECK(covers(ack, 5)); - BOOST_CHECK(covers(ack, 7)); - BOOST_CHECK(covers(ack, 9)); - - BOOST_CHECK(!covers(ack, 6)); - BOOST_CHECK(!covers(ack, 8)); - BOOST_CHECK(!covers(ack, 10)); -} - -QPID_AUTO_TEST_CASE(testUpdateFromCompletionData) -{ - AccumulatedAck ack(0); - SequenceNumber mark(2); - SequenceNumberSet ranges; - ranges.addRange(SequenceNumber(5), SequenceNumber(8)); - ranges.addRange(SequenceNumber(10), SequenceNumber(15)); - ranges.addRange(SequenceNumber(9), SequenceNumber(9)); - ranges.addRange(SequenceNumber(3), SequenceNumber(4)); - - ack.update(mark, ranges); - - for(int i = 0; i <= 15; i++) { - BOOST_CHECK(covers(ack, i)); - } - BOOST_CHECK(!covers(ack, 16)); - BOOST_CHECK_EQUAL((uint32_t) 15, ack.mark.getValue()); -} - -QPID_AUTO_TEST_CASE(testCase1) -{ - AccumulatedAck ack(3); - update(ack, 1,2); - for(int i = 1; i <= 3; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(!covers(ack, 4)); -} - -QPID_AUTO_TEST_CASE(testCase2) -{ - AccumulatedAck ack(3); - update(ack, 3,6); - for(int i = 1; i <= 6; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(!covers(ack, 7)); -} - -QPID_AUTO_TEST_CASE(testCase3) -{ - AccumulatedAck ack(3); - update(ack, 4,6); - for(int i = 1; i <= 6; i++) { - BOOST_CHECK(covers(ack, i)); - } - BOOST_CHECK(!covers(ack, 7)); -} - -QPID_AUTO_TEST_CASE(testCase4) -{ - AccumulatedAck ack(3); - update(ack, 5,6); - for(int i = 1; i <= 6; i++) { - if (i == 4) BOOST_CHECK(!covers(ack, i)); - else BOOST_CHECK(covers(ack, i)); - } - BOOST_CHECK(!covers(ack, 7)); -} - -QPID_AUTO_TEST_CASE(testConsolidation1) -{ - AccumulatedAck ack(3); - update(ack, 7,7); - BOOST_CHECK_EQUAL((uint32_t) 3, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 8,9); - BOOST_CHECK_EQUAL((uint32_t) 3, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 1,2); - BOOST_CHECK_EQUAL((uint32_t) 3, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 4,5); - BOOST_CHECK_EQUAL((uint32_t) 5, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 6,6); - BOOST_CHECK_EQUAL((uint32_t) 9, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 0, ack.ranges.size()); - - for(int i = 1; i <= 9; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(!covers(ack, 10)); -} - -QPID_AUTO_TEST_CASE(testConsolidation2) -{ - AccumulatedAck ack(0); - update(ack, 10,12); - BOOST_CHECK_EQUAL((uint32_t) 0, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - - update(ack, 7,9); - BOOST_CHECK_EQUAL((uint32_t) 0, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - BOOST_CHECK_EQUAL((uint32_t) 7, ack.ranges.front().start.getValue()); - BOOST_CHECK_EQUAL((uint32_t) 12, ack.ranges.front().end.getValue()); - - update(ack, 5,7); - BOOST_CHECK_EQUAL((uint32_t) 0, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - BOOST_CHECK_EQUAL((uint32_t) 5, ack.ranges.front().start.getValue()); - BOOST_CHECK_EQUAL((uint32_t) 12, ack.ranges.front().end.getValue()); - - update(ack, 3,4); - BOOST_CHECK_EQUAL((uint32_t) 0, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 1, ack.ranges.size()); - BOOST_CHECK_EQUAL((uint32_t) 3, ack.ranges.front().start.getValue()); - BOOST_CHECK_EQUAL((uint32_t) 12, ack.ranges.front().end.getValue()); - - update(ack, 1,2); - BOOST_CHECK_EQUAL((uint32_t) 12, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 0, ack.ranges.size()); - - for(int i = 1; i <= 12; i++) BOOST_CHECK(covers(ack, i)); - BOOST_CHECK(!covers(ack, 13)); -} - -QPID_AUTO_TEST_CASE(testConsolidation3) -{ - AccumulatedAck ack(0); - update(ack, 10,12); - update(ack, 6,7); - update(ack, 3,4); - update(ack, 1,15); - BOOST_CHECK_EQUAL((uint32_t) 15, ack.mark.getValue()); - BOOST_CHECK_EQUAL((size_t) 0, ack.ranges.size()); -} - -QPID_AUTO_TEST_CASE(testConsolidation4) -{ - AccumulatedAck ack(0); - ack.update(SequenceNumber(0), SequenceNumber(2)); - ack.update(SequenceNumber(5), SequenceNumber(8)); - ack.update(SequenceNumber(10), SequenceNumber(15)); - ack.update(SequenceNumber(9), SequenceNumber(9)); - ack.update(SequenceNumber(3), SequenceNumber(4)); - - for(int i = 0; i <= 15; i++) { - BOOST_CHECK(covers(ack, i)); - } - BOOST_CHECK(!covers(ack, 16)); - BOOST_CHECK_EQUAL((uint32_t) 15, ack.mark.getValue()); -} - -QPID_AUTO_TEST_SUITE_END() - - -}} // namespace qpid::tests diff --git a/cpp/src/tests/Address.cpp b/cpp/src/tests/Address.cpp deleted file mode 100644 index f41f27b6df..0000000000 --- a/cpp/src/tests/Address.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/messaging/Address.h" -#include "qpid/types/Variant.h" - -#include "unit_test.h" - -using namespace qpid::messaging; -using namespace qpid::types; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(AddressSuite) - -QPID_AUTO_TEST_CASE(testParseNameOnly) -{ - Address address("my-topic"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); -} - -QPID_AUTO_TEST_CASE(testParseSubject) -{ - Address address("my-topic/my-subject"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - BOOST_CHECK_EQUAL(std::string("my-subject"), address.getSubject()); -} - -QPID_AUTO_TEST_CASE(testParseOptions) -{ - Address address("my-topic; {a:bc, x:101, y:'a string'}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - - BOOST_CHECK_EQUAL(std::string("bc"), address.getOptions()["a"]); - BOOST_CHECK_EQUAL(101, static_cast<int>(address.getOptions()["x"])); - BOOST_CHECK_EQUAL(std::string("a string"), address.getOptions()["y"]); - - // Test asString() and asInt64() once here - - BOOST_CHECK_EQUAL(std::string("bc"), address.getOptions()["a"].asString()); - BOOST_CHECK_EQUAL(static_cast<uint16_t>(101), address.getOptions()["x"].asInt64()); - BOOST_CHECK_EQUAL(std::string("a string"), address.getOptions()["y"].asString()); -} - -QPID_AUTO_TEST_CASE(testParseSubjectAndOptions) -{ - Address address("my-topic/my-subject; {a:bc, x:101, y:'a string'}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - BOOST_CHECK_EQUAL(std::string("my-subject"), address.getSubject()); - - BOOST_CHECK_EQUAL(std::string("bc"), address.getOptions()["a"]); - BOOST_CHECK_EQUAL(101, static_cast<int>(address.getOptions()["x"])); - BOOST_CHECK_EQUAL(std::string("a string"), address.getOptions()["y"]); -} - -QPID_AUTO_TEST_CASE(testParseNestedOptions) -{ - Address address("my-topic; {a:{p:202, q:'another string'}, x:101, y:'a string'}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - BOOST_CHECK_EQUAL(202, static_cast<int>(address.getOptions()["a"].asMap()["p"])); - BOOST_CHECK_EQUAL(std::string("another string"), address.getOptions()["a"].asMap()["q"]); - BOOST_CHECK_EQUAL(std::string("a string"), address.getOptions()["y"]); -} - -QPID_AUTO_TEST_CASE(testParseOptionsWithList) -{ - Address address("my-topic; {a:[202, 'another string'], x:101}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - Variant::List& list = address.getOptions()["a"].asList(); - Variant::List::const_iterator i = list.begin(); - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL((uint16_t) 202, i->asInt64()); - BOOST_CHECK(++i != list.end()); - BOOST_CHECK_EQUAL(std::string("another string"), i->asString()); - BOOST_CHECK_EQUAL((uint16_t) 101, address.getOptions()["x"].asInt64()); -} - -QPID_AUTO_TEST_CASE(testParseOptionsWithEmptyList) -{ - Address address("my-topic; {a:[], x:101}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - Variant::List& list = address.getOptions()["a"].asList(); - BOOST_CHECK_EQUAL(list.size(), (size_t) 0); - BOOST_CHECK_EQUAL((uint16_t) 101, address.getOptions()["x"].asInt64()); -} - -QPID_AUTO_TEST_CASE(testParseOptionsWithEmptyMap) -{ - Address address("my-topic; {a:{}, x:101}"); - BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName()); - Variant::Map& map = address.getOptions()["a"].asMap(); - BOOST_CHECK_EQUAL(map.size(), (size_t) 0); - BOOST_CHECK_EQUAL((uint16_t) 101, address.getOptions()["x"].asInt64()); -} - -QPID_AUTO_TEST_CASE(testParseQuotedNameAndSubject) -{ - Address address("'my topic with / in it'/'my subject with ; in it'"); - BOOST_CHECK_EQUAL(std::string("my topic with / in it"), address.getName()); - BOOST_CHECK_EQUAL(std::string("my subject with ; in it"), address.getSubject()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} diff --git a/cpp/src/tests/Array.cpp b/cpp/src/tests/Array.cpp deleted file mode 100644 index 7622b89d15..0000000000 --- a/cpp/src/tests/Array.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include <sstream> -#include "qpid/framing/Array.h" -#include "qpid/framing/FieldValue.h" - -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ArrayTestSuite) - -using namespace qpid::framing; - -void populate(std::vector<std::string>& data, int count = 10) -{ - for (int i = 0; i < count; i++) { - std::stringstream out; - out << "item-" << i; - data.push_back(out.str()); - } -} - -QPID_AUTO_TEST_CASE(testEncodeDecode) -{ - std::vector<std::string> data; - populate(data); - - Array a(data); - - char buff[200]; - Buffer wbuffer(buff, 200); - a.encode(wbuffer); - - Array b; - Buffer rbuffer(buff, 200); - b.decode(rbuffer); - BOOST_CHECK_EQUAL(a, b); - - std::vector<std::string> data2; - b.collect(data2); - //BOOST_CHECK_EQUAL(data, data2); - BOOST_CHECK(data == data2); -} - -QPID_AUTO_TEST_CASE(testArrayAssignment) -{ - std::vector<std::string> data; - populate(data); - Array b; - { - Array a(data); - b = a; - BOOST_CHECK_EQUAL(a, b); - } - std::vector<std::string> data2; - b.collect(data2); - //BOOST_CHECK_EQUAL(data, data2); - BOOST_CHECK(data == data2); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/AsyncCompletion.cpp b/cpp/src/tests/AsyncCompletion.cpp deleted file mode 100644 index e32097106f..0000000000 --- a/cpp/src/tests/AsyncCompletion.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "unit_test.h" -#include "test_tools.h" -#include "BrokerFixture.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/sys/BlockingQueue.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/QueueQueryResult.h" -#include "qpid/client/TypedResult.h" - -using namespace std; -using namespace qpid; -using namespace client; -using namespace framing; - -namespace qpid { namespace broker { -class TransactionContext; -class PersistableQueue; -}} - -using broker::PersistableMessage; -using broker::NullMessageStore; -using broker::TransactionContext; -using broker::PersistableQueue; -using sys::TIME_SEC; -using boost::intrusive_ptr; - -/** @file Unit tests for async completion. - * Using a dummy store, verify that the broker indicates async completion of - * message enqueues at the correct time. - */ - -namespace qpid { -namespace tests { - -class AsyncCompletionMessageStore : public NullMessageStore { - public: - sys::BlockingQueue<boost::intrusive_ptr<PersistableMessage> > enqueued; - - AsyncCompletionMessageStore() : NullMessageStore() {} - ~AsyncCompletionMessageStore(){} - - void enqueue(TransactionContext*, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& ) - { - enqueued.push(msg); - } -}; - -QPID_AUTO_TEST_SUITE(AsyncCompletionTestSuite) - -QPID_AUTO_TEST_CASE(testWaitTillComplete) { - SessionFixture fix; - AsyncCompletionMessageStore* store = new AsyncCompletionMessageStore; - boost::shared_ptr<qpid::broker::MessageStore> p; - p.reset(store); - fix.broker->setStore(p); - AsyncSession s = fix.session; - - static const int count = 3; - - s.queueDeclare("q", arg::durable=true); - Completion transfers[count]; - for (int i = 0; i < count; ++i) { - Message msg(boost::lexical_cast<string>(i), "q"); - msg.getDeliveryProperties().setDeliveryMode(PERSISTENT); - transfers[i] = s.messageTransfer(arg::content=msg); - } - - // Get hold of the broker-side messages. - typedef vector<intrusive_ptr<PersistableMessage> > BrokerMessages; - BrokerMessages enqueued; - for (int j = 0; j < count; ++j) - enqueued.push_back(store->enqueued.pop(TIME_SEC)); - - // Send a sync, make sure it does not complete till all messages are complete. - // In reverse order for fun. - Completion sync = s.executionSync(arg::sync=true); - for (int k = count-1; k >= 0; --k) { - BOOST_CHECK(!transfers[k].isComplete()); // Should not be complete yet. - BOOST_CHECK(!sync.isComplete()); // Should not be complete yet. - enqueued[k]->enqueueComplete(); - } - sync.wait(); // Should complete now, all messages are completed. -} - -QPID_AUTO_TEST_CASE(testGetResult) { - SessionFixture fix; - AsyncSession s = fix.session; - - s.queueDeclare("q", arg::durable=true); - TypedResult<QueueQueryResult> tr = s.queueQuery("q"); - QueueQueryResult qq = tr.get(); - BOOST_CHECK_EQUAL(qq.getQueue(), "q"); - BOOST_CHECK_EQUAL(qq.getMessageCount(), 0U); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/AtomicValue.cpp b/cpp/src/tests/AtomicValue.cpp deleted file mode 100644 index d855d993a7..0000000000 --- a/cpp/src/tests/AtomicValue.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/sys/AtomicValue.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(AtomicValueTestSuite) - -QPID_AUTO_TEST_CASE(test) { - qpid::sys::AtomicValue<int> x(0); - BOOST_CHECK_EQUAL(++x, 1); - BOOST_CHECK_EQUAL(--x,0); - BOOST_CHECK_EQUAL(x+=5,5); - BOOST_CHECK_EQUAL(x-=10,-5); - BOOST_CHECK_EQUAL(x.fetchAndAdd(7), -5); - BOOST_CHECK_EQUAL(x.get(),2); - BOOST_CHECK_EQUAL(x.fetchAndSub(3), 2); - BOOST_CHECK_EQUAL(x.get(),-1); - - BOOST_CHECK_EQUAL(x.valueCompareAndSwap(-1,10), -1); - BOOST_CHECK_EQUAL(x.get(), 10); - BOOST_CHECK_EQUAL(x.valueCompareAndSwap(5, 6), 10); - BOOST_CHECK_EQUAL(x.get(), 10); - - BOOST_CHECK(!x.boolCompareAndSwap(5, 6)); - BOOST_CHECK_EQUAL(x.get(), 10); - BOOST_CHECK(x.boolCompareAndSwap(10, 6)); - BOOST_CHECK_EQUAL(x.get(), 6); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/Blob.cpp b/cpp/src/tests/Blob.cpp deleted file mode 100644 index 9878d92fe4..0000000000 --- a/cpp/src/tests/Blob.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - diff --git a/cpp/src/tests/BrokerFixture.h b/cpp/src/tests/BrokerFixture.h deleted file mode 100644 index 672d954572..0000000000 --- a/cpp/src/tests/BrokerFixture.h +++ /dev/null @@ -1,154 +0,0 @@ -#ifndef TESTS_BROKERFIXTURE_H -#define TESTS_BROKERFIXTURE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "SocketProxy.h" - -#include "qpid/broker/Broker.h" -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionImpl.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/LocalQueue.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/sys/Thread.h" -#include <boost/noncopyable.hpp> - -namespace qpid { -namespace tests { - -/** - * A fixture with an in-process broker. - */ -struct BrokerFixture : private boost::noncopyable { - typedef qpid::broker::Broker Broker; - typedef boost::intrusive_ptr<Broker> BrokerPtr; - - BrokerPtr broker; - qpid::sys::Thread brokerThread; - - BrokerFixture(Broker::Options opts=Broker::Options(), bool enableMgmt=false) { - // Keep the tests quiet unless logging env. vars have been set by user. - if (!::getenv("QPID_LOG_ENABLE") && !::getenv("QPID_TRACE")) { - qpid::log::Options logOpts; - logOpts.selectors.clear(); - logOpts.selectors.push_back("error+"); - qpid::log::Logger::instance().configure(logOpts); - } - opts.port=0; - // Management doesn't play well with multiple in-process brokers. - opts.enableMgmt=enableMgmt; - opts.workerThreads=1; - opts.dataDir=""; - opts.auth=false; - broker = Broker::create(opts); - // TODO aconway 2007-12-05: At one point BrokerFixture - // tests could hang in Connection ctor if the following - // line is removed. This may not be an issue anymore. - broker->accept(); - broker->getPort(qpid::broker::Broker::TCP_TRANSPORT); - brokerThread = qpid::sys::Thread(*broker); - }; - - void shutdownBroker() - { - broker->shutdown(); - broker = BrokerPtr(); - } - - ~BrokerFixture() { - if (broker) broker->shutdown(); - brokerThread.join(); - } - - /** Open a connection to the broker. */ - void open(qpid::client::Connection& c) { - c.open("localhost", broker->getPort(qpid::broker::Broker::TCP_TRANSPORT)); - } - - uint16_t getPort() { return broker->getPort(qpid::broker::Broker::TCP_TRANSPORT); } -}; - -/** Connection that opens in its constructor */ -struct LocalConnection : public qpid::client::Connection { - LocalConnection(uint16_t port) { open("localhost", port); } - LocalConnection(const qpid::client::ConnectionSettings& s) { open(s); } - ~LocalConnection() { close(); } -}; - -/** A local client connection via a socket proxy. */ -struct ProxyConnection : public qpid::client::Connection { - SocketProxy proxy; - ProxyConnection(int brokerPort) : proxy(brokerPort) { - open("localhost", proxy.getPort()); - } - ProxyConnection(const qpid::client::ConnectionSettings& s) : proxy(s.port) { - qpid::client::ConnectionSettings proxySettings(s); - proxySettings.port = proxy.getPort(); - open(proxySettings); - } - ~ProxyConnection() { close(); } -}; - -/** Convenience class to create and open a connection and session - * and some related useful objects. - */ -template <class ConnectionType=LocalConnection, class SessionType=qpid::client::Session> -struct ClientT { - ConnectionType connection; - SessionType session; - qpid::client::SubscriptionManager subs; - qpid::client::LocalQueue lq; - std::string name; - - ClientT(uint16_t port, const std::string& name_=std::string(), int timeout=0) - : connection(port), session(connection.newSession(name_,timeout)), subs(session), name(name_) {} - ClientT(const qpid::client::ConnectionSettings& settings, const std::string& name_=std::string(), int timeout=0) - : connection(settings), session(connection.newSession(name_, timeout)), subs(session), name(name_) {} - - ~ClientT() { close(); } - void close() { session.close(); connection.close(); } -}; - -typedef ClientT<> Client; - -/** - * A BrokerFixture and ready-connected BrokerFixture::Client all in one. - */ -template <class ConnectionType, class SessionType=qpid::client::Session> -struct SessionFixtureT : BrokerFixture, ClientT<ConnectionType,SessionType> { - - SessionFixtureT(Broker::Options opts=Broker::Options()) : - BrokerFixture(opts), - ClientT<ConnectionType,SessionType>(broker->getPort(qpid::broker::Broker::TCP_TRANSPORT)) - {} - -}; - -typedef SessionFixtureT<LocalConnection> SessionFixture; -typedef SessionFixtureT<ProxyConnection> ProxySessionFixture; - -}} // namespace qpid::tests - -#endif /*!TESTS_BROKERFIXTURE_H*/ diff --git a/cpp/src/tests/BrokerMgmtAgent.cpp b/cpp/src/tests/BrokerMgmtAgent.cpp deleted file mode 100644 index d0c6668b72..0000000000 --- a/cpp/src/tests/BrokerMgmtAgent.cpp +++ /dev/null @@ -1,792 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "unit_test.h" -#include "MessagingFixture.h" -#include "qpid/management/Buffer.h" -#include "qpid/messaging/Message.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" - -#include "qmf/org/apache/qpid/broker/mgmt/test/TestObject.h" - -#include <iomanip> - - -using qpid::management::Mutex; -using qpid::management::Manageable; -using qpid::management::Buffer; -using namespace qpid::messaging; -using namespace qpid::types; - - - -namespace qpid { - namespace tests { - - namespace _qmf = qmf::org::apache::qpid::broker::mgmt::test; - namespace { - - typedef boost::shared_ptr<_qmf::TestObject> TestObjectPtr; - typedef std::vector<TestObjectPtr> TestObjectVector; - - // Instantiates a broker and its internal management agent. Provides - // factories for constructing Receivers for object indication messages. - // - class AgentFixture - { - MessagingFixture *mFix; - - public: - AgentFixture( unsigned int pubInterval=10, - bool qmfV2=false, - qpid::broker::Broker::Options opts = qpid::broker::Broker::Options()) - { - opts.enableMgmt=true; - opts.qmf2Support=qmfV2; - opts.mgmtPubInterval=pubInterval; - mFix = new MessagingFixture(opts, true); - - _qmf::TestObject::registerSelf(getBrokerAgent()); - }; - ~AgentFixture() - { - delete mFix; - }; - ::qpid::management::ManagementAgent *getBrokerAgent() { return mFix->broker->getManagementAgent(); } - Receiver createV1DataIndRcvr( const std::string package, const std::string klass ) - { - return mFix->session.createReceiver(std::string("kqueue; {create: always, delete: always, " - "node: {type: queue, " - "x-bindings: [{exchange: qpid.management, " - "key: 'console.obj.1.0.") - + package + std::string(".") + klass - + std::string("'}]}}")); - }; - Receiver createV2DataIndRcvr( const std::string package, const std::string klass ) - { - std::string p(package); - std::replace(p.begin(), p.end(), '.', '_'); - std::string k(klass); - std::replace(k.begin(), k.end(), '.', '_'); - - return mFix->session.createReceiver(std::string("kqueue; {create: always, delete: always, " - "node: {type: queue, " - "x-bindings: [{exchange: qmf.default.topic, " - "key: 'agent.ind.data.") - + p + std::string(".") + k - + std::string("'}]}}")); - }; - }; - - - // A "management object" that supports the TestObject - // - class TestManageable : public qpid::management::Manageable - { - management::ManagementObject* mgmtObj; - const std::string key; - public: - TestManageable(management::ManagementAgent *agent, std::string _key) - : key(_key) - { - _qmf::TestObject *tmp = new _qmf::TestObject(agent, this); - - // seed it with some default values... - tmp->set_string1(key); - tmp->set_bool1(true); - qpid::types::Variant::Map vMap; - vMap["one"] = qpid::types::Variant(1); - vMap["two"] = qpid::types::Variant("two"); - vMap["three"] = qpid::types::Variant("whatever"); - tmp->set_map1(vMap); - - mgmtObj = tmp; - }; - ~TestManageable() { mgmtObj = 0; /* deleted by agent on shutdown */ }; - management::ManagementObject* GetManagementObject() const { return mgmtObj; }; - static void validateTestObjectProperties(_qmf::TestObject& to) - { - // verify the default values are as expected. We don't check 'string1', - // as it is the object key, and is unique for each object (no default value). - BOOST_CHECK(to.get_bool1() == true); - BOOST_CHECK(to.get_map1().size() == 3); - qpid::types::Variant::Map mappy = to.get_map1(); - BOOST_CHECK(1 == (unsigned int)mappy["one"]); - BOOST_CHECK(mappy["two"].asString() == std::string("two")); - BOOST_CHECK(mappy["three"].asString() == std::string("whatever")); - }; - }; - - - // decode a V1 Content Indication message - // - void decodeV1ObjectUpdates(const Message& inMsg, TestObjectVector& objs, const size_t objLen) - { - const size_t MAX_BUFFER_SIZE=65536; - char tmp[MAX_BUFFER_SIZE]; - - objs.clear(); - - BOOST_CHECK(inMsg.getContent().size() <= MAX_BUFFER_SIZE); - - ::memcpy(tmp, inMsg.getContent().data(), inMsg.getContent().size()); - Buffer buf(tmp, inMsg.getContent().size()); - - while (buf.available() > 8) { // 8 == qmf v1 header size - BOOST_CHECK_EQUAL(buf.getOctet(), 'A'); - BOOST_CHECK_EQUAL(buf.getOctet(), 'M'); - BOOST_CHECK_EQUAL(buf.getOctet(), '2'); - BOOST_CHECK_EQUAL(buf.getOctet(), 'c'); // opcode == content indication - // @@todo: kag: how do we skip 'i' entries??? - buf.getLong(); // ignore sequence - - std::string str1; // decode content body as string - buf.getRawData(str1, objLen); - - TestObjectPtr fake(new _qmf::TestObject(0,0)); - fake->readProperties( str1 ); - objs.push_back(fake); - } - } - - - // decode a V2 Content Indication message - // - void decodeV2ObjectUpdates(const qpid::messaging::Message& inMsg, TestObjectVector& objs) - { - objs.clear(); - - BOOST_CHECK_EQUAL(inMsg.getContentType(), std::string("amqp/list")); - - const ::qpid::types::Variant::Map& m = inMsg.getProperties(); - Variant::Map::const_iterator iter = m.find(std::string("qmf.opcode")); - BOOST_CHECK(iter != m.end()); - BOOST_CHECK_EQUAL(iter->second.asString(), std::string("_data_indication")); - - Variant::List vList; - ::qpid::amqp_0_10::ListCodec::decode(inMsg.getContent(), vList); - - for (Variant::List::iterator lIter = vList.begin(); lIter != vList.end(); lIter++) { - TestObjectPtr fake(new _qmf::TestObject(0,0)); - fake->readTimestamps(lIter->asMap()); - fake->mapDecodeValues((lIter->asMap())["_values"].asMap()); - objs.push_back(fake); - } - } - } - - QPID_AUTO_TEST_SUITE(BrokerMgmtAgent) - - // verify that an object that is added to the broker's management database is - // published correctly. Furthermore, verify that it is published once after - // it has been deleted. - // - QPID_AUTO_TEST_CASE(v1ObjPublish) - { - AgentFixture* fix = new AgentFixture(3); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - // create a manageable test object - TestManageable *tm = new TestManageable(agent, std::string("obj1")); - uint32_t objLen = tm->GetManagementObject()->writePropertiesSize(); - - Receiver r1 = fix->createV1DataIndRcvr("org.apache.qpid.broker.mgmt.test", "#"); - - agent->addObject(tm->GetManagementObject(), 1); - - // wait for the object to be published - Message m1; - BOOST_CHECK(r1.fetch(m1, Duration::SECOND * 6)); - - TestObjectVector objs; - decodeV1ObjectUpdates(m1, objs, objLen); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - BOOST_CHECK(0 == mappy["_delete_ts"].asUint64()); // not deleted - } - - // destroy the object - - tm->GetManagementObject()->resourceDestroy(); - - // wait for the deleted object to be published - - bool isDeleted = false; - while (!isDeleted && r1.fetch(m1, Duration::SECOND * 6)) { - - decodeV1ObjectUpdates(m1, objs, objLen); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) - isDeleted = true; - } - } - - BOOST_CHECK(isDeleted); - - r1.close(); - delete fix; - delete tm; - } - - // Repeat the previous test, but with V2-based object support - // - QPID_AUTO_TEST_CASE(v2ObjPublish) - { - AgentFixture* fix = new AgentFixture(3, true); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - TestManageable *tm = new TestManageable(agent, std::string("obj2")); - - Receiver r1 = fix->createV2DataIndRcvr(tm->GetManagementObject()->getPackageName(), "#"); - - agent->addObject(tm->GetManagementObject(), "testobj-1"); - - // wait for the object to be published - Message m1; - BOOST_CHECK(r1.fetch(m1, Duration::SECOND * 6)); - - TestObjectVector objs; - decodeV2ObjectUpdates(m1, objs); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - BOOST_CHECK(0 == mappy["_delete_ts"].asUint64()); - } - - // destroy the object - - tm->GetManagementObject()->resourceDestroy(); - - // wait for the deleted object to be published - - bool isDeleted = false; - while (!isDeleted && r1.fetch(m1, Duration::SECOND * 6)) { - - decodeV2ObjectUpdates(m1, objs); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) - isDeleted = true; - } - } - - BOOST_CHECK(isDeleted); - - r1.close(); - delete fix; - delete tm; - } - - - // verify that a deleted object is exported correctly using the - // exportDeletedObjects() method. V1 testcase. - // - QPID_AUTO_TEST_CASE(v1ExportDelObj) - { - AgentFixture* fix = new AgentFixture(3); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - // create a manageable test object - TestManageable *tm = new TestManageable(agent, std::string("myObj")); - uint32_t objLen = tm->GetManagementObject()->writePropertiesSize(); - - Receiver r1 = fix->createV1DataIndRcvr("org.apache.qpid.broker.mgmt.test", "#"); - - agent->addObject(tm->GetManagementObject(), 1); - - // wait for the object to be published - Message m1; - BOOST_CHECK(r1.fetch(m1, Duration::SECOND * 6)); - - TestObjectVector objs; - decodeV1ObjectUpdates(m1, objs, objLen); - BOOST_CHECK(objs.size() > 0); - - // destroy the object, then immediately export (before the next poll cycle) - - ::qpid::management::ManagementAgent::DeletedObjectList delObjs; - tm->GetManagementObject()->resourceDestroy(); - agent->exportDeletedObjects( delObjs ); - BOOST_CHECK(delObjs.size() == 1); - - // wait for the deleted object to be published - - bool isDeleted = false; - while (!isDeleted && r1.fetch(m1, Duration::SECOND * 6)) { - - decodeV1ObjectUpdates(m1, objs, objLen); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) - isDeleted = true; - } - } - - BOOST_CHECK(isDeleted); - - // verify there are no deleted objects to export now. - - agent->exportDeletedObjects( delObjs ); - BOOST_CHECK(delObjs.size() == 0); - - r1.close(); - delete fix; - delete tm; - } - - - // verify that a deleted object is imported correctly using the - // importDeletedObjects() method. V1 testcase. - // - QPID_AUTO_TEST_CASE(v1ImportDelObj) - { - AgentFixture* fix = new AgentFixture(3); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - // create a manageable test object - TestManageable *tm = new TestManageable(agent, std::string("anObj")); - uint32_t objLen = tm->GetManagementObject()->writePropertiesSize(); - - Receiver r1 = fix->createV1DataIndRcvr("org.apache.qpid.broker.mgmt.test", "#"); - - agent->addObject(tm->GetManagementObject(), 1); - - // wait for the object to be published - Message m1; - BOOST_CHECK(r1.fetch(m1, Duration::SECOND * 6)); - - TestObjectVector objs; - decodeV1ObjectUpdates(m1, objs, objLen); - BOOST_CHECK(objs.size() > 0); - - // destroy the object, then immediately export (before the next poll cycle) - - ::qpid::management::ManagementAgent::DeletedObjectList delObjs; - tm->GetManagementObject()->resourceDestroy(); - agent->exportDeletedObjects( delObjs ); - BOOST_CHECK(delObjs.size() == 1); - - // destroy the broker, and reinistantiate a new one without populating it - // with a TestObject. - - r1.close(); - delete fix; - delete tm; // should no longer be necessary - - fix = new AgentFixture(3); - r1 = fix->createV1DataIndRcvr("org.apache.qpid.broker.mgmt.test", "#"); - agent = fix->getBrokerAgent(); - agent->importDeletedObjects( delObjs ); - - // wait for the deleted object to be published - - bool isDeleted = false; - while (!isDeleted && r1.fetch(m1, Duration::SECOND * 6)) { - - decodeV1ObjectUpdates(m1, objs, objLen); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) - isDeleted = true; - } - } - - BOOST_CHECK(isDeleted); - - // verify there are no deleted objects to export now. - - agent->exportDeletedObjects( delObjs ); - BOOST_CHECK(delObjs.size() == 0); - - r1.close(); - delete fix; - } - - - // verify that an object that is added and deleted prior to the - // first poll cycle is accounted for by the export - // - QPID_AUTO_TEST_CASE(v1ExportFastDelObj) - { - AgentFixture* fix = new AgentFixture(3); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - // create a manageable test object - TestManageable *tm = new TestManageable(agent, std::string("objectifyMe")); - - // add, then immediately delete and export the object... - - ::qpid::management::ManagementAgent::DeletedObjectList delObjs; - agent->addObject(tm->GetManagementObject(), 999); - tm->GetManagementObject()->resourceDestroy(); - agent->exportDeletedObjects( delObjs ); - BOOST_CHECK(delObjs.size() == 1); - - delete fix; - delete tm; - } - - - // Verify that we can export and import multiple deleted objects correctly. - // - QPID_AUTO_TEST_CASE(v1ImportMultiDelObj) - { - AgentFixture* fix = new AgentFixture(3); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - Receiver r1 = fix->createV1DataIndRcvr("org.apache.qpid.broker.mgmt.test", "#"); - - // populate the agent with multiple test objects - const size_t objCount = 50; - std::vector<TestManageable *> tmv; - uint32_t objLen; - - for (size_t i = 0; i < objCount; i++) { - std::stringstream key; - key << "testobj-" << std::setfill('x') << std::setw(4) << i; - // (no, seriously, I didn't just do that.) - // Note well: we have to keep the key string length EXACTLY THE SAME - // FOR ALL OBJECTS, so objLen will be the same. Otherwise the - // decodeV1ObjectUpdates() will fail (v1 lacks explict encoded length). - TestManageable *tm = new TestManageable(agent, key.str()); - objLen = tm->GetManagementObject()->writePropertiesSize(); - agent->addObject(tm->GetManagementObject(), i + 1); - tmv.push_back(tm); - } - - // wait for the objects to be published - Message m1; - uint32_t msgCount = 0; - while(r1.fetch(m1, Duration::SECOND * 6)) { - TestObjectVector objs; - decodeV1ObjectUpdates(m1, objs, objLen); - msgCount += objs.size(); - } - - BOOST_CHECK_EQUAL(msgCount, objCount); - - // destroy some of the objects, then immediately export (before the next poll cycle) - - uint32_t delCount = 0; - for (size_t i = 0; i < objCount; i += 2) { - tmv[i]->GetManagementObject()->resourceDestroy(); - delCount++; - } - - ::qpid::management::ManagementAgent::DeletedObjectList delObjs; - agent->exportDeletedObjects( delObjs ); - BOOST_CHECK_EQUAL(delObjs.size(), delCount); - - // destroy the broker, and reinistantiate a new one without populating it - // with TestObjects. - - r1.close(); - delete fix; - while (tmv.size()) { - delete tmv.back(); - tmv.pop_back(); - } - - fix = new AgentFixture(3); - r1 = fix->createV1DataIndRcvr("org.apache.qpid.broker.mgmt.test", "#"); - agent = fix->getBrokerAgent(); - agent->importDeletedObjects( delObjs ); - - // wait for the deleted object to be published, verify the count - - uint32_t countDels = 0; - while (r1.fetch(m1, Duration::SECOND * 6)) { - TestObjectVector objs; - decodeV1ObjectUpdates(m1, objs, objLen); - BOOST_CHECK(objs.size() > 0); - - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) - countDels++; - } - } - - // make sure we get the correct # of deleted objects - BOOST_CHECK_EQUAL(countDels, delCount); - - // verify there are no deleted objects to export now. - - agent->exportDeletedObjects( delObjs ); - BOOST_CHECK(delObjs.size() == 0); - - r1.close(); - delete fix; - } - - // Verify that we can export and import multiple deleted objects correctly. - // QMF V2 variant - QPID_AUTO_TEST_CASE(v2ImportMultiDelObj) - { - AgentFixture* fix = new AgentFixture(3, true); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - Receiver r1 = fix->createV2DataIndRcvr("org.apache.qpid.broker.mgmt.test", "#"); - - // populate the agent with multiple test objects - const size_t objCount = 50; - std::vector<TestManageable *> tmv; - uint32_t objLen; - - for (size_t i = 0; i < objCount; i++) { - std::stringstream key; - key << "testobj-" << i; - TestManageable *tm = new TestManageable(agent, key.str()); - objLen = tm->GetManagementObject()->writePropertiesSize(); - agent->addObject(tm->GetManagementObject(), key.str()); - tmv.push_back(tm); - } - - // wait for the objects to be published - Message m1; - uint32_t msgCount = 0; - while(r1.fetch(m1, Duration::SECOND * 6)) { - TestObjectVector objs; - decodeV2ObjectUpdates(m1, objs); - msgCount += objs.size(); - } - - BOOST_CHECK_EQUAL(msgCount, objCount); - - // destroy some of the objects, then immediately export (before the next poll cycle) - - uint32_t delCount = 0; - for (size_t i = 0; i < objCount; i += 2) { - tmv[i]->GetManagementObject()->resourceDestroy(); - delCount++; - } - - ::qpid::management::ManagementAgent::DeletedObjectList delObjs; - agent->exportDeletedObjects( delObjs ); - BOOST_CHECK_EQUAL(delObjs.size(), delCount); - - // destroy the broker, and reinistantiate a new one without populating it - // with TestObjects. - - r1.close(); - delete fix; - while (tmv.size()) { - delete tmv.back(); - tmv.pop_back(); - } - - fix = new AgentFixture(3, true); - r1 = fix->createV2DataIndRcvr("org.apache.qpid.broker.mgmt.test", "#"); - agent = fix->getBrokerAgent(); - agent->importDeletedObjects( delObjs ); - - // wait for the deleted object to be published, verify the count - - uint32_t countDels = 0; - while (r1.fetch(m1, Duration::SECOND * 6)) { - TestObjectVector objs; - decodeV2ObjectUpdates(m1, objs); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) - countDels++; - } - } - - // make sure we get the correct # of deleted objects - BOOST_CHECK_EQUAL(countDels, delCount); - - // verify there are no deleted objects to export now. - - agent->exportDeletedObjects( delObjs ); - BOOST_CHECK(delObjs.size() == 0); - - r1.close(); - delete fix; - } - - // See QPID-2997 - QPID_AUTO_TEST_CASE(v2RapidRestoreObj) - { - AgentFixture* fix = new AgentFixture(3, true); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - // two objects, same ObjID - TestManageable *tm1 = new TestManageable(agent, std::string("obj2")); - TestManageable *tm2 = new TestManageable(agent, std::string("obj2")); - - Receiver r1 = fix->createV2DataIndRcvr(tm1->GetManagementObject()->getPackageName(), "#"); - - // add, then immediately delete and re-add a copy of the object - agent->addObject(tm1->GetManagementObject(), "testobj-1"); - tm1->GetManagementObject()->resourceDestroy(); - agent->addObject(tm2->GetManagementObject(), "testobj-1"); - - // expect: a delete notification, then an update notification - TestObjectVector objs; - bool isDeleted = false; - bool isAdvertised = false; - size_t count = 0; - Message m1; - while (r1.fetch(m1, Duration::SECOND * 6)) { - - decodeV2ObjectUpdates(m1, objs); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - count++; - TestManageable::validateTestObjectProperties(**oIter); - - qpid::types::Variant::Map mappy; - (*oIter)->writeTimestamps(mappy); - if (mappy["_delete_ts"].asUint64() != 0) { - isDeleted = true; - BOOST_CHECK(isAdvertised == false); // delete must be first - } else { - isAdvertised = true; - BOOST_CHECK(isDeleted == true); // delete must be first - } - } - } - - BOOST_CHECK(isDeleted); - BOOST_CHECK(isAdvertised); - BOOST_CHECK(count == 2); - - r1.close(); - delete fix; - delete tm1; - delete tm2; - } - - // See QPID-2997 - QPID_AUTO_TEST_CASE(v2DuplicateErrorObj) - { - AgentFixture* fix = new AgentFixture(3, true); - management::ManagementAgent* agent; - agent = fix->getBrokerAgent(); - - // turn off the expected error log message - qpid::log::Options logOpts; - logOpts.selectors.clear(); - logOpts.selectors.push_back("critical+"); - qpid::log::Logger::instance().configure(logOpts); - - // two objects, same ObjID - TestManageable *tm1 = new TestManageable(agent, std::string("obj2")); - TestManageable *tm2 = new TestManageable(agent, std::string("obj2")); - // Keep a pointer to the ManagementObject. This test simulates a user-caused error - // case (duplicate objects) where the broker has no choice but to leak a management - // object (safest assumption). To prevent valgrind from flagging this leak, we - // manually clean up the object at the end of the test. - management::ManagementObject *save = tm2->GetManagementObject(); - - Receiver r1 = fix->createV2DataIndRcvr(tm1->GetManagementObject()->getPackageName(), "#"); - - // add, then immediately delete and re-add a copy of the object - agent->addObject(tm1->GetManagementObject(), "testobj-1"); - agent->addObject(tm2->GetManagementObject(), "testobj-1"); - - TestObjectVector objs; - size_t count = 0; - Message m1; - while (r1.fetch(m1, Duration::SECOND * 6)) { - - decodeV2ObjectUpdates(m1, objs); - BOOST_CHECK(objs.size() > 0); - - for (TestObjectVector::iterator oIter = objs.begin(); oIter != objs.end(); oIter++) { - count++; - TestManageable::validateTestObjectProperties(**oIter); - } - } - - BOOST_CHECK(count == 1); // only one should be accepted. - - r1.close(); - delete fix; - delete tm1; - delete tm2; - delete save; - } - - QPID_AUTO_TEST_SUITE_END() - } -} - - diff --git a/cpp/src/tests/BrokerMgmtAgent.xml b/cpp/src/tests/BrokerMgmtAgent.xml deleted file mode 100644 index 202b8debf3..0000000000 --- a/cpp/src/tests/BrokerMgmtAgent.xml +++ /dev/null @@ -1,38 +0,0 @@ -<schema package="org.apache.qpid.broker.mgmt.test"> - -<!-- - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. ---> - - <!-- - =============================================================== - TestObject - =============================================================== - --> - <class name="TestObject"> - - A test object defined for the BrokerMgmtAgent unit test. - - <property name="string1" type="lstr" access="RW" index="y"/> - <property name="bool1" type="bool" access="RW"/> - <property name="map1" type="map" access="RW"/> - - </class> - -</schema> - diff --git a/cpp/src/tests/CMakeLists.txt b/cpp/src/tests/CMakeLists.txt deleted file mode 100644 index 405718f12b..0000000000 --- a/cpp/src/tests/CMakeLists.txt +++ /dev/null @@ -1,356 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Enable dashboard reporting. -include (CTest) - -# Make sure that everything get built before the tests -# Need to create a var with all the necessary top level targets - -add_definitions(-DBOOST_TEST_DYN_LINK) -include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) - -include (FindPythonInterp) - -# Create the environment scripts for tests -set (abs_srcdir ${CMAKE_CURRENT_SOURCE_DIR}) -set (abs_builddir ${CMAKE_CURRENT_BINARY_DIR}) -set (abs_top_srcdir ${CMAKE_SOURCE_DIR}) -set (abs_top_builddir ${CMAKE_BINARY_DIR}) -set (builddir_lib_suffix "") -configure_file (${CMAKE_CURRENT_SOURCE_DIR}/test_env.sh.in - ${CMAKE_CURRENT_BINARY_DIR}/test_env.sh) - - -# If valgrind is selected in the configuration step, set up the path to it -# for CTest. -if (ENABLE_VALGRIND) - set (MEMORYCHECK_COMMAND ${VALGRIND}) - set (MEMORYCHECK_COMMAND_OPTIONS "--gen-suppressions=all ---leak-check=full ---demangle=yes ---suppressions=${CMAKE_CURRENT_SOURCE_DIR}/.valgrind.supp ---num-callers=25 ---log-file=ctest_valgrind.vglog") -endif (ENABLE_VALGRIND) - -# Using the Boost DLLs triggers warning 4275 on Visual Studio -# (non dll-interface class used as base for dll-interface class). -# This is ok, so suppress the warning. -# Also, boost lengthy names trigger warning 4503, decorated name length exceeded -# and using getenv() triggers insecure CRT warnings which we can silence in the -# test environment. -if (MSVC) - add_definitions( /wd4275 /wd4503 /D_CRT_SECURE_NO_WARNINGS) -endif (MSVC) - -# Like this to work with cmake 2.4 on Unix -set (qpid_test_boost_libs - ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${Boost_SYSTEM_LIBRARY}) - -# Macro to make it easier to remember where the tests are built -macro(remember_location testname) - set (${testname}_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${testname}${CMAKE_EXECUTABLE_SUFFIX}) -endmacro(remember_location) - -# Windows uses some process-startup calls to ensure that errors, etc. don't -# result in error boxes being thrown up. Since it's expected that most test -# runs will be in scripts, the default is to force these outputs to stderr -# instead of windows. If you want to remove this code, build without the -# QPID_WINDOWS_DEFAULT_TEST_OUTPUTS ON. -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - option(QPID_WINDOWS_DEFAULT_TEST_OUTPUTS "Use default error-handling on Windows tests" OFF) - if (NOT QPID_WINDOWS_DEFAULT_TEST_OUTPUTS) - set(platform_test_additions windows/DisableWin32ErrorWindows.cpp) - endif (NOT QPID_WINDOWS_DEFAULT_TEST_OUTPUTS) -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -# -# Unit test program -# -# Unit tests are built as a single program to reduce valgrind overhead -# when running the tests. If you want to build a subset of the tests run -# ccmake and set unit_tests_to_build to the set you want to build. - -set(unit_tests_to_build - exception_test - RefCounted - SessionState - logging - AsyncCompletion - Url - Uuid - Shlib - FieldValue - FieldTable - Array - QueueOptionsTest - InlineAllocator - InlineVector - ClientSessionTest - MessagingSessionTests - SequenceSet - StringUtils - RangeSet - AtomicValue - QueueTest - AccumulatedAckTest - DtxWorkRecordTest - DeliveryRecordTest - ExchangeTest - HeadersExchangeTest - MessageTest - QueueRegistryTest - QueuePolicyTest - QueueFlowLimitTest - FramingTest - HeaderTest - SequenceNumberTest - TimerTest - TopicExchangeTest - TxBufferTest - TxPublishTest - MessageBuilderTest - ManagementTest - MessageReplayTracker - ConsoleTest - QueueEvents - ProxyTest - RetryList - RateFlowcontrolTest - FrameDecoder - ReplicationTest - ClientMessageTest - PollableCondition - Variant - ClientMessage - ${xml_tests} - CACHE STRING "Which unit tests to build" - ) - -mark_as_advanced(unit_tests_to_build) - -# Disabled till we move to amqp_0_10 codec. -# amqp_0_10/serialize.cpp allSegmentTypes.h \ -# amqp_0_10/ProxyTemplate.cpp \ -# amqp_0_10/apply.cpp \ -# amqp_0_10/Map.cpp \ -# amqp_0_10/handlers.cpp - -add_executable (unit_test unit_test - ${unit_tests_to_build} ${platform_test_additions}) -target_link_libraries (unit_test - ${qpid_test_boost_libs} - qpidmessaging qpidbroker qmfconsole) -remember_location(unit_test) - -add_library (shlibtest MODULE shlibtest.cpp) - -if (BUILD_CLUSTER) - include (cluster.cmake) -endif (BUILD_CLUSTER) - -# FIXME aconway 2009-11-30: enable SSL -#if SSL -#include ssl.mk -#endif - -# -# Other test programs -# -add_executable (qpid-perftest qpid-perftest.cpp ${platform_test_additions}) -target_link_libraries (qpid-perftest qpidclient) -#qpid_perftest_SOURCES=qpid-perftest.cpp test_tools.h TestOptions.h ConnectionOptions.h -remember_location(qpid-perftest) - -add_executable (qpid-txtest qpid-txtest.cpp ${platform_test_additions}) -target_link_libraries (qpid-txtest qpidclient) -#qpid_txtest_SOURCES=qpid-txtest.cpp TestOptions.h ConnectionOptions.h -remember_location(qpid-txtest) - -add_executable (qpid-latency-test qpid-latency-test.cpp ${platform_test_additions}) -target_link_libraries (qpid-latency-test qpidclient) -#qpid_latencytest_SOURCES=qpid-latency-test.cpp TestOptions.h ConnectionOptions.h -remember_location(qpid-latency-test) - -add_executable (echotest echotest.cpp ${platform_test_additions}) -target_link_libraries (echotest qpidclient) -#echotest_SOURCES=echotest.cpp TestOptions.h ConnectionOptions.h -remember_location(echotest) - -add_executable (qpid-client-test qpid-client-test.cpp ${platform_test_additions}) -target_link_libraries (qpid-client-test qpidclient) -#qpid_client_test_SOURCES=qpid-client-test.cpp TestOptions.h ConnectionOptions.h -remember_location(qpid-client-test) - -add_executable (qpid-topic-listener qpid-topic-listener.cpp ${platform_test_additions}) -target_link_libraries (qpid-topic-listener qpidclient) -#qpid_topic_listener_SOURCES=qpid-topic-listener.cpp TestOptions.h ConnectionOptions.h -remember_location(qpid-topic-listener) - -add_executable (qpid-topic-publisher qpid-topic-publisher.cpp ${platform_test_additions}) -target_link_libraries (qpid-topic-publisher qpidclient) -#qpid_topic_publisher_SOURCES=qpid-topic-publisher.cpp TestOptions.h ConnectionOptions.h -remember_location(qpid-topic-publisher) - -add_executable (publish publish.cpp ${platform_test_additions}) -target_link_libraries (publish qpidclient) -#publish_SOURCES=publish.cpp TestOptions.h ConnectionOptions.h -remember_location(publish) - -add_executable (consume consume.cpp ${platform_test_additions}) -target_link_libraries (consume qpidclient) -#consume_SOURCES=consume.cpp TestOptions.h ConnectionOptions.h -remember_location(consume) - -add_executable (header_test header_test.cpp ${platform_test_additions}) -target_link_libraries (header_test qpidclient) -#header_test_SOURCES=header_test.cpp TestOptions.h ConnectionOptions.h -remember_location(header_test) - -add_executable (declare_queues declare_queues.cpp ${platform_test_additions}) -target_link_libraries (declare_queues qpidclient) -remember_location(declare_queues) - -add_executable (replaying_sender replaying_sender.cpp ${platform_test_additions}) -target_link_libraries (replaying_sender qpidclient) -remember_location(replaying_sender) - -add_executable (resuming_receiver resuming_receiver.cpp ${platform_test_additions}) -target_link_libraries (resuming_receiver qpidclient) -remember_location(resuming_receiver) - -add_executable (txshift txshift.cpp ${platform_test_additions}) -target_link_libraries (txshift qpidclient) -#txshift_SOURCES=txshift.cpp TestOptions.h ConnectionOptions.h -remember_location(txshift) - -add_executable (txjob txjob.cpp ${platform_test_additions}) -target_link_libraries (txjob qpidclient) -#txjob_SOURCES=txjob.cpp TestOptions.h ConnectionOptions.h -remember_location(txjob) - -add_executable (receiver receiver.cpp ${platform_test_additions}) -target_link_libraries (receiver qpidclient) -#receiver_SOURCES=receiver.cpp TestOptions.h ConnectionOptions.h -remember_location(receiver) - -add_executable (sender sender.cpp Statistics.cpp ${platform_test_additions}) -target_link_libraries (sender qpidmessaging) -#sender_SOURCES=sender.cpp TestOptions.h ConnectionOptions.h -remember_location(sender) - -add_executable (qpid-receive qpid-receive.cpp Statistics.cpp ${platform_test_additions}) -target_link_libraries (qpid-receive qpidmessaging) -remember_location(qpid-receive) - -add_executable (qpid-send qpid-send.cpp Statistics.cpp ${platform_test_additions}) -target_link_libraries (qpid-send qpidmessaging) -remember_location(qpid-send) - -# qpid-perftest and qpid-latency-test are generally useful so install them -install (TARGETS qpid-perftest qpid-latency-test RUNTIME - DESTINATION ${QPID_INSTALL_BINDIR}) - -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - set (ENV{OUTDIR} ${EXECUTABLE_OUTPUT_PATH}) - set (test_script_suffix ".ps1") - set (shell "powershell") -endif (CMAKE_SYSTEM_NAME STREQUAL Windows) - -set(test_wrap ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_test${test_script_suffix}) - -add_test (unit_test ${test_wrap} ${unit_test_LOCATION}) -add_test (start_broker ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/start_broker${test_script_suffix}) -add_test (qpid-client-test ${test_wrap} ${qpid-client_test_LOCATION}) -add_test (quick_perftest ${test_wrap} ${qpid-perftest_LOCATION} --summary --count 100) -add_test (quick_topictest ${test_wrap} ${CMAKE_CURRENT_SOURCE_DIR}/quick_topictest${test_script_suffix}) -add_test (quick_txtest ${test_wrap} ${qpid-txtest_LOCATION} --queues 4 --tx-count 10 --quiet) -if (PYTHON_EXECUTABLE) - add_test (run_header_test ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_header_test${test_script_suffix}) - add_test (python_tests ${test_wrap} ${CMAKE_CURRENT_SOURCE_DIR}/python_tests${test_script_suffix}) -endif (PYTHON_EXECUTABLE) -add_test (stop_broker ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/stop_broker${test_script_suffix}) -if (PYTHON_EXECUTABLE) - add_test (federation_tests ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_federation_tests${test_script_suffix}) -if (BUILD_ACL) - add_test (acl_tests ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_acl_tests${test_script_suffix}) -endif (BUILD_ACL) -add_test (dynamic_log_level_test ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_log_level_test${test_script_suffix}) -if (BUILD_MSSQL) - add_test (store_tests ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_store_tests${test_script_suffix} MSSQL) -endif (BUILD_MSSQL) -if (BUILD_MSCLFS) - add_test (store_tests ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_store_tests${test_script_suffix} MSSQL-CLFS) -endif (BUILD_MSCLFS) -endif (PYTHON_EXECUTABLE) - -add_library(test_store MODULE test_store.cpp) -target_link_libraries (test_store qpidbroker qpidcommon) -set_target_properties (test_store PROPERTIES PREFIX "") - -#EXTRA_DIST += \ -# run_test vg_check \ -# run-unit-tests start_broker python_tests stop_broker \ -# quick_topictest \ -# quick_perftest \ -# quick_txtest \ -# topictest \ -# run_header_test \ -# header_test.py \ -# ssl_test \ -# config.null \ -# ais_check \ -# run_federation_tests \ -# run_acl_tests \ -# .valgrind.supp \ -# MessageUtils.h \ -# TestMessageStore.h \ -# TxMocks.h \ -# start_cluster stop_cluster restart_cluster - -add_library (dlclose_noop MODULE dlclose_noop.c) -#libdlclose_noop_la_LDFLAGS = -module -rpath $(abs_builddir) - -#CLEANFILES+=valgrind.out *.log *.vglog* dummy_test $(unit_wrappers) -# -## FIXME aconway 2008-05-23: Disabled interop_runner because it uses -## the obsolete Channel class. Convert to Session and re-enable. -## -## check_PROGRAMS += interop_runner -# -## interop_runner_SOURCES = \ -## interop_runner.cpp \ -## SimpleTestCaseBase.cpp \ -## BasicP2PTest.cpp \ -## BasicPubSubTest.cpp \ -## SimpleTestCaseBase.h \ -## BasicP2PTest.h \ -## BasicPubSubTest.h \ -## TestCase.h \ -## TestOptions.h ConnectionOptions.h -## interop_runner_LDADD = $(lib_client) $(lib_common) $(extra_libs) -# -# -## Longer running stability tests, not run by default check: target. -## Not run under valgrind, too slow -#LONG_TESTS=fanout_perftest shared_perftest multiq_perftest topic_perftest run_failover_soak -#EXTRA_DIST+=$(LONG_TESTS) run_perftest -#check-long: -# $(MAKE) check TESTS="start_broker $(LONG_TESTS) stop_broker" VALGRIND= diff --git a/cpp/src/tests/ClientMessage.cpp b/cpp/src/tests/ClientMessage.cpp deleted file mode 100644 index 994c46552c..0000000000 --- a/cpp/src/tests/ClientMessage.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/messaging/Message.h" - -#include "unit_test.h" - -using namespace qpid::messaging; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ClientMessageSuite) - -QPID_AUTO_TEST_CASE(testCopyConstructor) -{ - Message m("my-data"); - m.setSubject("my-subject"); - m.getProperties()["a"] = "ABC"; - Message c(m); - BOOST_CHECK_EQUAL(m.getContent(), c.getContent()); - BOOST_CHECK_EQUAL(m.getSubject(), c.getSubject()); - BOOST_CHECK_EQUAL(m.getProperties()["a"], c.getProperties()["a"]); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ClientMessageTest.cpp b/cpp/src/tests/ClientMessageTest.cpp deleted file mode 100644 index f925f1c234..0000000000 --- a/cpp/src/tests/ClientMessageTest.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -/**@file Unit tests for the client::Message class. */ - -#include "unit_test.h" -#include "qpid/client/Message.h" - -using namespace qpid::client; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ClientMessageTestSuite) - -QPID_AUTO_TEST_CASE(MessageCopyAssign) { - // Verify that message has normal copy semantics. - Message m("foo"); - BOOST_CHECK_EQUAL("foo", m.getData()); - Message c(m); - BOOST_CHECK_EQUAL("foo", c.getData()); - Message a; - BOOST_CHECK_EQUAL("", a.getData()); - a = m; - BOOST_CHECK_EQUAL("foo", a.getData()); - a.setData("a"); - BOOST_CHECK_EQUAL("a", a.getData()); - c.setData("c"); - BOOST_CHECK_EQUAL("c", c.getData()); - BOOST_CHECK_EQUAL("foo", m.getData()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ClientSessionTest.cpp b/cpp/src/tests/ClientSessionTest.cpp deleted file mode 100644 index 939f8f2b88..0000000000 --- a/cpp/src/tests/ClientSessionTest.cpp +++ /dev/null @@ -1,677 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "unit_test.h" -#include "test_tools.h" -#include "BrokerFixture.h" -#include "qpid/client/QueueOptions.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Time.h" -#include "qpid/client/Session.h" -#include "qpid/client/Message.h" -#include "qpid/framing/reply_exceptions.h" - -#include <boost/optional.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/bind.hpp> -#include <boost/ptr_container/ptr_vector.hpp> - -#include <vector> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ClientSessionTest) - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid; -using qpid::sys::Monitor; -using qpid::sys::Thread; -using qpid::sys::TIME_SEC; -using qpid::broker::Broker; -using std::string; -using std::cout; -using std::endl; - - -struct DummyListener : public sys::Runnable, public MessageListener { - std::vector<Message> messages; - string name; - uint expected; - SubscriptionManager submgr; - - DummyListener(Session& session, const string& n, uint ex) : - name(n), expected(ex), submgr(session) {} - - void run() - { - submgr.subscribe(*this, name); - submgr.run(); - } - - void received(Message& msg) - { - messages.push_back(msg); - if (--expected == 0) { - submgr.stop(); - } - } -}; - -struct SimpleListener : public MessageListener -{ - Monitor lock; - std::vector<Message> messages; - - void received(Message& msg) - { - Monitor::ScopedLock l(lock); - messages.push_back(msg); - lock.notifyAll(); - } - - void waitFor(const uint n) - { - Monitor::ScopedLock l(lock); - while (messages.size() < n) { - lock.wait(); - } - } -}; - -struct ClientSessionFixture : public ProxySessionFixture -{ - ClientSessionFixture(Broker::Options opts = Broker::Options()) : ProxySessionFixture(opts) { - session.queueDeclare(arg::queue="my-queue"); - } -}; - -QPID_AUTO_TEST_CASE(testQueueQuery) { - ClientSessionFixture fix; - fix.session = fix.connection.newSession(); - fix.session.queueDeclare(arg::queue="q", arg::alternateExchange="amq.fanout", - arg::exclusive=true, arg::autoDelete=true); - QueueQueryResult result = fix.session.queueQuery("q"); - BOOST_CHECK_EQUAL(false, result.getDurable()); - BOOST_CHECK_EQUAL(true, result.getExclusive()); - BOOST_CHECK_EQUAL("amq.fanout", result.getAlternateExchange()); -} - -QPID_AUTO_TEST_CASE(testDispatcher) -{ - ClientSessionFixture fix; - fix.session =fix.connection.newSession(); - size_t count = 100; - for (size_t i = 0; i < count; ++i) - fix.session.messageTransfer(arg::content=Message(boost::lexical_cast<string>(i), "my-queue")); - DummyListener listener(fix.session, "my-queue", count); - listener.run(); - BOOST_CHECK_EQUAL(count, listener.messages.size()); - for (size_t i = 0; i < count; ++i) - BOOST_CHECK_EQUAL(boost::lexical_cast<string>(i), listener.messages[i].getData()); -} - -QPID_AUTO_TEST_CASE(testDispatcherThread) -{ - ClientSessionFixture fix; - fix.session =fix.connection.newSession(); - size_t count = 10; - DummyListener listener(fix.session, "my-queue", count); - sys::Thread t(listener); - for (size_t i = 0; i < count; ++i) { - fix.session.messageTransfer(arg::content=Message(boost::lexical_cast<string>(i), "my-queue")); - } - t.join(); - BOOST_CHECK_EQUAL(count, listener.messages.size()); - for (size_t i = 0; i < count; ++i) - BOOST_CHECK_EQUAL(boost::lexical_cast<string>(i), listener.messages[i].getData()); -} - -// FIXME aconway 2009-06-17: test for unimplemented feature, enable when implemented. -void testSuspend0Timeout() { - ClientSessionFixture fix; - fix.session.suspend(); // session has 0 timeout. - try { - fix.connection.resume(fix.session); - BOOST_FAIL("Expected InvalidArgumentException."); - } catch(const InternalErrorException&) {} -} - -QPID_AUTO_TEST_CASE(testUseSuspendedError) -{ - ClientSessionFixture fix; - fix.session.timeout(60); - fix.session.suspend(); - try { - fix.session.exchangeQuery(arg::exchange="amq.fanout"); - BOOST_FAIL("Expected session suspended exception"); - } catch(const NotAttachedException&) {} -} - -// FIXME aconway 2009-06-17: test for unimplemented feature, enable when implemented. -void testSuspendResume() { - ClientSessionFixture fix; - fix.session.timeout(60); - fix.session.suspend(); - // Make sure we are still subscribed after resume. - fix.connection.resume(fix.session); - fix.session.messageTransfer(arg::content=Message("my-message", "my-queue")); - BOOST_CHECK_EQUAL("my-message", fix.subs.get("my-queue", TIME_SEC).getData()); -} - - -QPID_AUTO_TEST_CASE(testSendToSelf) { - ClientSessionFixture fix; - SimpleListener mylistener; - fix.session.queueDeclare(arg::queue="myq", arg::exclusive=true, arg::autoDelete=true); - fix.subs.subscribe(mylistener, "myq"); - sys::Thread runner(fix.subs);//start dispatcher thread - string data("msg"); - Message msg(data, "myq"); - const uint count=10; - for (uint i = 0; i < count; ++i) { - fix.session.messageTransfer(arg::content=msg); - } - mylistener.waitFor(count); - fix.subs.cancel("myq"); - fix.subs.stop(); - runner.join(); - fix.session.close(); - BOOST_CHECK_EQUAL(mylistener.messages.size(), count); - for (uint j = 0; j < count; ++j) { - BOOST_CHECK_EQUAL(mylistener.messages[j].getData(), data); - } -} - -QPID_AUTO_TEST_CASE(testLocalQueue) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="lq", arg::exclusive=true, arg::autoDelete=true); - LocalQueue lq; - fix.subs.subscribe(lq, "lq", FlowControl(2, FlowControl::UNLIMITED, false)); - fix.session.messageTransfer(arg::content=Message("foo0", "lq")); - fix.session.messageTransfer(arg::content=Message("foo1", "lq")); - fix.session.messageTransfer(arg::content=Message("foo2", "lq")); - BOOST_CHECK_EQUAL("foo0", lq.pop().getData()); - BOOST_CHECK_EQUAL("foo1", lq.pop().getData()); - BOOST_CHECK(lq.empty()); // Credit exhausted. - fix.subs.getSubscription("lq").setFlowControl(FlowControl::unlimited()); - BOOST_CHECK_EQUAL("foo2", lq.pop().getData()); -} - -struct DelayedTransfer : sys::Runnable -{ - ClientSessionFixture& fixture; - - DelayedTransfer(ClientSessionFixture& f) : fixture(f) {} - - void run() - { - qpid::sys::sleep(1); - fixture.session.messageTransfer(arg::content=Message("foo2", "getq")); - } -}; - -QPID_AUTO_TEST_CASE(testGet) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="getq", arg::exclusive=true, arg::autoDelete=true); - fix.session.messageTransfer(arg::content=Message("foo0", "getq")); - fix.session.messageTransfer(arg::content=Message("foo1", "getq")); - Message got; - BOOST_CHECK(fix.subs.get(got, "getq", TIME_SEC)); - BOOST_CHECK_EQUAL("foo0", got.getData()); - BOOST_CHECK(fix.subs.get(got, "getq", TIME_SEC)); - BOOST_CHECK_EQUAL("foo1", got.getData()); - BOOST_CHECK(!fix.subs.get(got, "getq")); - DelayedTransfer sender(fix); - Thread t(sender); - //test timed get where message shows up after a short delay - BOOST_CHECK(fix.subs.get(got, "getq", 5*TIME_SEC)); - BOOST_CHECK_EQUAL("foo2", got.getData()); - t.join(); -} - -QPID_AUTO_TEST_CASE(testOpenFailure) { - BrokerFixture b; - Connection c; - string host("unknowable-host"); - try { - c.open(host); - } catch (const Exception&) { - BOOST_CHECK(!c.isOpen()); - } - b.open(c); - BOOST_CHECK(c.isOpen()); - c.close(); - BOOST_CHECK(!c.isOpen()); -} - -QPID_AUTO_TEST_CASE(testPeriodicExpiration) { - Broker::Options opts; - opts.queueCleanInterval = 1; - ClientSessionFixture fix(opts); - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true); - - for (uint i = 0; i < 10; i++) { - Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - if (i % 2) m.getDeliveryProperties().setTtl(500); - fix.session.messageTransfer(arg::content=m); - } - - BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 10u); - qpid::sys::sleep(2); - BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 5u); -} - -QPID_AUTO_TEST_CASE(testExpirationOnPop) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true); - - for (uint i = 0; i < 10; i++) { - Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - if (i % 2) m.getDeliveryProperties().setTtl(200); - fix.session.messageTransfer(arg::content=m); - } - - qpid::sys::usleep(300* 1000); - - for (uint i = 0; i < 10; i++) { - if (i % 2) continue; - Message m; - BOOST_CHECK(fix.subs.get(m, "my-queue", TIME_SEC)); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData()); - } -} - -QPID_AUTO_TEST_CASE(testRelease) { - ClientSessionFixture fix; - - const uint count=10; - for (uint i = 0; i < count; i++) { - Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - fix.session.messageTransfer(arg::content=m); - } - - fix.subs.setAutoStop(false); - fix.subs.start(); - SubscriptionSettings settings; - settings.autoAck = 0; - - SimpleListener l1; - Subscription s1 = fix.subs.subscribe(l1, "my-queue", settings); - l1.waitFor(count); - s1.cancel(); - - for (uint i = 0; i < count; i++) { - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), l1.messages[i].getData()); - } - s1.release(s1.getUnaccepted()); - - //check that released messages are redelivered - settings.autoAck = 1; - SimpleListener l2; - Subscription s2 = fix.subs.subscribe(l2, "my-queue", settings); - l2.waitFor(count); - for (uint i = 0; i < count; i++) { - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), l2.messages[i].getData()); - } - - fix.subs.stop(); - fix.subs.wait(); - fix.session.close(); -} - -QPID_AUTO_TEST_CASE(testCompleteOnAccept) { - ClientSessionFixture fix; - const uint count = 8; - const uint chunk = 4; - for (uint i = 0; i < count; i++) { - Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - fix.session.messageTransfer(arg::content=m); - } - - SubscriptionSettings settings; - settings.autoAck = 0; - settings.completionMode = COMPLETE_ON_ACCEPT; - settings.flowControl = FlowControl::messageWindow(chunk); - - LocalQueue q; - Subscription s = fix.subs.subscribe(q, "my-queue", settings); - fix.session.messageFlush(arg::destination=s.getName()); - SequenceSet accepted; - for (uint i = 0; i < chunk; i++) { - Message m; - BOOST_CHECK(q.get(m)); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData()); - accepted.add(m.getId()); - } - Message m; - BOOST_CHECK(!q.get(m)); - - s.accept(accepted); - fix.session.messageFlush(arg::destination=s.getName()); - accepted.clear(); - - for (uint i = chunk; i < count; i++) { - Message m; - BOOST_CHECK(q.get(m)); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData()); - accepted.add(m.getId()); - } - fix.session.messageAccept(accepted); -} - -namespace -{ -struct Publisher : qpid::sys::Runnable -{ - AsyncSession session; - Message message; - uint count; - Thread thread; - - Publisher(Connection& con, Message m, uint c) : session(con.newSession()), message(m), count(c) {} - - void start() - { - thread = Thread(*this); - } - - void join() - { - thread.join(); - } - - void run() - { - for (uint i = 0; i < count; i++) { - session.messageTransfer(arg::content=message); - } - session.sync(); - session.close(); - } -}; -} - -QPID_AUTO_TEST_CASE(testConcurrentSenders) -{ - //Ensure concurrent publishing sessions on a connection don't - //cause assertions, deadlocks or other undesirables: - BrokerFixture fix; - Connection connection; - ConnectionSettings settings; - settings.maxFrameSize = 1024; - settings.port = fix.broker->getPort(qpid::broker::Broker::TCP_TRANSPORT); - connection.open(settings); - AsyncSession session = connection.newSession(); - Message message(string(512, 'X')); - - boost::ptr_vector<Publisher> publishers; - for (size_t i = 0; i < 5; i++) { - publishers.push_back(new Publisher(connection, message, 100)); - } - std::for_each(publishers.begin(), publishers.end(), boost::bind(&Publisher::start, _1)); - std::for_each(publishers.begin(), publishers.end(), boost::bind(&Publisher::join, _1)); - connection.close(); -} - - -QPID_AUTO_TEST_CASE(testExclusiveSubscribe) -{ - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="myq", arg::exclusive=true, arg::autoDelete=true); - SubscriptionSettings settings; - settings.exclusive = true; - LocalQueue q; - fix.subs.subscribe(q, "myq", settings, "first"); - //attempt to create new subscriber should fail - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(fix.subs.subscribe(q, "myq", "second"), ResourceLockedException); - ; - -} - -QPID_AUTO_TEST_CASE(testExclusiveBinding) { - FieldTable options; - options.setString("qpid.exclusive-binding", "anything"); - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="queue-1", arg::exclusive=true, arg::autoDelete=true); - fix.session.queueDeclare(arg::queue="queue-2", arg::exclusive=true, arg::autoDelete=true); - fix.session.exchangeBind(arg::exchange="amq.direct", arg::queue="queue-1", arg::bindingKey="my-key", arg::arguments=options); - fix.session.messageTransfer(arg::destination="amq.direct", arg::content=Message("message1", "my-key")); - fix.session.exchangeBind(arg::exchange="amq.direct", arg::queue="queue-2", arg::bindingKey="my-key", arg::arguments=options); - fix.session.messageTransfer(arg::destination="amq.direct", arg::content=Message("message2", "my-key")); - - Message got; - BOOST_CHECK(fix.subs.get(got, "queue-1")); - BOOST_CHECK_EQUAL("message1", got.getData()); - BOOST_CHECK(!fix.subs.get(got, "queue-1")); - - BOOST_CHECK(fix.subs.get(got, "queue-2")); - BOOST_CHECK_EQUAL("message2", got.getData()); - BOOST_CHECK(!fix.subs.get(got, "queue-2")); -} - -QPID_AUTO_TEST_CASE(testResubscribeWithLocalQueue) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="some-queue", arg::exclusive=true, arg::autoDelete=true); - LocalQueue p, q; - fix.subs.subscribe(p, "some-queue"); - fix.subs.cancel("some-queue"); - fix.subs.subscribe(q, "some-queue"); - - fix.session.messageTransfer(arg::content=Message("some-data", "some-queue")); - fix.session.messageFlush(arg::destination="some-queue"); - - Message got; - BOOST_CHECK(!p.get(got)); - - BOOST_CHECK(q.get(got)); - BOOST_CHECK_EQUAL("some-data", got.getData()); - BOOST_CHECK(!q.get(got)); -} - -QPID_AUTO_TEST_CASE(testReliableDispatch) { - ClientSessionFixture fix; - std::string queue("a-queue"); - fix.session.queueDeclare(arg::queue=queue, arg::autoDelete=true); - - ConnectionSettings settings; - settings.port = fix.broker->getPort(qpid::broker::Broker::TCP_TRANSPORT); - - Connection c1; - c1.open(settings); - Session s1 = c1.newSession(); - SubscriptionManager subs1(s1); - LocalQueue q1; - subs1.subscribe(q1, queue, FlowControl());//first subscriber has no credit - - Connection c2; - c2.open(settings); - Session s2 = c2.newSession(); - SubscriptionManager subs2(s2); - LocalQueue q2; - subs2.subscribe(q2, queue);//second subscriber has credit - - fix.session.messageTransfer(arg::content=Message("my-message", queue)); - - //check that the second consumer gets the message - Message got; - BOOST_CHECK(q2.get(got, 1*TIME_SEC)); - BOOST_CHECK_EQUAL("my-message", got.getData()); - - c1.close(); - c2.close(); -} - -QPID_AUTO_TEST_CASE(testSessionCloseOnInvalidSession) { - Session session; - session.close(); -} - -QPID_AUTO_TEST_CASE(testLVQVariedSize) { - ClientSessionFixture fix; - std::string queue("my-lvq"); - QueueOptions args; - args.setOrdering(LVQ_NO_BROWSE); - fix.session.queueDeclare(arg::queue=queue, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - - std::string key; - args.getLVQKey(key); - - for (size_t i = 0; i < 10; i++) { - std::ostringstream data; - size_t size = 100 - ((i % 10) * 10); - data << std::string(size, 'x'); - - Message m(data.str(), queue); - m.getHeaders().setString(key, "abc"); - fix.session.messageTransfer(arg::content=m); - } -} - -QPID_AUTO_TEST_CASE(testSessionManagerSetFlowControl) { - ClientSessionFixture fix; - std::string name("dummy"); - LocalQueue queue; - SubscriptionSettings settings; - settings.flowControl = FlowControl(); - fix.session.queueDeclare(arg::queue=name, arg::exclusive=true, arg::autoDelete=true); - fix.subs.subscribe(queue, name, settings); - fix.session.messageTransfer(arg::content=Message("my-message", name)); - fix.subs.setFlowControl(name, 1, FlowControl::UNLIMITED, false); - fix.session.messageFlush(name); - Message got; - BOOST_CHECK(queue.get(got, 0)); - BOOST_CHECK_EQUAL("my-message", got.getData()); -} - -QPID_AUTO_TEST_CASE(testGetThenSubscribe) { - ClientSessionFixture fix; - std::string name("myqueue"); - fix.session.queueDeclare(arg::queue=name, arg::exclusive=true, arg::autoDelete=true); - fix.session.messageTransfer(arg::content=Message("one", name)); - fix.session.messageTransfer(arg::content=Message("two", name)); - Message got; - BOOST_CHECK(fix.subs.get(got, name)); - BOOST_CHECK_EQUAL("one", got.getData()); - - DummyListener listener(fix.session, name, 1); - listener.run(); - BOOST_CHECK_EQUAL(1u, listener.messages.size()); - if (!listener.messages.empty()) { - BOOST_CHECK_EQUAL("two", listener.messages[0].getData()); - } -} - -QPID_AUTO_TEST_CASE(testSessionIsValid) { - ClientSessionFixture fix; - BOOST_CHECK(fix.session.isValid()); - Session session; - BOOST_CHECK(!session.isValid()); -} - -QPID_AUTO_TEST_CASE(testExpirationNotAltered) { - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true); - - Message m("my-message", "my-queue"); - m.getDeliveryProperties().setTtl(60000); - m.getDeliveryProperties().setExpiration(12345); - fix.session.messageTransfer(arg::content=m); - Message got; - BOOST_CHECK(fix.subs.get(got, "my-queue")); - BOOST_CHECK_EQUAL("my-message", got.getData()); - BOOST_CHECK_EQUAL(12345u, got.getDeliveryProperties().getExpiration()); -} - -QPID_AUTO_TEST_CASE(testGetConnectionFromSession) { - ClientSessionFixture fix; - FieldTable options; - options.setInt("no-local", 1); - fix.session.queueDeclare(arg::queue="a", arg::exclusive=true, arg::autoDelete=true, arg::arguments=options); - fix.session.queueDeclare(arg::queue="b", arg::exclusive=true, arg::autoDelete=true); - - Connection c = fix.session.getConnection(); - Session s = c.newSession(); - //If this new session was created as expected on the same connection as - //fix.session, then the no-local behaviour means that queue 'a' - //will not enqueue messages from this new session but queue 'b' - //will. - s.messageTransfer(arg::content=Message("a", "a")); - s.messageTransfer(arg::content=Message("b", "b")); - - Message got; - BOOST_CHECK(fix.subs.get(got, "b")); - BOOST_CHECK_EQUAL("b", got.getData()); - BOOST_CHECK(!fix.subs.get(got, "a")); -} - - -QPID_AUTO_TEST_CASE(testQueueDeleted) -{ - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue"); - LocalQueue queue; - fix.subs.subscribe(queue, "my-queue"); - - ScopedSuppressLogging sl; - fix.session.queueDelete(arg::queue="my-queue"); - BOOST_CHECK_THROW(queue.get(1*qpid::sys::TIME_SEC), qpid::framing::ResourceDeletedException); -} - -QPID_AUTO_TEST_CASE(testTtl) -{ - const uint64_t ms = 1000ULL; // convert sec to ms - const uint64_t us = 1000ULL * 1000ULL; // convert sec to us - - ClientSessionFixture fix; - fix.session.queueDeclare(arg::queue="ttl-test", arg::exclusive=true, arg::autoDelete=true); - Message msg1 = Message("AAA", "ttl-test"); - uint64_t ttl = 2 * ms; // 2 sec - msg1.getDeliveryProperties().setTtl(ttl); - Connection c = fix.session.getConnection(); - Session s = c.newSession(); - s.messageTransfer(arg::content=msg1); - - Message msg2 = Message("BBB", "ttl-test"); - ttl = 10 * ms; // 10 sec - msg2.getDeliveryProperties().setTtl(ttl); - s.messageTransfer(arg::content=msg2); - - qpid::sys::usleep(5 * us); // 5 sec - - // Message "AAA" should be expired and never be delivered - // Check "BBB" has ttl somewhere between 1 and 5 secs - Message got; - BOOST_CHECK(fix.subs.get(got, "ttl-test")); - BOOST_CHECK_EQUAL("BBB", got.getData()); - BOOST_CHECK(got.getDeliveryProperties().getTtl() > 1 * ms); - BOOST_CHECK(got.getDeliveryProperties().getTtl() < ttl - (5 * ms)); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ClusterFailover.cpp b/cpp/src/tests/ClusterFailover.cpp deleted file mode 100644 index bf5c147f19..0000000000 --- a/cpp/src/tests/ClusterFailover.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/**@file Tests for partial failure in a cluster. - * Partial failure means some nodes experience a failure while others do not. - * In this case the failed nodes must shut down. - */ - -#include "test_tools.h" -#include "unit_test.h" -#include "ClusterFixture.h" -#include "qpid/client/FailoverManager.h" -#include <boost/assign.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/bind.hpp> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ClusterFailoverTestSuite) - -using namespace std; -using namespace qpid; -using namespace qpid::cluster; -using namespace qpid::framing; -using namespace qpid::client; -using namespace qpid::client::arg; -using namespace boost::assign; -using broker::Broker; -using boost::shared_ptr; - -// Timeout for tests that wait for messages -const sys::Duration TIMEOUT=sys::TIME_SEC/4; - -ClusterFixture::Args getArgs(bool durable=std::getenv("STORE_LIB")) -{ - ClusterFixture::Args args; - args += "--auth", "no", "--no-module-dir", - "--load-module", getLibPath("CLUSTER_LIB"); - if (durable) - args += "--load-module", getLibPath("STORE_LIB"), "TMP_DATA_DIR"; - else - args += "--no-data-dir"; - return args; -} - -// Test re-connecting with same session name after a failure. -QPID_AUTO_TEST_CASE(testReconnectSameSessionName) { - ClusterFixture cluster(2, getArgs(), -1); - // Specify a timeout to make sure it is ignored, session resume is - // not implemented so sessions belonging to dead brokers should - // not be kept. - Client c0(cluster[0], "foo", 5); - BOOST_CHECK_EQUAL(2u, knownBrokerPorts(c0.connection, 2).size()); // wait for both. - c0.session.queueDeclare("q"); - c0.session.messageTransfer(arg::content=Message("sendme", "q")); - BOOST_CHECK_EQUAL(c0.subs.get("q").getData(), "sendme"); - cluster.killWithSilencer(0, c0.connection, 9); - Client c1(cluster[1], "foo", 5); - c1.session.queueQuery(); // Try to use the session. -} - -QPID_AUTO_TEST_CASE(testReconnectExclusiveQueue) { - // Regresion test. Session timeouts should be ignored - // by the broker as session resume is not implemented. - ClusterFixture cluster(2, getArgs(), -1); - Client c0(cluster[0], "foo", 5); - c0.session.queueDeclare("exq", arg::exclusive=true); - SubscriptionSettings settings; - settings.exclusive = true; - settings.autoAck = 0; - Subscription s0 = c0.subs.subscribe(c0.lq, "exq", settings, "exsub"); - c0.session.messageTransfer(arg::content=Message("sendme", "exq")); - BOOST_CHECK_EQUAL(c0.lq.get().getData(), "sendme"); - - // Regression: core dump on exit if unacked messages were left in - // a session with a timeout. - cluster.killWithSilencer(0, c0.connection); - - // Regression: session timeouts prevented re-connecting to - // exclusive queue. - Client c1(cluster[1]); - c1.session.queueDeclare("exq", arg::exclusive=true); - Subscription s1 = c1.subs.subscribe(c1.lq, "exq", settings, "exsub"); - s1.cancel(); - - // Regression: session timeouts prevented new member joining - // cluster with exclusive queues. - cluster.add(); - Client c2(cluster[2]); - c2.session.queueQuery(); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ClusterFixture.cpp b/cpp/src/tests/ClusterFixture.cpp deleted file mode 100644 index 6b62cb6fc7..0000000000 --- a/cpp/src/tests/ClusterFixture.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test_tools.h" -#include "unit_test.h" -#include "ForkedBroker.h" -#include "BrokerFixture.h" - -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionAccess.h" -#include "qpid/client/Session.h" -#include "qpid/client/FailoverListener.h" -#include "qpid/cluster/Cluster.h" -#include "qpid/cluster/Cpg.h" -#include "qpid/cluster/UpdateClient.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/Uuid.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Logger.h" - -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/assign.hpp> - -#include <string> -#include <iostream> -#include <iterator> -#include <vector> -#include <set> -#include <algorithm> -#include <iterator> - - -using namespace std; -using namespace qpid; -using namespace qpid::cluster; -using namespace qpid::framing; -using namespace qpid::client; -using qpid::sys::TIME_SEC; -using qpid::broker::Broker; -using boost::shared_ptr; -using qpid::cluster::Cluster; -using boost::assign::list_of; - - -#include "ClusterFixture.h" - -namespace qpid { -namespace tests { - -ClusterFixture::ClusterFixture(size_t n, const Args& args_, int localIndex_) - : name(Uuid(true).str()), localIndex(localIndex_), userArgs(args_) -{ - add(n); -} - -ClusterFixture::ClusterFixture(size_t n, boost::function<void (Args&, size_t)> updateArgs_, int localIndex_) - : name(Uuid(true).str()), localIndex(localIndex_), updateArgs(updateArgs_) -{ - add(n); -} - -ClusterFixture::Args ClusterFixture::makeArgs(const std::string& prefix, size_t index) { - Args args = list_of<string>("qpidd ") - ("--cluster-name")(name) - ("--log-prefix")(prefix); - args.insert(args.end(), userArgs.begin(), userArgs.end()); - if (updateArgs) updateArgs(args, index); - return args; -} - -void ClusterFixture::add() { - if (size() != size_t(localIndex)) { // fork a broker process. - std::ostringstream os; os << "fork" << size(); - std::string prefix = os.str(); - forkedBrokers.push_back(shared_ptr<ForkedBroker>(new ForkedBroker(makeArgs(prefix, size())))); - push_back(forkedBrokers.back()->getPort()); - } - else { // Run in this process - addLocal(); - } -} - -namespace { -/** Parse broker & cluster options */ -Broker::Options parseOpts(size_t argc, const char* argv[]) { - Broker::Options opts; - Plugin::addOptions(opts); // Pick up cluster options. - opts.parse(argc, argv, "", true); // Allow-unknown for --load-module - return opts; -} -} - -void ClusterFixture::addLocal() { - assert(int(size()) == localIndex); - ostringstream os; os << "local" << localIndex; - string prefix = os.str(); - Args args(makeArgs(prefix, localIndex)); - vector<const char*> argv(args.size()); - transform(args.begin(), args.end(), argv.begin(), boost::bind(&string::c_str, _1)); - qpid::log::Logger::instance().setPrefix(prefix); - localBroker.reset(new BrokerFixture(parseOpts(argv.size(), &argv[0]))); - push_back(localBroker->getPort()); - forkedBrokers.push_back(shared_ptr<ForkedBroker>()); -} - -bool ClusterFixture::hasLocal() const { return localIndex >= 0 && size_t(localIndex) < size(); } - -/** Kill a forked broker with sig, or shutdown localBroker if n==0. */ -void ClusterFixture::kill(size_t n, int sig) { - if (n == size_t(localIndex)) - localBroker->broker->shutdown(); - else - forkedBrokers[n]->kill(sig); -} - -/** Kill a broker and suppress errors from closing connection c. */ -void ClusterFixture::killWithSilencer(size_t n, client::Connection& c, int sig) { - ScopedSuppressLogging sl; - try { c.close(); } catch(...) {} - kill(n,sig); -} - -/** - * Get the known broker ports from a Connection. - *@param n if specified wait for the cluster size to be n, up to a timeout. - */ -std::set<int> knownBrokerPorts(qpid::client::Connection& c, int n) { - FailoverListener fl(c, false); - std::vector<qpid::Url> urls = fl.getKnownBrokers(); - if (n >= 0 && unsigned(n) != urls.size()) { - // Retry up to 10 secs in .1 second intervals. - for (size_t retry=100; urls.size() != unsigned(n) && retry != 0; --retry) { - qpid::sys::usleep(1000*100); // 0.1 secs - urls = fl.getKnownBrokers(); - } - } - std::set<int> s; - for (std::vector<qpid::Url>::const_iterator i = urls.begin(); i != urls.end(); ++i) - s.insert((*i)[0].port); - return s; -} - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ClusterFixture.h b/cpp/src/tests/ClusterFixture.h deleted file mode 100644 index f548ff9376..0000000000 --- a/cpp/src/tests/ClusterFixture.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef CLUSTER_FIXTURE_H -#define CLUSTER_FIXTURE_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test_tools.h" -#include "unit_test.h" -#include "ForkedBroker.h" -#include "BrokerFixture.h" - -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionAccess.h" -#include "qpid/client/Session.h" -#include "qpid/client/FailoverListener.h" -#include "qpid/cluster/Cluster.h" -#include "qpid/cluster/Cpg.h" -#include "qpid/cluster/UpdateClient.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/Uuid.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Logger.h" - -#include <boost/bind.hpp> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> - -#include <string> -#include <iostream> -#include <iterator> -#include <vector> -#include <set> -#include <algorithm> -#include <iterator> - - -using namespace std; -using namespace qpid; -using namespace qpid::cluster; -using namespace qpid::framing; -using namespace qpid::client; -using qpid::sys::TIME_SEC; -using qpid::broker::Broker; -using boost::shared_ptr; -using qpid::cluster::Cluster; - -namespace qpid { -namespace tests { - -/** Cluster fixture is a vector of ports for the replicas. - * - * At most one replica (by default replica 0) is in the current - * process, all others are forked as children. - */ -class ClusterFixture : public vector<uint16_t> { - public: - typedef std::vector<std::string> Args; - - /** @param localIndex can be -1 meaning don't automatically start a local broker. - * A local broker can be started with addLocal(). - */ - ClusterFixture(size_t n, const Args& args, int localIndex=-1); - - /**@param updateArgs function is passed the index of the cluster member and can update the arguments. */ - ClusterFixture(size_t n, boost::function<void (Args&, size_t)> updateArgs, int localIndex=-1); - - void add(size_t n) { for (size_t i=0; i < n; ++i) add(); } - void add(); // Add a broker. - void setup(); - - bool hasLocal() const; - - /** Kill a forked broker with sig, or shutdown localBroker. */ - void kill(size_t n, int sig=SIGINT); - - /** Kill a broker and suppress errors from closing connection c. */ - void killWithSilencer(size_t n, client::Connection& c, int sig=SIGINT); - - private: - - void addLocal(); // Add a local broker. - Args makeArgs(const std::string& prefix, size_t index); - string name; - std::auto_ptr<BrokerFixture> localBroker; - int localIndex; - std::vector<shared_ptr<ForkedBroker> > forkedBrokers; - Args userArgs; - boost::function<void (Args&, size_t)> updateArgs; -}; - -/** - * Get the known broker ports from a Connection. - *@param n if specified wait for the cluster size to be n, up to a timeout. - */ -std::set<int> knownBrokerPorts(qpid::client::Connection& source, int n=-1); - -}} // namespace qpid::tests - -#endif /*!CLUSTER_FIXTURE_H*/ diff --git a/cpp/src/tests/ConnectionOptions.h b/cpp/src/tests/ConnectionOptions.h deleted file mode 100644 index fe945e9ddd..0000000000 --- a/cpp/src/tests/ConnectionOptions.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_CLIENT_CONNECTIONOPTIONS_H -#define QPID_CLIENT_CONNECTIONOPTIONS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/client/ConnectionSettings.h" -#include "qpid/Options.h" - -namespace qpid { - -/** - * Options parser for ConnectionOptions. - */ -struct ConnectionOptions : public qpid::Options, - public qpid::client::ConnectionSettings -{ - ConnectionOptions() : qpid::Options("Connection Settings") - { - using namespace qpid; - addOptions() - ("broker,b", optValue(host, "HOST"), "Broker host to connect to") - ("port,p", optValue(port, "PORT"), "Broker port to connect to") - ("protocol,P", optValue(protocol, "tcp|ssl|rdma"), "Protocol to use for broker connection") - ("virtualhost,v", optValue(virtualhost, "VHOST"), "virtual host") - ("username", optValue(username, "USER"), "user name for broker log in.") - ("password", optValue(password, "PASSWORD"), "password for broker log in.") - ("mechanism", optValue(mechanism, "MECH"), "SASL mechanism to use when authenticating.") - ("locale", optValue(locale, "LOCALE"), "locale to use.") - ("max-channels", optValue(maxChannels, "N"), "the maximum number of channels the client requires.") - ("heartbeat", optValue(heartbeat, "N"), "Desired heartbeat interval in seconds.") - ("max-frame-size", optValue(maxFrameSize, "N"), "the maximum frame size to request.") - ("bounds-multiplier", optValue(bounds, "N"), - "bound size of write queue (as a multiple of the max frame size).") - ("tcp-nodelay", optValue(tcpNoDelay), "Turn on tcp-nodelay") - ("service", optValue(service, "SERVICE-NAME"), "SASL service name.") - ("min-ssf", optValue(minSsf, "N"), "Minimum acceptable strength for SASL security layer") - ("max-ssf", optValue(maxSsf, "N"), "Maximum acceptable strength for SASL security layer"); - } -}; - -} // namespace qpid - -#endif /*!QPID_CLIENT_CONNECTIONOPTIONS_H*/ diff --git a/cpp/src/tests/ConsoleTest.cpp b/cpp/src/tests/ConsoleTest.cpp deleted file mode 100644 index 107472ed9e..0000000000 --- a/cpp/src/tests/ConsoleTest.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/console/Package.h" -#include "qpid/console/ClassKey.h" -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ConsoleTestSuite) - -using namespace qpid::framing; -using namespace qpid::console; - -QPID_AUTO_TEST_CASE(testClassKey) { - uint8_t hash[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; - ClassKey k("com.redhat.test", "class", hash); - - BOOST_CHECK_EQUAL(k.getPackageName(), "com.redhat.test"); - BOOST_CHECK_EQUAL(k.getClassName(), "class"); - BOOST_CHECK_EQUAL(k.getHashString(), "00010203-04050607-08090a0b-0c0d0e0f"); - BOOST_CHECK_EQUAL(k.str(), "com.redhat.test:class(00010203-04050607-08090a0b-0c0d0e0f)"); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/DeliveryRecordTest.cpp b/cpp/src/tests/DeliveryRecordTest.cpp deleted file mode 100644 index f7013014ff..0000000000 --- a/cpp/src/tests/DeliveryRecordTest.cpp +++ /dev/null @@ -1,67 +0,0 @@ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/Queue.h" -#include "unit_test.h" -#include <iostream> -#include <memory> -#include <boost/format.hpp> - -using namespace qpid::broker; -using namespace qpid::sys; -using namespace qpid::framing; -using boost::dynamic_pointer_cast; -using std::list; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(DeliveryRecordTestSuite) - -QPID_AUTO_TEST_CASE(testSort) -{ - list<SequenceNumber> ids; - ids.push_back(SequenceNumber(6)); - ids.push_back(SequenceNumber(2)); - ids.push_back(SequenceNumber(4)); - ids.push_back(SequenceNumber(5)); - ids.push_back(SequenceNumber(1)); - ids.push_back(SequenceNumber(3)); - - list<DeliveryRecord> records; - for (list<SequenceNumber>::iterator i = ids.begin(); i != ids.end(); i++) { - DeliveryRecord r(QueuedMessage(0), Queue::shared_ptr(), "tag", false, false, false); - r.setId(*i); - records.push_back(r); - } - records.sort(); - - SequenceNumber expected(0); - for (list<DeliveryRecord>::iterator i = records.begin(); i != records.end(); i++) { - BOOST_CHECK(i->getId() == ++expected); - } -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/DispatcherTest.cpp b/cpp/src/tests/DispatcherTest.cpp deleted file mode 100644 index e1691db584..0000000000 --- a/cpp/src/tests/DispatcherTest.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Poller.h" -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/DispatchHandle.h" -#include "qpid/sys/posix/PrivatePosix.h" -#include "qpid/sys/Thread.h" - -#include <sys/types.h> -#include <sys/socket.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <signal.h> - -#include <iostream> -#include <boost/bind.hpp> - -using namespace std; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -int writeALot(int fd, const string& s) { - int bytesWritten = 0; - do { - errno = 0; - int lastWrite = ::write(fd, s.c_str(), s.size()); - if ( lastWrite >= 0) { - bytesWritten += lastWrite; - } - } while (errno != EAGAIN); - return bytesWritten; -} - -int readALot(int fd) { - int bytesRead = 0; - char buf[10240]; - - do { - errno = 0; - int lastRead = ::read(fd, buf, sizeof(buf)); - if ( lastRead >= 0) { - bytesRead += lastRead; - } - } while (errno != EAGAIN); - return bytesRead; -} - -int64_t writtenBytes = 0; -int64_t readBytes = 0; - -void writer(DispatchHandle& h, int fd, const string& s) { - writtenBytes += writeALot(fd, s); - h.rewatch(); -} - -void reader(DispatchHandle& h, int fd) { - readBytes += readALot(fd); - h.rewatch(); -} - -void rInterrupt(DispatchHandle&) { - cerr << "R"; -} - -void wInterrupt(DispatchHandle&) { - cerr << "W"; -} - -DispatchHandle::Callback rcb = rInterrupt; -DispatchHandle::Callback wcb = wInterrupt; - -DispatchHandleRef *volatile rh = 0; -DispatchHandleRef *volatile wh = 0; - -volatile bool stopWait = false; -volatile bool phase1finished = false; - -timer_t timer; - -void stop_handler(int /*signo*/, siginfo_t* /*info*/, void* /*context*/) { - stopWait = true; -} - -void timer_handler(int /*signo*/, siginfo_t* /*info*/, void* /*context*/) { - static int count = 0; - if (count++ < 10) { - rh->call(rcb); - wh->call(wcb); - } else { - phase1finished = true; - assert(::timer_delete(timer) == 0); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int /*argc*/, char** /*argv*/) -{ - // Create poller - Poller::shared_ptr poller(new Poller); - - // Create dispatcher thread - Thread dt(*poller); - Thread dt1(*poller); - Thread dt2(*poller); - Thread dt3(*poller); - - // Setup sender and receiver - int sv[2]; - int rc = ::socketpair(AF_UNIX, SOCK_STREAM, 0, sv); - assert(rc >= 0); - - // Set non-blocking - rc = ::fcntl(sv[0], F_SETFL, O_NONBLOCK); - assert(rc >= 0); - - rc = ::fcntl(sv[1], F_SETFL, O_NONBLOCK); - assert(rc >= 0); - - // Make up a large string - string testString = "This is only a test ... 1,2,3,4,5,6,7,8,9,10;"; - for (int i = 0; i < 8; i++) - testString += testString; - - PosixIOHandle f0(sv[0]); - PosixIOHandle f1(sv[1]); - - rh = new DispatchHandleRef(f0, boost::bind(reader, _1, sv[0]), 0, 0); - wh = new DispatchHandleRef(f1, 0, boost::bind(writer, _1, sv[1], testString), 0); - - rh->startWatch(poller); - wh->startWatch(poller); - - // Set up a regular itimer interupt - // We assume that this thread will handle the signals whilst sleeping - // as the Poller threads have signal handling blocked - - // Signal handling - struct ::sigaction sa; - sa.sa_sigaction = timer_handler; - sa.sa_flags = SA_RESTART | SA_SIGINFO; - ::sigemptyset(&sa.sa_mask); - rc = ::sigaction(SIGRTMIN, &sa,0); - assert(rc == 0); - - ::sigevent se; - ::memset(&se, 0, sizeof(se)); // Clear to make valgrind happy (this *is* the neatest way to do this portably - sigh) - se.sigev_notify = SIGEV_SIGNAL; - se.sigev_signo = SIGRTMIN; - rc = ::timer_create(CLOCK_REALTIME, &se, &timer); - assert(rc == 0); - - itimerspec ts = { - /*.it_value = */ {2, 0}, // s, ns - /*.it_interval = */ {2, 0}}; // s, ns - - rc = ::timer_settime(timer, 0, &ts, 0); - assert(rc == 0); - - // wait - while (!phase1finished) { - ::sleep(1); - } - - // Now test deleting/creating DispatchHandles in tight loop, so that we are likely to still be using the - // attached PollerHandles after deleting the DispatchHandle - DispatchHandleRef* t = wh; - wh = 0; - delete t; - t = rh; - rh = 0; - delete t; - - sa.sa_sigaction = stop_handler; - rc = ::sigaction(SIGRTMIN, &sa,0); - assert(rc == 0); - - itimerspec nts = { - /*.it_value = */ {30, 0}, // s, ns - /*.it_interval = */ {30, 0}}; // s, ns - - rc = ::timer_create(CLOCK_REALTIME, &se, &timer); - assert(rc == 0); - rc = ::timer_settime(timer, 0, &nts, 0); - assert(rc == 0); - - DispatchHandleRef* rh1; - DispatchHandleRef* wh1; - - struct timespec w = {0, 1000000}; - while (!stopWait) { - rh1 = new DispatchHandleRef(f0, boost::bind(reader, _1, sv[0]), 0, 0); - wh1 = new DispatchHandleRef(f1, 0, boost::bind(writer, _1, sv[1], testString), 0); - rh1->startWatch(poller); - wh1->startWatch(poller); - - ::nanosleep(&w, 0); - - delete wh1; - delete rh1; - } - - rc = ::timer_delete(timer); - assert(rc == 0); - - poller->shutdown(); - dt.join(); - dt1.join(); - dt2.join(); - dt3.join(); - - cout << "\nWrote: " << writtenBytes << "\n"; - cout << "Read: " << readBytes << "\n"; - - return 0; -} diff --git a/cpp/src/tests/DtxWorkRecordTest.cpp b/cpp/src/tests/DtxWorkRecordTest.cpp deleted file mode 100644 index 9d7666dca4..0000000000 --- a/cpp/src/tests/DtxWorkRecordTest.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxWorkRecord.h" -#include "unit_test.h" -#include <iostream> -#include <vector> -#include "TxMocks.h" - -using namespace qpid::broker; -using boost::static_pointer_cast; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(DtxWorkRecordTestSuite) - -QPID_AUTO_TEST_CASE(testOnePhaseCommit){ - MockTransactionalStore store; - store.expectBegin().expectCommit(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectCommit(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare().expectCommit(); - - DtxBuffer::shared_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast<TxOp>(opA)); - bufferA->markEnded(); - DtxBuffer::shared_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast<TxOp>(opB)); - bufferB->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - - work.commit(true); - - store.check(); - BOOST_CHECK(store.isCommitted()); - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_CASE(testFailOnOnePhaseCommit){ - MockTransactionalStore store; - store.expectBegin().expectAbort(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectRollback(); - - DtxBuffer::shared_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast<TxOp>(opA)); - bufferA->markEnded(); - DtxBuffer::shared_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast<TxOp>(opB)); - bufferB->markEnded(); - DtxBuffer::shared_ptr bufferC(new DtxBuffer()); - bufferC->enlist(static_pointer_cast<TxOp>(opC)); - bufferC->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - work.add(bufferC); - - work.commit(true); - - BOOST_CHECK(store.isAborted()); - store.check(); - - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testTwoPhaseCommit){ - MockTransactionalStore store; - store.expectBegin2PC().expectPrepare().expectCommit(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectCommit(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare().expectCommit(); - - DtxBuffer::shared_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast<TxOp>(opA)); - bufferA->markEnded(); - DtxBuffer::shared_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast<TxOp>(opB)); - bufferB->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - - BOOST_CHECK(work.prepare()); - BOOST_CHECK(store.isPrepared()); - work.commit(false); - store.check(); - BOOST_CHECK(store.isCommitted()); - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_CASE(testFailOnTwoPhaseCommit){ - MockTransactionalStore store; - store.expectBegin2PC().expectAbort(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectRollback(); - - DtxBuffer::shared_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast<TxOp>(opA)); - bufferA->markEnded(); - DtxBuffer::shared_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast<TxOp>(opB)); - bufferB->markEnded(); - DtxBuffer::shared_ptr bufferC(new DtxBuffer()); - bufferC->enlist(static_pointer_cast<TxOp>(opC)); - bufferC->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - work.add(bufferC); - - BOOST_CHECK(!work.prepare()); - BOOST_CHECK(store.isAborted()); - store.check(); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testRollback){ - MockTransactionalStore store; - store.expectBegin2PC().expectPrepare().expectAbort(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare().expectRollback(); - - DtxBuffer::shared_ptr bufferA(new DtxBuffer()); - bufferA->enlist(static_pointer_cast<TxOp>(opA)); - bufferA->markEnded(); - DtxBuffer::shared_ptr bufferB(new DtxBuffer()); - bufferB->enlist(static_pointer_cast<TxOp>(opB)); - bufferB->markEnded(); - - DtxWorkRecord work("my-xid", &store); - work.add(bufferA); - work.add(bufferB); - - BOOST_CHECK(work.prepare()); - BOOST_CHECK(store.isPrepared()); - work.rollback(); - store.check(); - BOOST_CHECK(store.isAborted()); - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ExchangeTest.cpp b/cpp/src/tests/ExchangeTest.cpp deleted file mode 100644 index 88a1cd99c2..0000000000 --- a/cpp/src/tests/ExchangeTest.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Exception.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/framing/reply_exceptions.h" -#include "unit_test.h" -#include <iostream> -#include "MessageUtils.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -using namespace qpid; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ExchangeTestSuite) - -QPID_AUTO_TEST_CASE(testMe) -{ - Queue::shared_ptr queue(new Queue("queue", true)); - Queue::shared_ptr queue2(new Queue("queue2", true)); - - TopicExchange topic("topic"); - topic.bind(queue, "abc", 0); - topic.bind(queue2, "abc", 0); - - DirectExchange direct("direct"); - direct.bind(queue, "abc", 0); - direct.bind(queue2, "abc", 0); - - queue.reset(); - queue2.reset(); - - intrusive_ptr<Message> msgPtr(MessageUtils::createMessage("exchange", "key", false, "id")); - DeliverableMessage msg(msgPtr); - topic.route(msg, "abc", 0); - direct.route(msg, "abc", 0); - -} - -QPID_AUTO_TEST_CASE(testIsBound) -{ - Queue::shared_ptr a(new Queue("a", true)); - Queue::shared_ptr b(new Queue("b", true)); - Queue::shared_ptr c(new Queue("c", true)); - Queue::shared_ptr d(new Queue("d", true)); - - string k1("abc"); - string k2("def"); - string k3("xyz"); - - FanOutExchange fanout("fanout"); - BOOST_CHECK(fanout.bind(a, "", 0)); - BOOST_CHECK(fanout.bind(b, "", 0)); - BOOST_CHECK(fanout.bind(c, "", 0)); - - BOOST_CHECK(fanout.isBound(a, 0, 0)); - BOOST_CHECK(fanout.isBound(b, 0, 0)); - BOOST_CHECK(fanout.isBound(c, 0, 0)); - BOOST_CHECK(!fanout.isBound(d, 0, 0)); - - DirectExchange direct("direct"); - BOOST_CHECK(direct.bind(a, k1, 0)); - BOOST_CHECK(direct.bind(a, k3, 0)); - BOOST_CHECK(direct.bind(b, k2, 0)); - BOOST_CHECK(direct.bind(c, k1, 0)); - - BOOST_CHECK(direct.isBound(a, 0, 0)); - BOOST_CHECK(direct.isBound(a, &k1, 0)); - BOOST_CHECK(direct.isBound(a, &k3, 0)); - BOOST_CHECK(!direct.isBound(a, &k2, 0)); - BOOST_CHECK(direct.isBound(b, 0, 0)); - BOOST_CHECK(direct.isBound(b, &k2, 0)); - BOOST_CHECK(direct.isBound(c, &k1, 0)); - BOOST_CHECK(!direct.isBound(d, 0, 0)); - BOOST_CHECK(!direct.isBound(d, &k1, 0)); - BOOST_CHECK(!direct.isBound(d, &k2, 0)); - BOOST_CHECK(!direct.isBound(d, &k3, 0)); - - TopicExchange topic("topic"); - BOOST_CHECK(topic.bind(a, k1, 0)); - BOOST_CHECK(topic.bind(a, k3, 0)); - BOOST_CHECK(topic.bind(b, k2, 0)); - BOOST_CHECK(topic.bind(c, k1, 0)); - - BOOST_CHECK(topic.isBound(a, 0, 0)); - BOOST_CHECK(topic.isBound(a, &k1, 0)); - BOOST_CHECK(topic.isBound(a, &k3, 0)); - BOOST_CHECK(!topic.isBound(a, &k2, 0)); - BOOST_CHECK(topic.isBound(b, 0, 0)); - BOOST_CHECK(topic.isBound(b, &k2, 0)); - BOOST_CHECK(topic.isBound(c, &k1, 0)); - BOOST_CHECK(!topic.isBound(d, 0, 0)); - BOOST_CHECK(!topic.isBound(d, &k1, 0)); - BOOST_CHECK(!topic.isBound(d, &k2, 0)); - BOOST_CHECK(!topic.isBound(d, &k3, 0)); - - HeadersExchange headers("headers"); - FieldTable args1; - args1.setString("x-match", "all"); - args1.setString("a", "A"); - args1.setInt("b", 1); - FieldTable args2; - args2.setString("x-match", "any"); - args2.setString("a", "A"); - args2.setInt("b", 1); - FieldTable args3; - args3.setString("x-match", "any"); - args3.setString("c", "C"); - args3.setInt("b", 6); - - headers.bind(a, "", &args1); - headers.bind(a, "", &args3); - headers.bind(b, "", &args2); - headers.bind(c, "", &args1); - - BOOST_CHECK(headers.isBound(a, 0, 0)); - BOOST_CHECK(headers.isBound(a, 0, &args1)); - BOOST_CHECK(headers.isBound(a, 0, &args3)); - BOOST_CHECK(!headers.isBound(a, 0, &args2)); - BOOST_CHECK(headers.isBound(b, 0, 0)); - BOOST_CHECK(headers.isBound(b, 0, &args2)); - BOOST_CHECK(headers.isBound(c, 0, &args1)); - BOOST_CHECK(!headers.isBound(d, 0, 0)); - BOOST_CHECK(!headers.isBound(d, 0, &args1)); - BOOST_CHECK(!headers.isBound(d, 0, &args2)); - BOOST_CHECK(!headers.isBound(d, 0, &args3)); -} - -QPID_AUTO_TEST_CASE(testDeleteGetAndRedeclare) -{ - ExchangeRegistry exchanges; - exchanges.declare("my-exchange", "direct", false, FieldTable()); - exchanges.destroy("my-exchange"); - try { - exchanges.get("my-exchange"); - } catch (const NotFoundException&) {} - std::pair<Exchange::shared_ptr, bool> response = exchanges.declare("my-exchange", "direct", false, FieldTable()); - BOOST_CHECK_EQUAL(string("direct"), response.first->getType()); -} - -intrusive_ptr<Message> cmessage(std::string exchange, std::string routingKey) { - intrusive_ptr<Message> msg(new Message()); - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange, 0, 0))); - AMQFrame header((AMQHeaderBody())); - msg->getFrames().append(method); - msg->getFrames().append(header); - msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setRoutingKey(routingKey); - return msg; -} - -QPID_AUTO_TEST_CASE(testSequenceOptions) -{ - FieldTable args; - args.setInt("qpid.msg_sequence",1); - char* buff = new char[10000]; - framing::Buffer buffer(buff,10000); - { - DirectExchange direct("direct1", false, args); - - intrusive_ptr<Message> msg1 = cmessage("e", "A"); - intrusive_ptr<Message> msg2 = cmessage("e", "B"); - intrusive_ptr<Message> msg3 = cmessage("e", "C"); - - DeliverableMessage dmsg1(msg1); - DeliverableMessage dmsg2(msg2); - DeliverableMessage dmsg3(msg3); - - direct.route(dmsg1, "abc", 0); - direct.route(dmsg2, "abc", 0); - direct.route(dmsg3, "abc", 0); - - BOOST_CHECK_EQUAL(1, msg1->getApplicationHeaders()->getAsInt64("qpid.msg_sequence")); - BOOST_CHECK_EQUAL(2, msg2->getApplicationHeaders()->getAsInt64("qpid.msg_sequence")); - BOOST_CHECK_EQUAL(3, msg3->getApplicationHeaders()->getAsInt64("qpid.msg_sequence")); - - FanOutExchange fanout("fanout1", false, args); - HeadersExchange header("headers1", false, args); - TopicExchange topic ("topic1", false, args); - - // check other exchanges, that they preroute - intrusive_ptr<Message> msg4 = cmessage("e", "A"); - intrusive_ptr<Message> msg5 = cmessage("e", "B"); - intrusive_ptr<Message> msg6 = cmessage("e", "C"); - - DeliverableMessage dmsg4(msg4); - DeliverableMessage dmsg5(msg5); - DeliverableMessage dmsg6(msg6); - - fanout.route(dmsg4, "abc", 0); - BOOST_CHECK_EQUAL(1, msg4->getApplicationHeaders()->getAsInt64("qpid.msg_sequence")); - - FieldTable headers; - header.route(dmsg5, "abc", &headers); - BOOST_CHECK_EQUAL(1, msg5->getApplicationHeaders()->getAsInt64("qpid.msg_sequence")); - - topic.route(dmsg6, "abc", 0); - BOOST_CHECK_EQUAL(1, msg6->getApplicationHeaders()->getAsInt64("qpid.msg_sequence")); - direct.encode(buffer); - } - { - - ExchangeRegistry exchanges; - buffer.reset(); - DirectExchange::shared_ptr exch_dec = Exchange::decode(exchanges, buffer); - - intrusive_ptr<Message> msg1 = cmessage("e", "A"); - DeliverableMessage dmsg1(msg1); - exch_dec->route(dmsg1, "abc", 0); - - BOOST_CHECK_EQUAL(4, msg1->getApplicationHeaders()->getAsInt64("qpid.msg_sequence")); - - } - delete [] buff; -} - -QPID_AUTO_TEST_CASE(testIVEOption) -{ - FieldTable args; - args.setInt("qpid.ive",1); - DirectExchange direct("direct1", false, args); - FanOutExchange fanout("fanout1", false, args); - HeadersExchange header("headers1", false, args); - TopicExchange topic ("topic1", false, args); - - intrusive_ptr<Message> msg1 = cmessage("direct1", "abc"); - msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString("a", "abc"); - DeliverableMessage dmsg1(msg1); - - FieldTable args2; - args2.setString("x-match", "any"); - args2.setString("a", "abc"); - - direct.route(dmsg1, "abc", 0); - fanout.route(dmsg1, "abc", 0); - header.route(dmsg1, "abc", &args2); - topic.route(dmsg1, "abc", 0); - Queue::shared_ptr queue(new Queue("queue", true)); - Queue::shared_ptr queue1(new Queue("queue1", true)); - Queue::shared_ptr queue2(new Queue("queue2", true)); - Queue::shared_ptr queue3(new Queue("queue3", true)); - - BOOST_CHECK(HeadersExchange::match(args2, msg1->getProperties<MessageProperties>()->getApplicationHeaders())); - - BOOST_CHECK(direct.bind(queue, "abc", 0)); - BOOST_CHECK(fanout.bind(queue1, "abc", 0)); - BOOST_CHECK(header.bind(queue2, "", &args2)); - BOOST_CHECK(topic.bind(queue3, "abc", 0)); - - BOOST_CHECK_EQUAL(1u,queue->getMessageCount()); - BOOST_CHECK_EQUAL(1u,queue1->getMessageCount()); - BOOST_CHECK_EQUAL(1u,queue2->getMessageCount()); - BOOST_CHECK_EQUAL(1u,queue3->getMessageCount()); - -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/FieldTable.cpp b/cpp/src/tests/FieldTable.cpp deleted file mode 100644 index fe2a14ec03..0000000000 --- a/cpp/src/tests/FieldTable.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/framing/Array.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/List.h" -#include "qpid/sys/alloca.h" - -#include "unit_test.h" - -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(FieldTableTestSuite) - -QPID_AUTO_TEST_CASE(testMe) -{ - FieldTable ft; - ft.setString("A", "BCDE"); - BOOST_CHECK(string("BCDE") == ft.getAsString("A")); - - char buff[100]; - Buffer wbuffer(buff, 100); - wbuffer.put(ft); - - Buffer rbuffer(buff, 100); - FieldTable ft2; - rbuffer.get(ft2); - BOOST_CHECK(string("BCDE") == ft2.getAsString("A")); - -} - -QPID_AUTO_TEST_CASE(testAssignment) -{ - FieldTable a; - FieldTable b; - - a.setString("A", "BBBB"); - a.setInt("B", 1234); - b = a; - a.setString("A", "CCCC"); - - BOOST_CHECK(string("CCCC") == a.getAsString("A")); - BOOST_CHECK(string("BBBB") == b.getAsString("A")); - BOOST_CHECK_EQUAL(1234, a.getAsInt("B")); - BOOST_CHECK_EQUAL(1234, b.getAsInt("B")); - BOOST_CHECK(IntegerValue(1234) == *a.get("B")); - BOOST_CHECK(IntegerValue(1234) == *b.get("B")); - - FieldTable d; - { - FieldTable c; - c = a; - - char* buff = static_cast<char*>(::alloca(c.encodedSize())); - Buffer wbuffer(buff, c.encodedSize()); - wbuffer.put(c); - - Buffer rbuffer(buff, c.encodedSize()); - rbuffer.get(d); - BOOST_CHECK_EQUAL(c, d); - BOOST_CHECK(string("CCCC") == c.getAsString("A")); - BOOST_CHECK(IntegerValue(1234) == *c.get("B")); - } - BOOST_CHECK(string("CCCC") == d.getAsString("A")); - BOOST_CHECK(IntegerValue(1234) == *d.get("B")); -} - - -QPID_AUTO_TEST_CASE(testNestedValues) -{ - double d = 1.2345; - uint32_t u = 101; - char buff[1000]; - { - FieldTable a; - FieldTable b; - std::vector<std::string> items; - items.push_back("one"); - items.push_back("two"); - Array c(items); - List list; - list.push_back(List::ValuePtr(new Str16Value("red"))); - list.push_back(List::ValuePtr(new Unsigned32Value(u))); - list.push_back(List::ValuePtr(new Str8Value("yellow"))); - list.push_back(List::ValuePtr(new DoubleValue(d))); - - a.setString("id", "A"); - b.setString("id", "B"); - a.setTable("B", b); - a.setArray("C", c); - a.set("my-list", FieldTable::ValuePtr(new ListValue(list))); - - - Buffer wbuffer(buff, 100); - wbuffer.put(a); - } - { - Buffer rbuffer(buff, 100); - FieldTable a; - FieldTable b; - Array c; - rbuffer.get(a); - BOOST_CHECK(string("A") == a.getAsString("id")); - a.getTable("B", b); - BOOST_CHECK(string("B") == b.getAsString("id")); - a.getArray("C", c); - std::vector<std::string> items; - c.collect(items); - BOOST_CHECK((uint) 2 == items.size()); - BOOST_CHECK(string("one") == items[0]); - BOOST_CHECK(string("two") == items[1]); - - List list; - BOOST_CHECK(a.get("my-list")->get<List>(list)); - List::const_iterator i = list.begin(); - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL(std::string("red"), (*i)->get<std::string>()); - - i++; - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL(u, (uint32_t) (*i)->get<int>()); - - i++; - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL(std::string("yellow"), (*i)->get<std::string>()); - - i++; - BOOST_CHECK(i != list.end()); - BOOST_CHECK_EQUAL(d, (*i)->get<double>()); - - i++; - BOOST_CHECK(i == list.end()); - } -} - -QPID_AUTO_TEST_CASE(testFloatAndDouble) -{ - char buff[100]; - float f = 5.672f; - double d = 56.720001; - { - FieldTable a; - a.setString("string", "abc"); - a.setInt("int", 5672); - a.setFloat("float", f); - a.setDouble("double", d); - - Buffer wbuffer(buff, 100); - wbuffer.put(a); - } - { - Buffer rbuffer(buff, 100); - FieldTable a; - rbuffer.get(a); - BOOST_CHECK(string("abc") == a.getAsString("string")); - BOOST_CHECK(5672 == a.getAsInt("int")); - float f2; - BOOST_CHECK(!a.getFloat("string", f2)); - BOOST_CHECK(!a.getFloat("int", f2)); - BOOST_CHECK(a.getFloat("float", f2)); - BOOST_CHECK(f2 == f); - - double d2; - BOOST_CHECK(!a.getDouble("string", d2)); - BOOST_CHECK(!a.getDouble("int", d2)); - BOOST_CHECK(a.getDouble("double", d2)); - BOOST_CHECK(d2 == d); - } -} - -QPID_AUTO_TEST_CASE(test64GetAndSetConverts) -{ - FieldTable args; - args.setInt64("a",100); - args.setInt64("b",-(int64_t) ((int64_t) 1<<34)); - - args.setUInt64("c",1u); - args.setUInt64("d",(uint64_t) ((uint64_t) 1<<34)); - BOOST_CHECK_EQUAL(1u, args.getAsUInt64("c")); - BOOST_CHECK_EQUAL(100u, args.getAsUInt64("a")); - BOOST_CHECK_EQUAL(1, args.getAsInt64("c")); - BOOST_CHECK_EQUAL(100, args.getAsInt64("a")); - BOOST_CHECK_EQUAL(-(int64_t) ((int64_t) 1<<34), args.getAsInt64("b")); - BOOST_CHECK_EQUAL((uint64_t) ((uint64_t) 1<<34), args.getAsUInt64("d")); - BOOST_CHECK_EQUAL((int64_t) ((int64_t) 1<<34), args.getAsInt64("d")); - -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/FieldValue.cpp b/cpp/src/tests/FieldValue.cpp deleted file mode 100644 index 0ebd0d7d44..0000000000 --- a/cpp/src/tests/FieldValue.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#include "qpid/framing/FieldValue.h" - -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(FieldValueTestSuite) - -using namespace qpid::framing; - -Str16Value s("abc"); -IntegerValue i(42); -//DecimalValue d(1234,2); -//FieldTableValue ft; -//EmptyValue e; - -QPID_AUTO_TEST_CASE(testStr16ValueEquals) -{ - - BOOST_CHECK(Str16Value("abc") == s); - BOOST_CHECK(Str16Value("foo") != s); - BOOST_CHECK(s != i); - BOOST_CHECK(s.convertsTo<std::string>() == true); - BOOST_CHECK(s.convertsTo<int>() == false); - BOOST_CHECK(s.get<std::string>() == "abc"); - BOOST_CHECK_THROW(s.get<int>(), InvalidConversionException); -// BOOST_CHECK(s != ft); - -} - -QPID_AUTO_TEST_CASE(testIntegerValueEquals) -{ - BOOST_CHECK(IntegerValue(42) == i); - BOOST_CHECK(IntegerValue(5) != i); - BOOST_CHECK(i != s); - BOOST_CHECK(i.convertsTo<std::string>() == false); - BOOST_CHECK(i.convertsTo<int>() == true); - BOOST_CHECK_THROW(i.get<std::string>(), InvalidConversionException); - BOOST_CHECK(i.get<int>() == 42); -// BOOST_CHECK(i != ft); -} - -#if 0 -QPID_AUTO_TEST_CASE(testDecimalValueEquals) -{ - BOOST_CHECK(DecimalValue(1234, 2) == d); - BOOST_CHECK(DecimalValue(12345, 2) != d); - BOOST_CHECK(DecimalValue(1234, 3) != d); - BOOST_CHECK(d != s); -} - -QPID_AUTO_TEST_CASE(testFieldTableValueEquals) -{ - ft.getValue().setString("foo", "FOO"); - ft.getValue().setInt("magic", 7); - - BOOST_CHECK_EQUAL(std::string("FOO"), - ft.getValue().getString("foo")); - BOOST_CHECK_EQUAL(7, ft.getValue().getInt("magic")); - - FieldTableValue f2; - BOOST_CHECK(ft != f2); - f2.getValue().setString("foo", "FOO"); - BOOST_CHECK(ft != f2); - f2.getValue().setInt("magic", 7); - BOOST_CHECK_EQUAL(ft,f2); - BOOST_CHECK(ft == f2); - f2.getValue().setString("foo", "BAR"); - BOOST_CHECK(ft != f2); - BOOST_CHECK(ft != i); -} -#endif - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ForkedBroker.cpp b/cpp/src/tests/ForkedBroker.cpp deleted file mode 100644 index 53eaa7e1ce..0000000000 --- a/cpp/src/tests/ForkedBroker.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "ForkedBroker.h" -#include "qpid/log/Statement.h" -#include <boost/bind.hpp> -#include <algorithm> -#include <stdlib.h> -#include <sys/types.h> -#include <signal.h> - -using namespace std; -using qpid::ErrnoException; - -namespace std { -static ostream& operator<<(ostream& o, const qpid::tests::ForkedBroker::Args& a) { -copy(a.begin(), a.end(), ostream_iterator<string>(o, " ")); -return o; -} -} - -namespace qpid { -namespace tests { - -ForkedBroker::ForkedBroker(const Args& constArgs) : running(false), exitStatus(0) { - Args args(constArgs); - // Substitute the special value "TMP_DATA_DIR" with a temporary data dir. - Args::iterator i = find(args.begin(), args.end(), string("TMP_DATA_DIR")); - if (i != args.end()) { - args.erase(i); - char dd[] = "/tmp/ForkedBroker.XXXXXX"; - if (!mkdtemp(dd)) - throw qpid::ErrnoException("Can't create data dir"); - dataDir = dd; - args.push_back("--data-dir"); - args.push_back(dataDir); - } - // Never use the default data directory, set --no-data-dir if no other data-dir arg. - Args::iterator j = find(args.begin(), args.end(), string("--data-dir")); - Args::iterator k = find(args.begin(), args.end(), string("--no-data-dir")); - if (j == args.end() && k == args.end()) - args.push_back("--no-data-dir"); - init(args); -} - -ForkedBroker::~ForkedBroker() { - try { kill(); } - catch (const std::exception& e) { - QPID_LOG(error, QPID_MSG("Killing forked broker: " << e.what())); - } - if (!dataDir.empty()) - { - int unused_ret; // Suppress warnings about ignoring return value. - unused_ret = ::system(("rm -rf "+dataDir).c_str()); - } -} - -void ForkedBroker::kill(int sig) { - if (pid == 0) return; - int savePid = pid; - pid = 0; // Reset pid here in case of an exception. - using qpid::ErrnoException; - if (::kill(savePid, sig) < 0) - throw ErrnoException("kill failed"); - int status; - if (::waitpid(savePid, &status, 0) < 0 && sig != 9) - throw ErrnoException("wait for forked process failed"); - if (WEXITSTATUS(status) != 0 && sig != 9) - throw qpid::Exception(QPID_MSG("Forked broker exited with: " << WEXITSTATUS(status))); - running = false; - exitStatus = status; -} - -bool isLogOption(const std::string& s) { - const char * log_enable = "--log-enable", - * trace = "--trace"; - return( (! strncmp(s.c_str(), log_enable, strlen(log_enable))) || - (! strncmp(s.c_str(), trace, strlen(trace))) - ); -} - -namespace { - void ignore_signal(int) - { - } -} - -void ForkedBroker::init(const Args& userArgs) { - using qpid::ErrnoException; - port = 0; - int pipeFds[2]; - if(::pipe(pipeFds) < 0) throw ErrnoException("Can't create pipe"); - - // Ignore the SIGCHLD signal generated by an exitting child - // We will clean up any exitting children in the waitpid above - // This should really be neater (like only once not per fork) - struct ::sigaction sa; - sa.sa_handler = ignore_signal; - ::sigemptyset(&sa.sa_mask); - ::sigaddset(&sa.sa_mask, SIGCHLD); - sa.sa_flags = SA_NOCLDSTOP | SA_RESTART; - ::sigaction(SIGCHLD, &sa, 0); - - pid = ::fork(); - if (pid < 0) throw ErrnoException("Fork failed"); - if (pid) { // parent - ::close(pipeFds[1]); - FILE* f = ::fdopen(pipeFds[0], "r"); - if (!f) throw ErrnoException("fopen failed"); - if (::fscanf(f, "%d", &port) != 1) { - if (ferror(f)) throw ErrnoException("Error reading port number from child."); - else throw qpid::Exception("EOF reading port number from child."); - } - ::fclose(f); - running = true; - } - else { // child - ::close(pipeFds[0]); - int fd = ::dup2(pipeFds[1], 1); // pipe stdout to the parent. - if (fd < 0) throw ErrnoException("dup2 failed"); - const char* prog = ::getenv("QPIDD_EXEC"); - if (!prog) prog = "../qpidd"; // This only works from within svn checkout - Args args(userArgs); - args.push_back("--port=0"); - // Keep quiet except for errors. - if (!::getenv("QPID_TRACE") && !::getenv("QPID_LOG_ENABLE") - && find_if(userArgs.begin(), userArgs.end(), isLogOption) == userArgs.end()) - args.push_back("--log-enable=error+"); - std::vector<const char*> argv(args.size()); - std::transform(args.begin(), args.end(), argv.begin(), boost::bind(&std::string::c_str, _1)); - argv.push_back(0); - QPID_LOG(debug, "ForkedBroker exec " << prog << ": " << args); - - execv(prog, const_cast<char* const*>(&argv[0])); - QPID_LOG(critical, "execv failed to start broker: prog=\"" << prog << "\"; args=\"" << args << "\"; errno=" << errno << " (" << std::strerror(errno) << ")"); - ::exit(1); - } -} - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ForkedBroker.h b/cpp/src/tests/ForkedBroker.h deleted file mode 100644 index 87e141a425..0000000000 --- a/cpp/src/tests/ForkedBroker.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef TESTS_FORKEDBROKER_H -#define TESTS_FORKEDBROKER_H - - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" -#include "qpid/broker/Broker.h" -#include <boost/lexical_cast.hpp> -#include <string> -#include <stdio.h> -#include <sys/wait.h> - -namespace qpid { -namespace tests { - -/** - * Class to fork a broker child process. - * - * For most tests a BrokerFixture may be more convenient as it starts - * a broker in the same process which allows you to easily debug into - * the broker. - * - * This useful for tests that need to start multiple brokers where - * those brokers can't coexist in the same process (e.g. for cluster - * tests where CPG doesn't allow multiple group members in a single - * process.) - * - */ -class ForkedBroker { - public: - typedef std::vector<std::string> Args; - - // argv args are passed to broker. - // - // Special value "TMP_DATA_DIR" is substituted with a temporary - // data directory for the broker. - // - ForkedBroker(const Args& argv); - ~ForkedBroker(); - - void kill(int sig=SIGINT); - int wait(); // Wait for exit, return exit status. - uint16_t getPort() { return port; } - pid_t getPID() { return pid; } - bool isRunning() { return running; } - - private: - - void init(const Args& args); - - bool running; - int exitStatus; - - pid_t pid; - int port; - std::string dataDir; -}; - -}} // namespace qpid::tests - -#endif /*!TESTS_FORKEDBROKER_H*/ diff --git a/cpp/src/tests/Frame.cpp b/cpp/src/tests/Frame.cpp deleted file mode 100644 index 1270eabba3..0000000000 --- a/cpp/src/tests/Frame.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/framing/Frame.h" - -#include <boost/lexical_cast.hpp> -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(FrameTestSuite) - -using namespace std; -using namespace qpid::framing; -using namespace boost; - -QPID_AUTO_TEST_CASE(testContentBody) { - Frame f(42, AMQContentBody("foobar")); - AMQBody* body=f.getBody(); - BOOST_CHECK(dynamic_cast<AMQContentBody*>(body)); - Buffer b(f.encodedSize(); - f.encode(b); - b.flip(); - Frame g; - g.decode(b); - AMQContentBody* content=dynamic_cast<AMQContentBody*>(g.getBody()); - BOOST_REQUIRE(content); - BOOST_CHECK_EQUAL(content->getData(), "foobar"); -} - -QPID_AUTO_TEST_CASE(testMethodBody) { - FieldTable args; - args.setString("foo", "bar"); - Frame f( - 42, QueueDeclareBody(ProtocolVersion(), 1, "q", "altex", - true, false, true, false, true, args)); - BOOST_CHECK_EQUAL(f.getChannel(), 42); - Buffer b(f.encodedSize(); - f.encode(b); - b.flip(); - Frame g; - g.decode(b); - BOOST_CHECK_EQUAL(f.getChannel(), g.getChannel()); - QueueDeclareBody* declare=dynamic_cast<QueueDeclareBody*>(g.getBody()); - BOOST_REQUIRE(declare); - BOOST_CHECK_EQUAL(declare->getAlternateExchange(), "altex"); - BOOST_CHECK_EQUAL(lexical_cast<string>(*f.getBody()), lexical_cast<string>(*g.getBody())); -} - -QPID_AUTO_TEST_CASE(testLoop) { - // Run in a loop so heap profiler can spot any allocations. - Buffer b(1024); - for (int i = 0; i < 100; ++i) { - Frame ctor(2, AccessRequestOkBody(ProtocolVersion(), 42)); - Frame assign(3); - assign.body = AccessRequestOkBody(ProtocolVersion(), 42); - assign.encode(b); - b.flip(); - Frame g; - g.decode(b); - BOOST_REQUIRE(dynamic_cast<AccessRequestOkBody*>(g.getBody())->getTicket() == 42); - } -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/FrameDecoder.cpp b/cpp/src/tests/FrameDecoder.cpp deleted file mode 100644 index 9eeff2a41e..0000000000 --- a/cpp/src/tests/FrameDecoder.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "unit_test.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FrameDecoder.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/Buffer.h" -#include <string> - - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(FrameDecoderTest) - -using namespace std; -using namespace qpid::framing; - - -string makeData(int size) { - string data; - data.resize(size); - for (int i =0; i < size; ++i) - data[i] = 'a' + (i%26); - return data; -} -string encodeFrame(string data) { - AMQFrame f((AMQContentBody(data))); - string encoded; - encoded.resize(f.encodedSize()); - Buffer b(&encoded[0], encoded.size()); - f.encode(b); - return encoded; -} - -string getData(const AMQFrame& frame) { - const AMQContentBody* content = dynamic_cast<const AMQContentBody*>(frame.getBody()); - BOOST_CHECK(content); - return content->getData(); -} - -QPID_AUTO_TEST_CASE(testByteFragments) { - string data = makeData(42); - string encoded = encodeFrame(data); - FrameDecoder decoder; - for (size_t i = 0; i < encoded.size()-1; ++i) { - Buffer buf(&encoded[i], 1); - BOOST_CHECK(!decoder.decode(buf)); - } - Buffer buf(&encoded[encoded.size()-1], 1); - BOOST_CHECK(decoder.decode(buf)); - BOOST_CHECK_EQUAL(data, getData(decoder.getFrame())); -} - - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/FramingTest.cpp b/cpp/src/tests/FramingTest.cpp deleted file mode 100644 index f8795316cc..0000000000 --- a/cpp/src/tests/FramingTest.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/client/Connection.h" -#include "qpid/client/Connector.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/framing/all_method_bodies.h" -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/reply_exceptions.h" -#include "unit_test.h" - -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> -#include <iostream> - -#include <memory> -#include <sstream> -#include <typeinfo> - -using namespace qpid; -using namespace qpid::framing; -using namespace std; - -namespace qpid { -namespace tests { - -template <class T> -std::string tostring(const T& x) -{ - std::ostringstream out; - out << x; - return out.str(); -} - -QPID_AUTO_TEST_SUITE(FramingTestSuite) - -QPID_AUTO_TEST_CASE(testMessageTransferBody) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - MessageTransferBody in(version, "my-exchange", 1, 1); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - MessageTransferBody out(version); - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testConnectionSecureBody) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - std::string s = "security credential"; - ConnectionSecureBody in(version, s); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - ConnectionSecureBody out(version); - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testConnectionRedirectBody) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - std::string a = "hostA"; - std::string b = "hostB"; - Array hosts(0x95); - hosts.add(boost::shared_ptr<FieldValue>(new Str16Value(a))); - hosts.add(boost::shared_ptr<FieldValue>(new Str16Value(b))); - - ConnectionRedirectBody in(version, a, hosts); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - ConnectionRedirectBody out(version); - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testQueueDeclareBody) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - QueueDeclareBody in(version, "name", "dlq", true, false, true, false, FieldTable()); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - QueueDeclareBody out(version); - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testConnectionRedirectBodyFrame) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - std::string a = "hostA"; - std::string b = "hostB"; - Array hosts(0x95); - hosts.add(boost::shared_ptr<FieldValue>(new Str16Value(a))); - hosts.add(boost::shared_ptr<FieldValue>(new Str16Value(b))); - - AMQFrame in((ConnectionRedirectBody(version, a, hosts))); - in.setChannel(999); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - AMQFrame out; - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(testMessageCancelBodyFrame) -{ - char buffer[1024]; - ProtocolVersion version(highestProtocolVersion); - Buffer wbuff(buffer, sizeof(buffer)); - AMQFrame in((MessageCancelBody(version, "tag"))); - in.setChannel(999); - in.encode(wbuff); - - Buffer rbuff(buffer, sizeof(buffer)); - AMQFrame out; - out.decode(rbuff); - BOOST_CHECK_EQUAL(tostring(in), tostring(out)); -} - -QPID_AUTO_TEST_CASE(badStrings) { - char data[(65535 + 2) + (255 + 1)]; - Buffer b(data, sizeof(data)); - BOOST_CHECK_THROW(b.putShortString(std::string(256, 'X')), - Exception); - BOOST_CHECK_THROW(b.putMediumString(std::string(65536, 'X')), - Exception); - b.putShortString(std::string(255, 'X')); - b.putMediumString(std::string(65535, 'X')); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/HeaderTest.cpp b/cpp/src/tests/HeaderTest.cpp deleted file mode 100644 index 4b16f3c793..0000000000 --- a/cpp/src/tests/HeaderTest.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/framing/amqp_framing.h" -#include "qpid/framing/FieldValue.h" -#include "unit_test.h" - -using namespace qpid::framing; -using namespace std; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(HeaderTestSuite) - -QPID_AUTO_TEST_CASE(testGenericProperties) -{ - AMQHeaderBody body; - body.get<MessageProperties>(true)->getApplicationHeaders().setString( - "A", "BCDE"); - char buff[100]; - Buffer wbuffer(buff, 100); - body.encode(wbuffer); - - Buffer rbuffer(buff, 100); - AMQHeaderBody body2; - body2.decode(rbuffer, body.encodedSize()); - MessageProperties* props = - body2.get<MessageProperties>(true); - BOOST_CHECK_EQUAL( - string("BCDE"), - props->getApplicationHeaders().get("A")->get<string>()); -} - -QPID_AUTO_TEST_CASE(testMessageProperties) -{ - AMQFrame out((AMQHeaderBody())); - MessageProperties* props1 = - out.castBody<AMQHeaderBody>()->get<MessageProperties>(true); - - props1->setContentLength(42); - props1->setMessageId(Uuid(true)); - props1->setCorrelationId("correlationId"); - props1->setReplyTo(ReplyTo("ex","key")); - props1->setContentType("contentType"); - props1->setContentEncoding("contentEncoding"); - props1->setUserId("userId"); - props1->setAppId("appId"); - - char buff[10000]; - Buffer wbuffer(buff, 10000); - out.encode(wbuffer); - - Buffer rbuffer(buff, 10000); - AMQFrame in; - in.decode(rbuffer); - MessageProperties* props2 = - in.castBody<AMQHeaderBody>()->get<MessageProperties>(true); - - BOOST_CHECK_EQUAL(props1->getContentLength(), props2->getContentLength()); - BOOST_CHECK_EQUAL(props1->getMessageId(), props2->getMessageId()); - BOOST_CHECK_EQUAL(props1->getCorrelationId(), props2->getCorrelationId()); - BOOST_CHECK_EQUAL(props1->getContentType(), props2->getContentType()); - BOOST_CHECK_EQUAL(props1->getContentEncoding(), props2->getContentEncoding()); - BOOST_CHECK_EQUAL(props1->getUserId(), props2->getUserId()); - BOOST_CHECK_EQUAL(props1->getAppId(), props2->getAppId()); - -} - -QPID_AUTO_TEST_CASE(testDeliveryProperies) -{ - AMQFrame out((AMQHeaderBody())); - DeliveryProperties* props1 = - out.castBody<AMQHeaderBody>()->get<DeliveryProperties>(true); - - props1->setDiscardUnroutable(true); - props1->setExchange("foo"); - - char buff[10000]; - Buffer wbuffer(buff, 10000); - out.encode(wbuffer); - - Buffer rbuffer(buff, 10000); - AMQFrame in; - in.decode(rbuffer); - DeliveryProperties* props2 = - in.castBody<AMQHeaderBody>()->get<DeliveryProperties>(true); - - BOOST_CHECK(props2->getDiscardUnroutable()); - BOOST_CHECK_EQUAL(string("foo"), props2->getExchange()); - BOOST_CHECK(!props2->hasTimestamp()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/HeadersExchangeTest.cpp b/cpp/src/tests/HeadersExchangeTest.cpp deleted file mode 100644 index 40deb59c86..0000000000 --- a/cpp/src/tests/HeadersExchangeTest.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Exception.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FieldValue.h" -#include "unit_test.h" - -using namespace qpid::broker; -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(HeadersExchangeTestSuite) - -QPID_AUTO_TEST_CASE(testMatchAll) -{ - FieldTable b, m, n; - b.setString("x-match", "all"); - b.setString("foo", "FOO"); - b.setInt("n", 42); - m.setString("foo", "FOO"); - m.setInt("n", 42); - BOOST_CHECK(HeadersExchange::match(b, m)); - - // Ignore extras. - m.setString("extra", "x"); - BOOST_CHECK(HeadersExchange::match(b, m)); - - // Fail mismatch, wrong value. - m.setString("foo", "NotFoo"); - BOOST_CHECK(!HeadersExchange::match(b, m)); - - // Fail mismatch, missing value - n.setInt("n", 42); - n.setString("extra", "x"); - BOOST_CHECK(!HeadersExchange::match(b, n)); -} - -QPID_AUTO_TEST_CASE(testMatchAny) -{ - FieldTable b, m, n; - b.setString("x-match", "any"); - b.setString("foo", "FOO"); - b.setInt("n", 42); - m.setString("foo", "FOO"); - BOOST_CHECK(!HeadersExchange::match(b, n)); - BOOST_CHECK(HeadersExchange::match(b, m)); - m.setInt("n", 42); - BOOST_CHECK(HeadersExchange::match(b, m)); -} - -QPID_AUTO_TEST_CASE(testMatchEmptyValue) -{ - FieldTable b, m; - b.setString("x-match", "all"); - b.set("foo", FieldTable::ValuePtr()); - b.set("n", FieldTable::ValuePtr()); - BOOST_CHECK(!HeadersExchange::match(b, m)); - m.setString("foo", "blah"); - m.setInt("n", 123); -} - -QPID_AUTO_TEST_CASE(testMatchEmptyArgs) -{ - FieldTable b, m; - m.setString("foo", "FOO"); - - b.setString("x-match", "all"); - BOOST_CHECK(HeadersExchange::match(b, m)); - b.setString("x-match", "any"); - BOOST_CHECK(!HeadersExchange::match(b, m)); -} - - -QPID_AUTO_TEST_CASE(testMatchNoXMatch) -{ - FieldTable b, m; - b.setString("foo", "FOO"); - m.setString("foo", "FOO"); - BOOST_CHECK(!HeadersExchange::match(b, m)); -} - -QPID_AUTO_TEST_CASE(testBindNoXMatch) -{ - HeadersExchange exchange("test"); - Queue::shared_ptr queue; - std::string key; - FieldTable args; - try { - //just checking this doesn't cause assertion etc - exchange.bind(queue, key, &args); - } catch(qpid::Exception&) { - //expected - } -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/InitialStatusMap.cpp b/cpp/src/tests/InitialStatusMap.cpp deleted file mode 100644 index ecbe2d4161..0000000000 --- a/cpp/src/tests/InitialStatusMap.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/cluster/InitialStatusMap.h" -#include "qpid/framing/Uuid.h" -#include <boost/assign.hpp> - -using namespace std; -using namespace qpid::cluster; -using namespace qpid::framing; -using namespace qpid::framing::cluster; -using namespace boost::assign; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(InitialStatusMapTestSuite) - -typedef InitialStatusMap::Status Status; - -Status activeStatus(const Uuid& id=Uuid(), const MemberSet& ms=MemberSet()) { - return Status(ProtocolVersion(), 0, true, id, STORE_STATE_NO_STORE, Uuid(), - encodeMemberSet(ms)); -} - -Status newcomerStatus(const Uuid& id=Uuid(), const MemberSet& ms=MemberSet()) { - return Status(ProtocolVersion(), 0, false, id, STORE_STATE_NO_STORE, Uuid(), - encodeMemberSet(ms)); -} - -Status storeStatus(bool active, StoreState state, Uuid start=Uuid(), Uuid stop=Uuid(), - const MemberSet& ms=MemberSet()) -{ - return Status(ProtocolVersion(), 0, active, start, state, stop, - encodeMemberSet(ms)); -} - -QPID_AUTO_TEST_CASE(testFirstInCluster) { - // Single member is first in cluster. - InitialStatusMap map(MemberId(0), 1); - Uuid id(true); - BOOST_CHECK(!map.isComplete()); - MemberSet members = list_of(MemberId(0)); - map.configChange(members); - BOOST_CHECK(!map.isComplete()); - map.received(MemberId(0), newcomerStatus(id, list_of<MemberId>(0))); - BOOST_CHECK(map.isComplete()); - BOOST_CHECK(map.transitionToComplete()); - BOOST_CHECK(map.getElders().empty()); - BOOST_CHECK(!map.isUpdateNeeded()); - BOOST_CHECK_EQUAL(id, map.getClusterId()); -} - -QPID_AUTO_TEST_CASE(testJoinExistingCluster) { - // Single member 0 joins existing cluster 1,2 - InitialStatusMap map(MemberId(0), 1); - Uuid id(true); - MemberSet members = list_of(MemberId(0))(MemberId(1))(MemberId(2)); - map.configChange(members); - BOOST_CHECK(map.isResendNeeded()); - BOOST_CHECK(!map.isComplete()); - map.received(MemberId(0), newcomerStatus()); - map.received(MemberId(1), activeStatus(id)); - BOOST_CHECK(!map.isComplete()); - map.received(MemberId(2), activeStatus(id)); - BOOST_CHECK(map.isComplete()); - BOOST_CHECK(map.transitionToComplete()); - BOOST_CHECK_EQUAL(map.getElders(), list_of<MemberId>(1)(2)); - BOOST_CHECK(map.isUpdateNeeded()); - BOOST_CHECK_EQUAL(map.getClusterId(), id); - - // Check that transitionToComplete is reset. - map.configChange(list_of<MemberId>(0)(1)); - BOOST_CHECK(!map.transitionToComplete()); -} - -QPID_AUTO_TEST_CASE(testMultipleFirstInCluster) { - // Multiple members 0,1,2 join at same time. - InitialStatusMap map(MemberId(1), 1); // self is 1 - Uuid id(true); - MemberSet members = list_of(MemberId(0))(MemberId(1))(MemberId(2)); - map.configChange(members); - BOOST_CHECK(map.isResendNeeded()); - - // All new members - map.received(MemberId(0), newcomerStatus(id, list_of<MemberId>(0)(1)(2))); - map.received(MemberId(1), newcomerStatus(id, list_of<MemberId>(0)(1)(2))); - map.received(MemberId(2), newcomerStatus(id, list_of<MemberId>(0)(1)(2))); - BOOST_CHECK(!map.isResendNeeded()); - BOOST_CHECK(map.isComplete()); - BOOST_CHECK(map.transitionToComplete()); - BOOST_CHECK_EQUAL(map.getElders(), list_of(MemberId(2))); - BOOST_CHECK(!map.isUpdateNeeded()); - BOOST_CHECK_EQUAL(map.getClusterId(), id); -} - -QPID_AUTO_TEST_CASE(testMultipleJoinExisting) { - // Multiple members 2,3 join simultaneously a cluster containing 0,1. - InitialStatusMap map(MemberId(2), 1); // self is 2 - Uuid id(true); - MemberSet members = list_of(MemberId(0))(MemberId(1))(MemberId(2))(MemberId(3)); - map.configChange(members); - BOOST_CHECK(map.isResendNeeded()); - map.received(MemberId(0), activeStatus(id, list_of<MemberId>(0))); - map.received(MemberId(1), newcomerStatus(id, list_of<MemberId>(0)(1))); - map.received(MemberId(2), newcomerStatus(id, list_of<MemberId>(0)(1)(2)(3))); - map.received(MemberId(3), newcomerStatus(id, list_of<MemberId>(0)(1)(2)(3))); - BOOST_CHECK(!map.isResendNeeded()); - BOOST_CHECK(map.isComplete()); - BOOST_CHECK(map.transitionToComplete()); - BOOST_CHECK_EQUAL(map.getElders(), list_of<MemberId>(0)(1)(3)); - BOOST_CHECK(map.isUpdateNeeded()); - BOOST_CHECK_EQUAL(map.getClusterId(), id); -} - -QPID_AUTO_TEST_CASE(testMembersLeave) { - // Test that map completes if members leave rather than send status. - InitialStatusMap map(MemberId(0), 1); - Uuid id(true); - map.configChange(list_of(MemberId(0))(MemberId(1))(MemberId(2))); - map.received(MemberId(0), newcomerStatus()); - map.received(MemberId(1), activeStatus(id)); - BOOST_CHECK(!map.isComplete()); - map.configChange(list_of(MemberId(0))(MemberId(1))); // 2 left - BOOST_CHECK(map.isComplete()); - BOOST_CHECK(map.transitionToComplete()); - BOOST_CHECK_EQUAL(map.getElders(), list_of(MemberId(1))); - BOOST_CHECK_EQUAL(map.getClusterId(), id); -} - -QPID_AUTO_TEST_CASE(testInteveningConfig) { - // Multiple config changes arrives before we complete the map. - InitialStatusMap map(MemberId(0), 1); - Uuid id(true); - - map.configChange(list_of<MemberId>(0)(1)); - BOOST_CHECK(map.isResendNeeded()); - map.received(MemberId(0), newcomerStatus()); - BOOST_CHECK(!map.isComplete()); - BOOST_CHECK(!map.isResendNeeded()); - // New member 2 joins before we receive 1 - map.configChange(list_of<MemberId>(0)(1)(2)); - BOOST_CHECK(!map.isComplete()); - BOOST_CHECK(map.isResendNeeded()); - map.received(1, activeStatus(id)); - map.received(2, newcomerStatus()); - // We should not be complete as we haven't received 0 since new member joined - BOOST_CHECK(!map.isComplete()); - BOOST_CHECK(!map.isResendNeeded()); - - map.received(0, newcomerStatus()); - BOOST_CHECK(map.isComplete()); - BOOST_CHECK(map.transitionToComplete()); - BOOST_CHECK_EQUAL(map.getElders(), list_of<MemberId>(1)); - BOOST_CHECK_EQUAL(map.getClusterId(), id); -} - -QPID_AUTO_TEST_CASE(testAllCleanNoUpdate) { - InitialStatusMap map(MemberId(0), 3); - map.configChange(list_of<MemberId>(0)(1)(2)); - map.received(MemberId(0), storeStatus(false, STORE_STATE_CLEAN_STORE)); - map.received(MemberId(1), storeStatus(false, STORE_STATE_CLEAN_STORE)); - map.received(MemberId(2), storeStatus(false, STORE_STATE_CLEAN_STORE)); - BOOST_CHECK(!map.isUpdateNeeded()); -} - -QPID_AUTO_TEST_CASE(testAllEmptyNoUpdate) { - InitialStatusMap map(MemberId(0), 3); - map.configChange(list_of<MemberId>(0)(1)(2)); - map.received(MemberId(0), storeStatus(false, STORE_STATE_EMPTY_STORE)); - map.received(MemberId(1), storeStatus(false, STORE_STATE_EMPTY_STORE)); - map.received(MemberId(2), storeStatus(false, STORE_STATE_EMPTY_STORE)); - BOOST_CHECK(map.isComplete()); - BOOST_CHECK(!map.isUpdateNeeded()); -} - -QPID_AUTO_TEST_CASE(testAllNoStoreNoUpdate) { - InitialStatusMap map(MemberId(0), 3); - map.configChange(list_of<MemberId>(0)(1)(2)); - map.received(MemberId(0), storeStatus(false, STORE_STATE_NO_STORE)); - map.received(MemberId(1), storeStatus(false, STORE_STATE_NO_STORE)); - map.received(MemberId(2), storeStatus(false, STORE_STATE_NO_STORE)); - BOOST_CHECK(map.isComplete()); - BOOST_CHECK(!map.isUpdateNeeded()); -} - -QPID_AUTO_TEST_CASE(testDirtyNeedUpdate) { - InitialStatusMap map(MemberId(0), 3); - map.configChange(list_of<MemberId>(0)(1)(2)); - map.received(MemberId(0), storeStatus(false, STORE_STATE_DIRTY_STORE)); - map.received(MemberId(1), storeStatus(false, STORE_STATE_CLEAN_STORE)); - map.received(MemberId(2), storeStatus(false, STORE_STATE_CLEAN_STORE)); - BOOST_CHECK(map.transitionToComplete()); - BOOST_CHECK(map.isUpdateNeeded()); -} - -QPID_AUTO_TEST_CASE(testEmptyNeedUpdate) { - InitialStatusMap map(MemberId(0), 3); - map.configChange(list_of<MemberId>(0)(1)(2)); - map.received(MemberId(0), storeStatus(false, STORE_STATE_EMPTY_STORE)); - map.received(MemberId(1), storeStatus(false, STORE_STATE_CLEAN_STORE)); - map.received(MemberId(2), storeStatus(false, STORE_STATE_CLEAN_STORE)); - BOOST_CHECK(map.transitionToComplete()); - BOOST_CHECK(map.isUpdateNeeded()); -} - -QPID_AUTO_TEST_CASE(testEmptyAlone) { - InitialStatusMap map(MemberId(0), 1); - map.configChange(list_of<MemberId>(0)); - map.received(MemberId(0), storeStatus(false, STORE_STATE_EMPTY_STORE)); - BOOST_CHECK(map.transitionToComplete()); - BOOST_CHECK(!map.isUpdateNeeded()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/InlineAllocator.cpp b/cpp/src/tests/InlineAllocator.cpp deleted file mode 100644 index a4c4d64cea..0000000000 --- a/cpp/src/tests/InlineAllocator.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/InlineAllocator.h" -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(InlineAllocatorTestSuite) - -using namespace qpid; -using namespace std; - -QPID_AUTO_TEST_CASE(testAllocate) { - InlineAllocator<std::allocator<char>, 2> alloc; - - char* p = alloc.allocate(1); - BOOST_CHECK(p == (char*)&alloc); - alloc.deallocate(p,1); - - p = alloc.allocate(2); - BOOST_CHECK(p == (char*)&alloc); - alloc.deallocate(p,2); - - p = alloc.allocate(3); - BOOST_CHECK(p != (char*)&alloc); - alloc.deallocate(p,3); -} - -QPID_AUTO_TEST_CASE(testAllocateFull) { - InlineAllocator<std::allocator<char>, 1> alloc; - - char* p = alloc.allocate(1); - BOOST_CHECK(p == (char*)&alloc); - - char* q = alloc.allocate(1); - BOOST_CHECK(q != (char*)&alloc); - - alloc.deallocate(p,1); - p = alloc.allocate(1); - BOOST_CHECK(p == (char*)&alloc); - - alloc.deallocate(p,1); - alloc.deallocate(q,1); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/InlineVector.cpp b/cpp/src/tests/InlineVector.cpp deleted file mode 100644 index ba5165886d..0000000000 --- a/cpp/src/tests/InlineVector.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/InlineVector.h" -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(InlineVectorTestSuite) - -using namespace qpid; -using namespace std; - -typedef InlineVector<int, 3> Vec; - -bool isInline(const Vec& v) { - // If nothing, give it the benefit of the doubt; - // can't take address of nothing. - if (v.size() <= 0) - return true; - return (const char*)&v <= (const char*)(&v[0]) && - (const char*)(&v[0]) < (const char*)&v+sizeof(v); -} - -QPID_AUTO_TEST_CASE(testCtor) { - { - Vec v; - BOOST_CHECK(isInline(v)); - BOOST_CHECK(v.empty()); - } - { - Vec v(3, 42); - BOOST_CHECK(isInline(v)); - BOOST_CHECK_EQUAL(3u, v.size()); - BOOST_CHECK_EQUAL(v[0], 42); - BOOST_CHECK_EQUAL(v[2], 42); - - Vec u(v); - BOOST_CHECK(isInline(u)); - BOOST_CHECK_EQUAL(3u, u.size()); - BOOST_CHECK_EQUAL(u[0], 42); - BOOST_CHECK_EQUAL(u[2], 42); - } - - { - Vec v(4, 42); - - BOOST_CHECK_EQUAL(v.size(), 4u); - BOOST_CHECK(!isInline(v)); - Vec u(v); - BOOST_CHECK_EQUAL(u.size(), 4u); - BOOST_CHECK(!isInline(u)); - } -} - -QPID_AUTO_TEST_CASE(testInsert) { - { - Vec v; - v.push_back(1); - BOOST_CHECK_EQUAL(v.size(), 1u); - BOOST_CHECK_EQUAL(v.back(), 1); - BOOST_CHECK(isInline(v)); - - v.insert(v.begin(), 2); - BOOST_CHECK_EQUAL(v.size(), 2u); - BOOST_CHECK_EQUAL(v.back(), 1); - BOOST_CHECK(isInline(v)); - - v.push_back(3); - BOOST_CHECK(isInline(v)); - - v.push_back(4); - - BOOST_CHECK(!isInline(v)); - } - { - Vec v(3,42); - v.insert(v.begin(), 9); - BOOST_CHECK_EQUAL(v.size(), 4u); - BOOST_CHECK(!isInline(v)); - } - { - Vec v(3,42); - v.insert(v.begin()+1, 9); - BOOST_CHECK(!isInline(v)); - BOOST_CHECK_EQUAL(v.size(), 4u); - } -} - -QPID_AUTO_TEST_CASE(testAssign) { - Vec v(3,42); - Vec u; - u = v; - BOOST_CHECK(isInline(u)); - u.push_back(4); - BOOST_CHECK(!isInline(u)); - v = u; - BOOST_CHECK(!isInline(v)); -} - -QPID_AUTO_TEST_CASE(testResize) { - Vec v; - v.resize(5); - BOOST_CHECK(!isInline(v)); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am deleted file mode 100644 index ed97c41bff..0000000000 --- a/cpp/src/tests/Makefile.am +++ /dev/null @@ -1,398 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -AM_CXXFLAGS = $(WARNING_CFLAGS) -DBOOST_TEST_DYN_LINK -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src -PUBLIC_INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include # Use public API only -QMF_GEN=$(top_srcdir)/managementgen/qmf-gen - -abs_builddir=@abs_builddir@ -abs_srcdir=@abs_srcdir@ - -extra_libs = -lib_client = $(abs_builddir)/../libqpidclient.la -lib_messaging = $(abs_builddir)/../libqpidmessaging.la -lib_common = $(abs_builddir)/../libqpidcommon.la -lib_broker = $(abs_builddir)/../libqpidbroker.la -lib_console = $(abs_builddir)/../libqmfconsole.la -lib_qmf2 = $(abs_builddir)/../libqmf2.la -# lib_amqp_0_10 = $(abs_builddir)/../libqpidamqp_0_10.la - -# -# Initialize variables that are incremented with += -# -check_PROGRAMS= -check_LTLIBRARIES= -TESTS= -EXTRA_DIST= -CLEANFILES= -LONG_TESTS= -CLEAN_LOCAL= - -# -# Destination for intalled programs and tests defined here -# -qpidexecdir = $(libexecdir)/qpid -qpidexec_PROGRAMS = -qpidexec_SCRIPTS = -qpidtestdir = $(qpidexecdir)/tests -qpidtest_PROGRAMS = -qpidtest_SCRIPTS = -tmoduledir = $(libdir)/qpid/tests -tmodule_LTLIBRARIES= - -# -# Unit test program -# -# Unit tests are built as a single program to reduce valgrind overhead -# when running the tests. If you want to build a subset of the tests do -# rm -f unit_test; make unit_test unit_test_OBJECTS="unit_test.o SelectedTest.o" -# - -TESTS+=unit_test -check_PROGRAMS+=unit_test -unit_test_LDADD=-lboost_unit_test_framework \ - $(lib_messaging) $(lib_broker) $(lib_console) $(lib_qmf2) - -unit_test_SOURCES= unit_test.cpp unit_test.h \ - MessagingSessionTests.cpp \ - MessagingThreadTests.cpp \ - MessagingFixture.h \ - ClientSessionTest.cpp \ - BrokerFixture.h SocketProxy.h \ - exception_test.cpp \ - RefCounted.cpp \ - SessionState.cpp logging.cpp \ - AsyncCompletion.cpp \ - Url.cpp Uuid.cpp \ - Shlib.cpp FieldValue.cpp FieldTable.cpp Array.cpp \ - QueueOptionsTest.cpp \ - InlineAllocator.cpp \ - InlineVector.cpp \ - SequenceSet.cpp \ - StringUtils.cpp \ - RangeSet.cpp \ - AtomicValue.cpp \ - QueueTest.cpp \ - AccumulatedAckTest.cpp \ - DtxWorkRecordTest.cpp \ - DeliveryRecordTest.cpp \ - ExchangeTest.cpp \ - HeadersExchangeTest.cpp \ - MessageTest.cpp \ - QueueRegistryTest.cpp \ - QueuePolicyTest.cpp \ - QueueFlowLimitTest.cpp \ - FramingTest.cpp \ - HeaderTest.cpp \ - SequenceNumberTest.cpp \ - TimerTest.cpp \ - TopicExchangeTest.cpp \ - TxBufferTest.cpp \ - TxPublishTest.cpp \ - MessageBuilderTest.cpp \ - ConnectionOptions.h \ - ForkedBroker.h \ - ForkedBroker.cpp \ - ManagementTest.cpp \ - MessageReplayTracker.cpp \ - ConsoleTest.cpp \ - QueueEvents.cpp \ - ProxyTest.cpp \ - RetryList.cpp \ - RateFlowcontrolTest.cpp \ - FrameDecoder.cpp \ - ReplicationTest.cpp \ - ClientMessageTest.cpp \ - PollableCondition.cpp \ - Variant.cpp \ - Address.cpp \ - ClientMessage.cpp \ - Qmf2.cpp - -if HAVE_XML -unit_test_SOURCES+= XmlClientSessionTest.cpp -endif - -TESTLIBFLAGS = -module -rpath $(abs_builddir) - -check_LTLIBRARIES += libshlibtest.la -libshlibtest_la_LDFLAGS = $(TESTLIBFLAGS) -libshlibtest_la_SOURCES = shlibtest.cpp - -tmodule_LTLIBRARIES += test_store.la -test_store_la_SOURCES = test_store.cpp -test_store_la_LIBADD = $(lib_broker) -test_store_la_LDFLAGS = -module - -include cluster.mk -include sasl.mk -if SSL -include ssl.mk -endif - -# Test programs that are installed and therefore built as part of make, not make check - -qpidtest_SCRIPTS += qpid-cpp-benchmark install_env.sh -EXTRA_DIST += qpid-cpp-benchmark install_env.sh - -qpidtest_PROGRAMS += receiver -receiver_SOURCES = \ - receiver.cpp \ - TestOptions.h \ - ConnectionOptions.h -receiver_LDADD = $(lib_client) - -qpidtest_PROGRAMS += sender -sender_SOURCES = \ - sender.cpp \ - TestOptions.h \ - ConnectionOptions.h \ - Statistics.cpp -sender_LDADD = $(lib_messaging) - -qpidtest_PROGRAMS += qpid-receive -qpid_receive_SOURCES = \ - qpid-receive.cpp \ - TestOptions.h \ - ConnectionOptions.h \ - Statistics.h \ - Statistics.cpp -qpid_receive_LDADD = $(lib_messaging) - -qpidtest_PROGRAMS += qpid-send -qpid_send_SOURCES = \ - qpid-send.cpp \ - TestOptions.h \ - ConnectionOptions.h \ - Statistics.h \ - Statistics.cpp -qpid_send_LDADD = $(lib_messaging) - -qpidtest_PROGRAMS+=qpid-perftest -qpid_perftest_SOURCES=qpid-perftest.cpp test_tools.h TestOptions.h ConnectionOptions.h -qpid_perftest_INCLUDES=$(PUBLIC_INCLUDES) -qpid_perftest_LDADD=$(lib_client) - -qpidtest_PROGRAMS+=qpid-txtest -qpid_txtest_INCLUDES=$(PUBLIC_INCLUDES) -qpid_txtest_SOURCES=qpid-txtest.cpp TestOptions.h ConnectionOptions.h -qpid_txtest_LDADD=$(lib_client) - -qpidtest_PROGRAMS+=qpid-latency-test -qpid_latency_test_INCLUDES=$(PUBLIC_INCLUDES) -qpid_latency_test_SOURCES=qpid-latency-test.cpp TestOptions.h ConnectionOptions.h -qpid_latency_test_LDADD=$(lib_client) - -qpidtest_PROGRAMS+=qpid-client-test -qpid_client_test_INCLUDES=$(PUBLIC_INCLUDES) -qpid_client_test_SOURCES=qpid-client-test.cpp TestOptions.h ConnectionOptions.h -qpid_client_test_LDADD=$(lib_client) - -qpidtest_PROGRAMS+=qpid-topic-listener -qpid_topic_listener_INCLUDES=$(PUBLIC_INCLUDES) -qpid_topic_listener_SOURCES=qpid-topic-listener.cpp TestOptions.h ConnectionOptions.h -qpid_topic_listener_LDADD=$(lib_client) - -qpidtest_PROGRAMS+=qpid-topic-publisher -qpid_topic_publisher_INCLUDES=$(PUBLIC_INCLUDES) -qpid_topic_publisher_SOURCES=qpid-topic-publisher.cpp TestOptions.h ConnectionOptions.h -qpid_topic_publisher_LDADD=$(lib_client) - -qpidtest_PROGRAMS+=qpid-ping -qpid_ping_INCLUDES=$(PUBLIC_INCLUDES) -qpid_ping_SOURCES=qpid-ping.cpp test_tools.h TestOptions.h ConnectionOptions.h -qpid_ping_LDADD=$(lib_client) - -# -# Other test programs -# - -check_PROGRAMS+=echotest -echotest_INCLUDES=$(PUBLIC_INCLUDES) -echotest_SOURCES=echotest.cpp TestOptions.h ConnectionOptions.h -echotest_LDADD=$(lib_client) - -check_PROGRAMS+=publish -publish_INCLUDES=$(PUBLIC_INCLUDES) -publish_SOURCES=publish.cpp TestOptions.h ConnectionOptions.h -publish_LDADD=$(lib_client) - -check_PROGRAMS+=consume -consume_INCLUDES=$(PUBLIC_INCLUDES) -consume_SOURCES=consume.cpp TestOptions.h ConnectionOptions.h -consume_LDADD=$(lib_client) - -check_PROGRAMS+=header_test -header_test_INCLUDES=$(PUBLIC_INCLUDES) -header_test_SOURCES=header_test.cpp TestOptions.h ConnectionOptions.h -header_test_LDADD=$(lib_client) - -check_PROGRAMS+=failover_soak -failover_soak_INCLUDES=$(PUBLIC_INCLUDES) -failover_soak_SOURCES=failover_soak.cpp ForkedBroker.h ForkedBroker.cpp -failover_soak_LDADD=$(lib_client) $(lib_broker) - -check_PROGRAMS+=declare_queues -declare_queues_INCLUDES=$(PUBLIC_INCLUDES) -declare_queues_SOURCES=declare_queues.cpp -declare_queues_LDADD=$(lib_client) - -check_PROGRAMS+=replaying_sender -replaying_sender_INCLUDES=$(PUBLIC_INCLUDES) -replaying_sender_SOURCES=replaying_sender.cpp -replaying_sender_LDADD=$(lib_client) - -check_PROGRAMS+=resuming_receiver -resuming_receiver_INCLUDES=$(PUBLIC_INCLUDES) -resuming_receiver_SOURCES=resuming_receiver.cpp -resuming_receiver_LDADD=$(lib_client) - -check_PROGRAMS+=txshift -txshift_INCLUDES=$(PUBLIC_INCLUDES) -txshift_SOURCES=txshift.cpp TestOptions.h ConnectionOptions.h -txshift_LDADD=$(lib_client) - -check_PROGRAMS+=txjob -txjob_INCLUDES=$(PUBLIC_INCLUDES) -txjob_SOURCES=txjob.cpp TestOptions.h ConnectionOptions.h -txjob_LDADD=$(lib_client) - -check_PROGRAMS+=PollerTest -PollerTest_SOURCES=PollerTest.cpp -PollerTest_LDADD=$(lib_common) $(lib_client) $(SOCKLIBS) - -check_PROGRAMS+=DispatcherTest -DispatcherTest_SOURCES=DispatcherTest.cpp -DispatcherTest_LDADD=$(lib_common) $(lib_client) $(SOCKLIBS) - -check_PROGRAMS+=datagen -datagen_SOURCES=datagen.cpp -datagen_LDADD=$(lib_common) $(lib_client) - -check_PROGRAMS+=qpid-stream -qpid_stream_INCLUDES=$(PUBLIC_INCLUDES) -qpid_stream_SOURCES=qpid-stream.cpp -qpid_stream_LDADD=$(lib_messaging) - -TESTS_ENVIRONMENT = \ - VALGRIND=$(VALGRIND) \ - LIBTOOL="$(LIBTOOL)" \ - QPID_DATA_DIR= \ - $(srcdir)/run_test - -system_tests = qpid-client-test quick_perftest quick_topictest run_header_test quick_txtest -TESTS += start_broker $(system_tests) python_tests stop_broker run_federation_tests \ - run_acl_tests run_cli_tests replication_test dynamic_log_level_test \ - run_queue_flow_limit_tests - -EXTRA_DIST += \ - run_test vg_check \ - run-unit-tests start_broker python_tests stop_broker \ - quick_topictest \ - quick_perftest \ - quick_txtest \ - topictest \ - run_header_test \ - header_test.py \ - ssl_test \ - config.null \ - ais_check \ - run_federation_tests \ - run_cli_tests \ - run_acl_tests \ - .valgrind.supp \ - MessageUtils.h \ - TestMessageStore.h \ - TxMocks.h \ - replication_test \ - run_perftest \ - ring_queue_test \ - run_ring_queue_test \ - dynamic_log_level_test \ - qpid-ctrl \ - CMakeLists.txt \ - cluster.cmake \ - windows/DisableWin32ErrorWindows.cpp \ - background.ps1 \ - find_prog.ps1 \ - python_tests.ps1 \ - quick_topictest.ps1 \ - run_federation_tests.ps1 \ - run_header_test.ps1 \ - run_test.ps1 \ - start_broker.ps1 \ - stop_broker.ps1 \ - topictest.ps1 \ - run_queue_flow_limit_tests - -check_LTLIBRARIES += libdlclose_noop.la -libdlclose_noop_la_LDFLAGS = -module -rpath $(abs_builddir) -libdlclose_noop_la_SOURCES = dlclose_noop.c - -CLEANFILES+=valgrind.out *.log *.vglog* dummy_test qpidd.port $(unit_wrappers) - -# Longer running stability tests, not run by default check: target. -# Not run under valgrind, too slow - -LONG_TESTS+=start_broker fanout_perftest shared_perftest multiq_perftest topic_perftest run_ring_queue_test stop_broker \ - run_failover_soak reliable_replication_test \ - federated_cluster_test_with_node_failure - -EXTRA_DIST+= \ - fanout_perftest \ - shared_perftest \ - multiq_perftest \ - topic_perftest \ - run_failover_soak \ - reliable_replication_test \ - federated_cluster_test_with_node_failure \ - sasl_test_setup.sh - -check-long: - $(MAKE) check TESTS="$(LONG_TESTS)" VALGRIND= - -# Things that should be built before the check target runs. -check-am: python_prep test_env.sh install_env.sh sasl_config - -PYTHON_SRC_DIR=$(abs_srcdir)/../../../python -PYTHON_BLD_DIR=$(abs_builddir)/python - -# Generate python client as part of the all-am target so it gets built before tests. -all-am: python_prep - -python_prep: - if test -d $(PYTHON_SRC_DIR); \ - then cd $(PYTHON_SRC_DIR) && python $(PYTHON_SRC_DIR)/setup.py install \ - --prefix=$(PYTHON_BLD_DIR) --install-lib=$(PYTHON_BLD_DIR) \ - --install-scripts=$(PYTHON_BLD_DIR)/commands; \ - else echo "WARNING: python client not built, missing $(PYTHON_SRC_DIR)"; fi - -sasl_config: sasl_test_setup.sh - sh $(srcdir)/sasl_test_setup.sh - touch sasl_config - -CLEAN_LOCAL += sasl_config - -clean-local: - rm -rf $(CLEAN_LOCAL) - -include testagent.mk -include brokermgmt.mk - diff --git a/cpp/src/tests/ManagementTest.cpp b/cpp/src/tests/ManagementTest.cpp deleted file mode 100644 index 8944c084c0..0000000000 --- a/cpp/src/tests/ManagementTest.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/management/ManagementObject.h" -#include "qpid/framing/Buffer.h" -#include "qpid/console/ObjectId.h" -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ManagementTestSuite) - -using namespace qpid::framing; -using namespace qpid::management; - -QPID_AUTO_TEST_CASE(testObjectIdSerializeStream) { - std::string text("0-10-4-2500-80000000000()"); - std::stringstream input(text); - - ObjectId oid(input); - - std::stringstream output; - output << oid; - - BOOST_CHECK_EQUAL(text, output.str()); -} - -QPID_AUTO_TEST_CASE(testObjectIdSerializeString) { - std::string text("0-10-4-2500-80000000000()"); - - ObjectId oid(text); - - std::stringstream output; - output << oid; - - BOOST_CHECK_EQUAL(text, output.str()); -} - -QPID_AUTO_TEST_CASE(testObjectIdEncode) { - qpid::types::Variant::Map oidMap; - - ObjectId oid(1, 2, 3, 9999); - oid.setV2Key("testkey"); - oid.setAgentName("myAgent"); - - std::stringstream out1; - out1 << oid; - - BOOST_CHECK_EQUAL(out1.str(), "1-2-3-myAgent-9999(testkey)"); -} - -QPID_AUTO_TEST_CASE(testObjectIdAttach) { - AgentAttachment agent; - ObjectId oid(&agent, 10, 20); - oid.setV2Key("GabbaGabbaHey"); - oid.setAgentName("MrSmith"); - - std::stringstream out1; - out1 << oid; - - BOOST_CHECK_EQUAL(out1.str(), "10-20-0-MrSmith-0(GabbaGabbaHey)"); - - agent.setBanks(30, 40); - std::stringstream out2; - out2 << oid; - - BOOST_CHECK_EQUAL(out2.str(), "10-20-30-MrSmith-0(GabbaGabbaHey)"); -} - -QPID_AUTO_TEST_CASE(testObjectIdCreate) { - ObjectId oid("some-agent-name", "an-object-name"); - - BOOST_CHECK_EQUAL(oid.getAgentName(), "some-agent-name"); - BOOST_CHECK_EQUAL(oid.getV2Key(), "an-object-name"); -} - -QPID_AUTO_TEST_CASE(testConsoleObjectId) { - qpid::console::ObjectId oid1, oid2; - - oid1.setValue(1, 2); - oid2.setValue(3, 4); - - BOOST_CHECK(oid1 < oid2); - BOOST_CHECK(oid1 <= oid2); - BOOST_CHECK(oid2 > oid1); - BOOST_CHECK(oid2 >= oid1); - BOOST_CHECK(oid1 != oid2); - BOOST_CHECK(oid1 == oid1); - - oid1.setValue(3, 6); - oid2.setValue(3, 4); - - BOOST_CHECK(oid1 > oid2); - BOOST_CHECK(oid1 >= oid2); - BOOST_CHECK(oid2 < oid1); - BOOST_CHECK(oid2 <= oid1); - BOOST_CHECK(oid1 != oid2); - - oid2.setValue(3, 6); - BOOST_CHECK(oid1 == oid2); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/MessageBuilderTest.cpp b/cpp/src/tests/MessageBuilderTest.cpp deleted file mode 100644 index c3d40ed88a..0000000000 --- a/cpp/src/tests/MessageBuilderTest.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageBuilder.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/framing/frame_functors.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/TypeFilter.h" -#include "unit_test.h" -#include <list> - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -class MockMessageStore : public NullMessageStore -{ - enum Op {STAGE=1, APPEND=2}; - - uint64_t id; - boost::intrusive_ptr<PersistableMessage> expectedMsg; - string expectedData; - std::list<Op> ops; - - void checkExpectation(Op actual) - { - BOOST_CHECK_EQUAL(ops.front(), actual); - ops.pop_front(); - } - - public: - MockMessageStore() : id(0), expectedMsg(0) {} - - void expectStage(PersistableMessage& msg) - { - expectedMsg = &msg; - ops.push_back(STAGE); - } - - void expectAppendContent(PersistableMessage& msg, const string& data) - { - expectedMsg = &msg; - expectedData = data; - ops.push_back(APPEND); - } - - void stage(const boost::intrusive_ptr<PersistableMessage>& msg) - { - checkExpectation(STAGE); - BOOST_CHECK_EQUAL(expectedMsg, msg); - msg->setPersistenceId(++id); - } - - void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const string& data) - { - checkExpectation(APPEND); - BOOST_CHECK_EQUAL(boost::static_pointer_cast<const PersistableMessage>(expectedMsg), msg); - BOOST_CHECK_EQUAL(expectedData, data); - } - - bool expectationsMet() - { - return ops.empty(); - } - - //don't treat this store as a null impl - bool isNull() const - { - return false; - } - -}; - -QPID_AUTO_TEST_SUITE(MessageBuilderTestSuite) - -QPID_AUTO_TEST_CASE(testHeaderOnly) -{ - MessageBuilder builder(0); - builder.start(SequenceNumber()); - - std::string exchange("builder-exchange"); - std::string key("builder-exchange"); - - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange, 0, 0))); - AMQFrame header((AMQHeaderBody())); - - header.castBody<AMQHeaderBody>()->get<MessageProperties>(true)->setContentLength(0); - header.castBody<AMQHeaderBody>()->get<DeliveryProperties>(true)->setRoutingKey(key); - - builder.handle(method); - builder.handle(header); - - BOOST_CHECK(builder.getMessage()); - BOOST_CHECK_EQUAL(exchange, builder.getMessage()->getExchangeName()); - BOOST_CHECK_EQUAL(key, builder.getMessage()->getRoutingKey()); - BOOST_CHECK(builder.getMessage()->getFrames().isComplete()); -} - -QPID_AUTO_TEST_CASE(test1ContentFrame) -{ - MessageBuilder builder(0); - builder.start(SequenceNumber()); - - std::string data("abcdefg"); - std::string exchange("builder-exchange"); - std::string key("builder-exchange"); - - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange, 0, 0))); - AMQFrame header((AMQHeaderBody())); - AMQFrame content((AMQContentBody(data))); - method.setEof(false); - header.setBof(false); - header.setEof(false); - content.setBof(false); - - header.castBody<AMQHeaderBody>()->get<MessageProperties>(true)->setContentLength(data.size()); - header.castBody<AMQHeaderBody>()->get<DeliveryProperties>(true)->setRoutingKey(key); - - builder.handle(method); - BOOST_CHECK(builder.getMessage()); - BOOST_CHECK(!builder.getMessage()->getFrames().isComplete()); - - builder.handle(header); - BOOST_CHECK(builder.getMessage()); - BOOST_CHECK(!builder.getMessage()->getFrames().isComplete()); - - builder.handle(content); - BOOST_CHECK(builder.getMessage()); - BOOST_CHECK(builder.getMessage()->getFrames().isComplete()); -} - -QPID_AUTO_TEST_CASE(test2ContentFrames) -{ - MessageBuilder builder(0); - builder.start(SequenceNumber()); - - std::string data1("abcdefg"); - std::string data2("hijklmn"); - std::string exchange("builder-exchange"); - std::string key("builder-exchange"); - - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange, 0, 0))); - AMQFrame header((AMQHeaderBody())); - AMQFrame content1((AMQContentBody(data1))); - AMQFrame content2((AMQContentBody(data2))); - method.setEof(false); - header.setBof(false); - header.setEof(false); - content1.setBof(false); - content1.setEof(false); - content2.setBof(false); - - header.castBody<AMQHeaderBody>()->get<MessageProperties>(true)->setContentLength(data1.size() + data2.size()); - header.castBody<AMQHeaderBody>()->get<DeliveryProperties>(true)->setRoutingKey(key); - - builder.handle(method); - builder.handle(header); - builder.handle(content1); - BOOST_CHECK(builder.getMessage()); - BOOST_CHECK(!builder.getMessage()->getFrames().isComplete()); - - builder.handle(content2); - BOOST_CHECK(builder.getMessage()); - BOOST_CHECK(builder.getMessage()->getFrames().isComplete()); -} -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/MessageReplayTracker.cpp b/cpp/src/tests/MessageReplayTracker.cpp deleted file mode 100644 index 3d79ee53c2..0000000000 --- a/cpp/src/tests/MessageReplayTracker.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "unit_test.h" -#include "BrokerFixture.h" -#include "qpid/client/MessageReplayTracker.h" -#include "qpid/sys/Time.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(MessageReplayTrackerTests) - -using namespace qpid::client; -using namespace qpid::sys; -using std::string; - -class ReplayBufferChecker -{ - public: - - ReplayBufferChecker(uint from, uint to) : end(to), i(from) {} - - void operator()(const Message& m) - { - if (i > end) BOOST_FAIL("Extra message found: " + m.getData()); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i++)).str(), m.getData()); - } - private: - const uint end; - uint i; - -}; - -QPID_AUTO_TEST_CASE(testReplay) -{ - ProxySessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true); - - MessageReplayTracker tracker(10); - tracker.init(fix.session); - for (uint i = 0; i < 5; i++) { - Message message((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - tracker.send(message); - } - ReplayBufferChecker checker(1, 10); - tracker.foreach(checker); - - tracker.replay(fix.session); - for (uint j = 0; j < 2; j++) {//each message should have been sent twice - for (uint i = 0; i < 5; i++) { - Message m; - BOOST_CHECK(fix.subs.get(m, "my-queue", TIME_SEC)); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), m.getData()); - } - } - Message m; - BOOST_CHECK(!fix.subs.get(m, "my-queue")); -} - -QPID_AUTO_TEST_CASE(testCheckCompletion) -{ - ProxySessionFixture fix; - fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true); - - MessageReplayTracker tracker(10); - tracker.init(fix.session); - for (uint i = 0; i < 5; i++) { - Message message((boost::format("Message_%1%") % (i+1)).str(), "my-queue"); - tracker.send(message); - } - fix.session.sync();//ensures all messages are complete - tracker.checkCompletion(); - tracker.replay(fix.session); - Message received; - for (uint i = 0; i < 5; i++) { - BOOST_CHECK(fix.subs.get(received, "my-queue")); - BOOST_CHECK_EQUAL((boost::format("Message_%1%") % (i+1)).str(), received.getData()); - } - BOOST_CHECK(!fix.subs.get(received, "my-queue")); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/MessageTest.cpp b/cpp/src/tests/MessageTest.cpp deleted file mode 100644 index 7d67c92b37..0000000000 --- a/cpp/src/tests/MessageTest.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Message.h" -#include "qpid/framing/AMQP_HighestVersion.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/alloca.h" - -#include "unit_test.h" - -#include <iostream> - -using namespace qpid::broker; -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(MessageTestSuite) - -QPID_AUTO_TEST_CASE(testEncodeDecode) -{ - string exchange = "MyExchange"; - string routingKey = "MyRoutingKey"; - Uuid messageId(true); - string data1("abcdefg"); - string data2("hijklmn"); - - boost::intrusive_ptr<Message> msg(new Message()); - - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange, 0, 0))); - AMQFrame header((AMQHeaderBody())); - AMQFrame content1((AMQContentBody(data1))); - AMQFrame content2((AMQContentBody(data2))); - - msg->getFrames().append(method); - msg->getFrames().append(header); - msg->getFrames().append(content1); - msg->getFrames().append(content2); - - MessageProperties* mProps = msg->getFrames().getHeaders()->get<MessageProperties>(true); - mProps->setContentLength(data1.size() + data2.size()); - mProps->setMessageId(messageId); - FieldTable applicationHeaders; - applicationHeaders.setString("abc", "xyz"); - mProps->setApplicationHeaders(applicationHeaders); - DeliveryProperties* dProps = msg->getFrames().getHeaders()->get<DeliveryProperties>(true); - dProps->setRoutingKey(routingKey); - dProps->setDeliveryMode(PERSISTENT); - BOOST_CHECK(msg->isPersistent()); - - char* buff = static_cast<char*>(::alloca(msg->encodedSize())); - Buffer wbuffer(buff, msg->encodedSize()); - msg->encode(wbuffer); - - Buffer rbuffer(buff, msg->encodedSize()); - msg = new Message(); - msg->decodeHeader(rbuffer); - msg->decodeContent(rbuffer); - BOOST_CHECK_EQUAL(exchange, msg->getExchangeName()); - BOOST_CHECK_EQUAL(routingKey, msg->getRoutingKey()); - BOOST_CHECK_EQUAL((uint64_t) data1.size() + data2.size(), msg->contentSize()); - BOOST_CHECK_EQUAL((uint64_t) data1.size() + data2.size(), msg->getProperties<MessageProperties>()->getContentLength()); - BOOST_CHECK_EQUAL(messageId, msg->getProperties<MessageProperties>()->getMessageId()); - BOOST_CHECK_EQUAL(string("xyz"), msg->getProperties<MessageProperties>()->getApplicationHeaders().getAsString("abc")); - BOOST_CHECK_EQUAL((uint8_t) PERSISTENT, msg->getProperties<DeliveryProperties>()->getDeliveryMode()); - BOOST_CHECK(msg->isPersistent()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/MessageUtils.h b/cpp/src/tests/MessageUtils.h deleted file mode 100644 index a1b140d484..0000000000 --- a/cpp/src/tests/MessageUtils.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Message.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/Uuid.h" - -using namespace qpid; -using namespace broker; -using namespace framing; - -namespace qpid { -namespace tests { - -struct MessageUtils -{ - static boost::intrusive_ptr<Message> createMessage(const string& exchange="", const string& routingKey="", - const bool durable = false, const Uuid& messageId=Uuid(true), - uint64_t contentSize = 0) - { - boost::intrusive_ptr<broker::Message> msg(new broker::Message()); - - AMQFrame method(( MessageTransferBody(ProtocolVersion(), exchange, 0, 0))); - AMQFrame header((AMQHeaderBody())); - - msg->getFrames().append(method); - msg->getFrames().append(header); - MessageProperties* props = msg->getFrames().getHeaders()->get<MessageProperties>(true); - props->setContentLength(contentSize); - props->setMessageId(messageId); - msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setRoutingKey(routingKey); - if (durable) - msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setDeliveryMode(2); - return msg; - } - - static void addContent(boost::intrusive_ptr<Message> msg, const string& data) - { - AMQFrame content((AMQContentBody(data))); - msg->getFrames().append(content); - } -}; - -}} // namespace qpid::tests diff --git a/cpp/src/tests/MessagingFixture.h b/cpp/src/tests/MessagingFixture.h deleted file mode 100644 index 2312a87e9d..0000000000 --- a/cpp/src/tests/MessagingFixture.h +++ /dev/null @@ -1,345 +0,0 @@ -#ifndef TESTS_MESSAGINGFIXTURE_H -#define TESTS_MESSAGINGFIXTURE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "BrokerFixture.h" -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Session.h" -#include "qpid/framing/Uuid.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Session.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Message.h" -#include "qpid/types/Variant.h" - -namespace qpid { -namespace tests { - -using qpid::types::Variant; - -struct BrokerAdmin -{ - qpid::client::Connection connection; - qpid::client::Session session; - - BrokerAdmin(uint16_t port) - { - connection.open("localhost", port); - session = connection.newSession(); - } - - void createQueue(const std::string& name) - { - session.queueDeclare(qpid::client::arg::queue=name); - } - - void deleteQueue(const std::string& name) - { - session.queueDelete(qpid::client::arg::queue=name); - } - - void createExchange(const std::string& name, const std::string& type) - { - session.exchangeDeclare(qpid::client::arg::exchange=name, qpid::client::arg::type=type); - } - - void deleteExchange(const std::string& name) - { - session.exchangeDelete(qpid::client::arg::exchange=name); - } - - bool checkQueueExists(const std::string& name) - { - return session.queueQuery(name).getQueue() == name; - } - - bool checkExchangeExists(const std::string& name, std::string& type) - { - qpid::framing::ExchangeQueryResult result = session.exchangeQuery(name); - type = result.getType(); - return !result.getNotFound(); - } - - void send(qpid::client::Message& message, const std::string& exchange=std::string()) - { - session.messageTransfer(qpid::client::arg::destination=exchange, qpid::client::arg::content=message); - } - - ~BrokerAdmin() - { - session.close(); - connection.close(); - } -}; - -struct MessagingFixture : public BrokerFixture -{ - messaging::Connection connection; - messaging::Session session; - BrokerAdmin admin; - - MessagingFixture(Broker::Options opts = Broker::Options(), bool mgmtEnabled=false) : - BrokerFixture(opts, mgmtEnabled), - connection(open(broker->getPort(Broker::TCP_TRANSPORT))), - session(connection.createSession()), - admin(broker->getPort(Broker::TCP_TRANSPORT)) - { - } - - static messaging::Connection open(uint16_t port) - { - messaging::Connection connection( - (boost::format("amqp:tcp:localhost:%1%") % (port)).str()); - connection.open(); - return connection; - } - - /** Open a connection to the broker. */ - qpid::messaging::Connection newConnection() - { - qpid::messaging::Connection connection( - (boost::format("amqp:tcp:localhost:%1%") % (broker->getPort(qpid::broker::Broker::TCP_TRANSPORT))).str()); - return connection; - } - - void ping(const qpid::messaging::Address& address) - { - messaging::Receiver r = session.createReceiver(address); - messaging::Sender s = session.createSender(address); - messaging::Message out(framing::Uuid(true).str()); - s.send(out); - messaging::Message in; - BOOST_CHECK(r.fetch(in, 5*messaging::Duration::SECOND)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - r.close(); - s.close(); - } - - ~MessagingFixture() - { - session.close(); - connection.close(); - } -}; - -struct QueueFixture : MessagingFixture -{ - std::string queue; - - QueueFixture(const std::string& name = "test-queue") : queue(name) - { - admin.createQueue(queue); - } - - ~QueueFixture() - { - admin.deleteQueue(queue); - } - -}; - -struct TopicFixture : MessagingFixture -{ - std::string topic; - - TopicFixture(const std::string& name = "test-topic", const std::string& type="fanout") : topic(name) - { - admin.createExchange(topic, type); - } - - ~TopicFixture() - { - admin.deleteExchange(topic); - } - -}; - -struct MultiQueueFixture : MessagingFixture -{ - typedef std::vector<std::string>::const_iterator const_iterator; - std::vector<std::string> queues; - - MultiQueueFixture(const std::vector<std::string>& names = boost::assign::list_of<std::string>("q1")("q2")("q3")) : queues(names) - { - for (const_iterator i = queues.begin(); i != queues.end(); ++i) { - admin.createQueue(*i); - } - } - - ~MultiQueueFixture() - { - connection.close(); - for (const_iterator i = queues.begin(); i != queues.end(); ++i) { - admin.deleteQueue(*i); - } - } - -}; - -inline std::vector<std::string> fetch(messaging::Receiver& receiver, int count, messaging::Duration timeout=messaging::Duration::SECOND*5) -{ - std::vector<std::string> data; - messaging::Message message; - for (int i = 0; i < count && receiver.fetch(message, timeout); i++) { - data.push_back(message.getContent()); - } - return data; -} - - -inline void send(messaging::Sender& sender, uint count = 1, uint start = 1, - const std::string& base = "Message") -{ - for (uint i = start; i < start + count; ++i) { - sender.send(messaging::Message((boost::format("%1%_%2%") % base % i).str())); - } -} - -inline void receive(messaging::Receiver& receiver, uint count = 1, uint start = 1, - const std::string& base = "Message", - messaging::Duration timeout=messaging::Duration::SECOND*5) -{ - for (uint i = start; i < start + count; ++i) { - BOOST_CHECK_EQUAL(receiver.fetch(timeout).getContent(), (boost::format("%1%_%2%") % base % i).str()); - } -} - - -class MethodInvoker -{ - public: - MethodInvoker(messaging::Session& session) : replyTo("#; {create:always, node:{x-declare:{auto-delete:true}}}"), - sender(session.createSender("qmf.default.direct/broker")), - receiver(session.createReceiver(replyTo)) {} - - void createExchange(const std::string& name, const std::string& type, bool durable=false) - { - Variant::Map params; - params["name"]=name; - params["type"]="exchange"; - params["properties"] = Variant::Map(); - params["properties"].asMap()["exchange-type"] = type; - params["properties"].asMap()["durable"] = durable; - methodRequest("create", params); - } - - void deleteExchange(const std::string& name) - { - Variant::Map params; - params["name"]=name; - params["type"]="exchange"; - methodRequest("delete", params); - } - - void createQueue(const std::string& name, bool durable=false, bool autodelete=false, - const Variant::Map& options=Variant::Map()) - { - Variant::Map params; - params["name"]=name; - params["type"]="queue"; - params["properties"] = options; - params["properties"].asMap()["durable"] = durable; - params["properties"].asMap()["auto-delete"] = autodelete; - methodRequest("create", params); - } - - void deleteQueue(const std::string& name) - { - Variant::Map params; - params["name"]=name; - params["type"]="queue"; - methodRequest("delete", params); - } - - void bind(const std::string& exchange, const std::string& queue, const std::string& key, - const Variant::Map& options=Variant::Map()) - { - Variant::Map params; - params["name"]=(boost::format("%1%/%2%/%3%") % (exchange) % (queue) % (key)).str(); - params["type"]="binding"; - params["properties"] = options; - methodRequest("create", params); - } - - void unbind(const std::string& exchange, const std::string& queue, const std::string& key) - { - Variant::Map params; - params["name"]=(boost::format("%1%/%2%/%3%") % (exchange) % (queue) % (key)).str(); - params["type"]="binding"; - methodRequest("delete", params); - } - - void methodRequest(const std::string& method, const Variant::Map& inParams, Variant::Map* outParams = 0) - { - Variant::Map content; - Variant::Map objectId; - objectId["_object_name"] = "org.apache.qpid.broker:broker:amqp-broker"; - content["_object_id"] = objectId; - content["_method_name"] = method; - content["_arguments"] = inParams; - - messaging::Message request; - request.setReplyTo(replyTo); - request.getProperties()["x-amqp-0-10.app-id"] = "qmf2"; - request.getProperties()["qmf.opcode"] = "_method_request"; - encode(content, request); - - sender.send(request); - - messaging::Message response; - if (receiver.fetch(response, messaging::Duration::SECOND*5)) { - if (response.getProperties()["x-amqp-0-10.app-id"] == "qmf2") { - std::string opcode = response.getProperties()["qmf.opcode"]; - if (opcode == "_method_response") { - if (outParams) { - Variant::Map m; - decode(response, m); - *outParams = m["_arguments"].asMap(); - } - } else if (opcode == "_exception") { - Variant::Map m; - decode(response, m); - throw Exception(QPID_MSG("Error: " << m["_values"])); - } else { - throw Exception(QPID_MSG("Invalid response received, unexpected opcode: " << opcode)); - } - } else { - throw Exception(QPID_MSG("Invalid response received, not a qmfv2 message: app-id=" - << response.getProperties()["x-amqp-0-10.app-id"])); - } - } else { - throw Exception(QPID_MSG("No response received")); - } - } - private: - messaging::Address replyTo; - messaging::Sender sender; - messaging::Receiver receiver; -}; - -}} // namespace qpid::tests - -#endif /*!TESTS_MESSAGINGFIXTURE_H*/ diff --git a/cpp/src/tests/MessagingSessionTests.cpp b/cpp/src/tests/MessagingSessionTests.cpp deleted file mode 100644 index 6aa4c63ed7..0000000000 --- a/cpp/src/tests/MessagingSessionTests.cpp +++ /dev/null @@ -1,997 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "MessagingFixture.h" -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/messaging/Address.h" -#include "qpid/messaging/Connection.h" -#include "qpid/messaging/Message.h" -#include "qpid/messaging/Receiver.h" -#include "qpid/messaging/Sender.h" -#include "qpid/messaging/Session.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Session.h" -#include "qpid/framing/ExchangeQueryResult.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/Time.h" -#include <boost/assign.hpp> -#include <boost/format.hpp> -#include <string> -#include <vector> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(MessagingSessionTests) - -using namespace qpid::messaging; -using namespace qpid::types; -using namespace qpid; -using qpid::broker::Broker; -using qpid::framing::Uuid; - - -QPID_AUTO_TEST_CASE(testSimpleSendReceive) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - out.setSubject("test-subject"); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::SECOND * 5); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - BOOST_CHECK_EQUAL(in.getSubject(), out.getSubject()); -} - -QPID_AUTO_TEST_CASE(testSyncSendReceive) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - sender.send(out, true); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::IMMEDIATE); - fix.session.acknowledge(true); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); -} - -QPID_AUTO_TEST_CASE(testSendReceiveHeaders) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - for (uint i = 0; i < 10; ++i) { - out.getProperties()["a"] = i; - out.setProperty("b", i + 100); - sender.send(out); - } - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in; - for (uint i = 0; i < 10; ++i) { - BOOST_CHECK(receiver.fetch(in, Duration::SECOND * 5)); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - BOOST_CHECK_EQUAL(in.getProperties()["a"].asUint32(), i); - BOOST_CHECK_EQUAL(in.getProperties()["b"].asUint32(), i + 100); - fix.session.acknowledge(); - } -} - -QPID_AUTO_TEST_CASE(testSenderError) -{ - MessagingFixture fix; - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(fix.session.createSender("NonExistentAddress"), qpid::messaging::NotFound); - fix.session = fix.connection.createSession(); - BOOST_CHECK_THROW(fix.session.createSender("NonExistentAddress; {create:receiver}"), - qpid::messaging::NotFound); -} - -QPID_AUTO_TEST_CASE(testReceiverError) -{ - MessagingFixture fix; - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(fix.session.createReceiver("NonExistentAddress"), qpid::messaging::NotFound); - fix.session = fix.connection.createSession(); - BOOST_CHECK_THROW(fix.session.createReceiver("NonExistentAddress; {create:sender}"), - qpid::messaging::NotFound); -} - -QPID_AUTO_TEST_CASE(testSimpleTopic) -{ - TopicFixture fix; - - Sender sender = fix.session.createSender(fix.topic); - Message msg("one"); - sender.send(msg); - Receiver sub1 = fix.session.createReceiver(fix.topic); - sub1.setCapacity(10u); - msg.setContent("two"); - sender.send(msg); - Receiver sub2 = fix.session.createReceiver(fix.topic); - sub2.setCapacity(10u); - msg.setContent("three"); - sender.send(msg); - Receiver sub3 = fix.session.createReceiver(fix.topic); - sub3.setCapacity(10u); - msg.setContent("four"); - sender.send(msg); - BOOST_CHECK_EQUAL(fetch(sub2, 2), boost::assign::list_of<std::string>("three")("four")); - sub2.close(); - - msg.setContent("five"); - sender.send(msg); - BOOST_CHECK_EQUAL(fetch(sub1, 4), boost::assign::list_of<std::string>("two")("three")("four")("five")); - BOOST_CHECK_EQUAL(fetch(sub3, 2), boost::assign::list_of<std::string>("four")("five")); - Message in; - BOOST_CHECK(!sub2.fetch(in, Duration::IMMEDIATE));//TODO: or should this raise an error? - - - //TODO: check pending messages... -} - -QPID_AUTO_TEST_CASE(testNextReceiver) -{ - MultiQueueFixture fix; - - for (uint i = 0; i < fix.queues.size(); i++) { - Receiver r = fix.session.createReceiver(fix.queues[i]); - r.setCapacity(10u); - } - - for (uint i = 0; i < fix.queues.size(); i++) { - Sender s = fix.session.createSender(fix.queues[i]); - Message msg((boost::format("Message_%1%") % (i+1)).str()); - s.send(msg); - } - - for (uint i = 0; i < fix.queues.size(); i++) { - Message msg; - BOOST_CHECK(fix.session.nextReceiver().fetch(msg, Duration::SECOND)); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1)).str()); - } -} - -QPID_AUTO_TEST_CASE(testMapMessage) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out; - Variant::Map content; - content["abc"] = "def"; - content["pi"] = 3.14f; - Variant utf8("A utf 8 string"); - utf8.setEncoding("utf8"); - content["utf8"] = utf8; - Variant utf16("\x00\x61\x00\x62\x00\x63"); - utf16.setEncoding("utf16"); - content["utf16"] = utf16; - encode(content, out); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - Variant::Map view; - decode(in, view); - BOOST_CHECK_EQUAL(view["abc"].asString(), "def"); - BOOST_CHECK_EQUAL(view["pi"].asFloat(), 3.14f); - BOOST_CHECK_EQUAL(view["utf8"].asString(), utf8.asString()); - BOOST_CHECK_EQUAL(view["utf8"].getEncoding(), utf8.getEncoding()); - BOOST_CHECK_EQUAL(view["utf16"].asString(), utf16.asString()); - BOOST_CHECK_EQUAL(view["utf16"].getEncoding(), utf16.getEncoding()); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testMapMessageWithInitial) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out; - Variant::Map imap; - imap["abc"] = "def"; - imap["pi"] = 3.14f; - encode(imap, out); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - Variant::Map view; - decode(in, view); - BOOST_CHECK_EQUAL(view["abc"].asString(), "def"); - BOOST_CHECK_EQUAL(view["pi"].asFloat(), 3.14f); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testListMessage) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out; - Variant::List content; - content.push_back(Variant("abc")); - content.push_back(Variant(1234)); - content.push_back(Variant("def")); - content.push_back(Variant(56.789)); - encode(content, out); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - Variant::List view; - decode(in, view); - BOOST_CHECK_EQUAL(view.size(), content.size()); - BOOST_CHECK_EQUAL(view.front().asString(), "abc"); - BOOST_CHECK_EQUAL(view.back().asDouble(), 56.789); - - Variant::List::const_iterator i = view.begin(); - BOOST_CHECK(i != view.end()); - BOOST_CHECK_EQUAL(i->asString(), "abc"); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asInt64(), 1234); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asString(), "def"); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asDouble(), 56.789); - BOOST_CHECK(++i == view.end()); - - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testListMessageWithInitial) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out; - Variant::List ilist; - ilist.push_back(Variant("abc")); - ilist.push_back(Variant(1234)); - ilist.push_back(Variant("def")); - ilist.push_back(Variant(56.789)); - encode(ilist, out); - sender.send(out); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - Variant::List view; - decode(in, view); - BOOST_CHECK_EQUAL(view.size(), ilist.size()); - BOOST_CHECK_EQUAL(view.front().asString(), "abc"); - BOOST_CHECK_EQUAL(view.back().asDouble(), 56.789); - - Variant::List::const_iterator i = view.begin(); - BOOST_CHECK(i != view.end()); - BOOST_CHECK_EQUAL(i->asString(), "abc"); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asInt64(), 1234); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asString(), "def"); - BOOST_CHECK(++i != view.end()); - BOOST_CHECK_EQUAL(i->asDouble(), 56.789); - BOOST_CHECK(++i == view.end()); - - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testReject) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message m1("reject-me"); - sender.send(m1); - Message m2("accept-me"); - sender.send(m2); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(5 * Duration::SECOND); - BOOST_CHECK_EQUAL(in.getContent(), m1.getContent()); - fix.session.reject(in); - in = receiver.fetch(5 * Duration::SECOND); - BOOST_CHECK_EQUAL(in.getContent(), m2.getContent()); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testAvailable) -{ - MultiQueueFixture fix; - - Receiver r1 = fix.session.createReceiver(fix.queues[0]); - r1.setCapacity(100); - - Receiver r2 = fix.session.createReceiver(fix.queues[1]); - r2.setCapacity(100); - - Sender s1 = fix.session.createSender(fix.queues[0]); - Sender s2 = fix.session.createSender(fix.queues[1]); - - for (uint i = 0; i < 10; ++i) { - s1.send(Message((boost::format("A_%1%") % (i+1)).str())); - } - for (uint i = 0; i < 5; ++i) { - s2.send(Message((boost::format("B_%1%") % (i+1)).str())); - } - qpid::sys::sleep(1);//is there any avoid an arbitrary sleep while waiting for messages to be dispatched? - for (uint i = 0; i < 5; ++i) { - BOOST_CHECK_EQUAL(fix.session.getReceivable(), 15u - 2*i); - BOOST_CHECK_EQUAL(r1.getAvailable(), 10u - i); - BOOST_CHECK_EQUAL(r1.fetch().getContent(), (boost::format("A_%1%") % (i+1)).str()); - BOOST_CHECK_EQUAL(r2.getAvailable(), 5u - i); - BOOST_CHECK_EQUAL(r2.fetch().getContent(), (boost::format("B_%1%") % (i+1)).str()); - fix.session.acknowledge(); - } - for (uint i = 5; i < 10; ++i) { - BOOST_CHECK_EQUAL(fix.session.getReceivable(), 10u - i); - BOOST_CHECK_EQUAL(r1.getAvailable(), 10u - i); - BOOST_CHECK_EQUAL(r1.fetch().getContent(), (boost::format("A_%1%") % (i+1)).str()); - } -} - -QPID_AUTO_TEST_CASE(testUnsettledAcks) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - for (uint i = 0; i < 10; ++i) { - sender.send(Message((boost::format("Message_%1%") % (i+1)).str())); - } - Receiver receiver = fix.session.createReceiver(fix.queue); - for (uint i = 0; i < 10; ++i) { - BOOST_CHECK_EQUAL(receiver.fetch().getContent(), (boost::format("Message_%1%") % (i+1)).str()); - } - BOOST_CHECK_EQUAL(fix.session.getUnsettledAcks(), 0u); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(fix.session.getUnsettledAcks(), 10u); - fix.session.sync(); - BOOST_CHECK_EQUAL(fix.session.getUnsettledAcks(), 0u); -} - -QPID_AUTO_TEST_CASE(testUnsettledSend) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - send(sender, 10); - //Note: this test relies on 'inside knowledge' of the sender - //implementation and the fact that the simple test case makes it - //possible to predict when completion information will be sent to - //the client. TODO: is there a better way of testing this? - BOOST_CHECK_EQUAL(sender.getUnsettled(), 10u); - fix.session.sync(); - BOOST_CHECK_EQUAL(sender.getUnsettled(), 0u); - - Receiver receiver = fix.session.createReceiver(fix.queue); - receive(receiver, 10); - fix.session.acknowledge(); -} - -QPID_AUTO_TEST_CASE(testBrowse) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - send(sender, 10); - Receiver browser1 = fix.session.createReceiver(fix.queue + "; {mode:browse}"); - receive(browser1, 10); - Receiver browser2 = fix.session.createReceiver(fix.queue + "; {mode:browse}"); - receive(browser2, 10); - Receiver consumer = fix.session.createReceiver(fix.queue); - receive(consumer, 10); - fix.session.acknowledge(); -} - -struct QueueCreatePolicyFixture : public MessagingFixture -{ - qpid::messaging::Address address; - - QueueCreatePolicyFixture(const std::string& a) : address(a) {} - - void test() - { - ping(address); - BOOST_CHECK(admin.checkQueueExists(address.getName())); - } - - ~QueueCreatePolicyFixture() - { - admin.deleteQueue(address.getName()); - } -}; - -QPID_AUTO_TEST_CASE(testCreatePolicyQueueAlways) -{ - QueueCreatePolicyFixture fix("#; {create:always, node:{type:queue}}"); - fix.test(); -} - -QPID_AUTO_TEST_CASE(testCreatePolicyQueueReceiver) -{ - QueueCreatePolicyFixture fix("#; {create:receiver, node:{type:queue}}"); - Receiver r = fix.session.createReceiver(fix.address); - fix.test(); - r.close(); -} - -QPID_AUTO_TEST_CASE(testCreatePolicyQueueSender) -{ - QueueCreatePolicyFixture fix("#; {create:sender, node:{type:queue}}"); - Sender s = fix.session.createSender(fix.address); - fix.test(); - s.close(); -} - -struct ExchangeCreatePolicyFixture : public MessagingFixture -{ - qpid::messaging::Address address; - const std::string exchangeType; - - ExchangeCreatePolicyFixture(const std::string& a, const std::string& t) : - address(a), exchangeType(t) {} - - void test() - { - ping(address); - std::string actualType; - BOOST_CHECK(admin.checkExchangeExists(address.getName(), actualType)); - BOOST_CHECK_EQUAL(exchangeType, actualType); - } - - ~ExchangeCreatePolicyFixture() - { - admin.deleteExchange(address.getName()); - } -}; - -QPID_AUTO_TEST_CASE(testCreatePolicyTopic) -{ - ExchangeCreatePolicyFixture fix("#; {create:always, node:{type:topic}}", - "topic"); - fix.test(); -} - -QPID_AUTO_TEST_CASE(testCreatePolicyTopicReceiverFanout) -{ - ExchangeCreatePolicyFixture fix("#/my-subject; {create:receiver, node:{type:topic, x-declare:{type:fanout}}}", "fanout"); - Receiver r = fix.session.createReceiver(fix.address); - fix.test(); - r.close(); -} - -QPID_AUTO_TEST_CASE(testCreatePolicyTopicSenderDirect) -{ - ExchangeCreatePolicyFixture fix("#/my-subject; {create:sender, node:{type:topic, x-declare:{type:direct}}}", "direct"); - Sender s = fix.session.createSender(fix.address); - fix.test(); - s.close(); -} - -struct DeletePolicyFixture : public MessagingFixture -{ - enum Mode {RECEIVER, SENDER, ALWAYS, NEVER}; - - std::string getPolicy(Mode mode) - { - switch (mode) { - case SENDER: - return "{delete:sender}"; - case RECEIVER: - return "{delete:receiver}"; - case ALWAYS: - return "{delete:always}"; - case NEVER: - return "{delete:never}"; - } - return ""; - } - - void testAll() - { - test(RECEIVER); - test(SENDER); - test(ALWAYS); - test(NEVER); - } - - virtual ~DeletePolicyFixture() {} - virtual void create(const qpid::messaging::Address&) = 0; - virtual void destroy(const qpid::messaging::Address&) = 0; - virtual bool exists(const qpid::messaging::Address&) = 0; - - void test(Mode mode) - { - qpid::messaging::Address address("#; " + getPolicy(mode)); - create(address); - - Sender s = session.createSender(address); - Receiver r = session.createReceiver(address); - switch (mode) { - case RECEIVER: - s.close(); - BOOST_CHECK(exists(address)); - r.close(); - BOOST_CHECK(!exists(address)); - break; - case SENDER: - r.close(); - BOOST_CHECK(exists(address)); - s.close(); - BOOST_CHECK(!exists(address)); - break; - case ALWAYS: - s.close(); - BOOST_CHECK(!exists(address)); - break; - case NEVER: - r.close(); - BOOST_CHECK(exists(address)); - s.close(); - BOOST_CHECK(exists(address)); - destroy(address); - } - } -}; - -struct QueueDeletePolicyFixture : DeletePolicyFixture -{ - void create(const qpid::messaging::Address& address) - { - admin.createQueue(address.getName()); - } - void destroy(const qpid::messaging::Address& address) - { - admin.deleteQueue(address.getName()); - } - bool exists(const qpid::messaging::Address& address) - { - return admin.checkQueueExists(address.getName()); - } -}; - -struct ExchangeDeletePolicyFixture : DeletePolicyFixture -{ - const std::string exchangeType; - ExchangeDeletePolicyFixture(const std::string type = "topic") : exchangeType(type) {} - - void create(const qpid::messaging::Address& address) - { - admin.createExchange(address.getName(), exchangeType); - } - void destroy(const qpid::messaging::Address& address) - { - admin.deleteExchange(address.getName()); - } - bool exists(const qpid::messaging::Address& address) - { - std::string actualType; - return admin.checkExchangeExists(address.getName(), actualType) && actualType == exchangeType; - } -}; - -QPID_AUTO_TEST_CASE(testDeletePolicyQueue) -{ - QueueDeletePolicyFixture fix; - fix.testAll(); -} - -QPID_AUTO_TEST_CASE(testDeletePolicyExchange) -{ - ExchangeDeletePolicyFixture fix; - fix.testAll(); -} - -QPID_AUTO_TEST_CASE(testAssertPolicyQueue) -{ - MessagingFixture fix; - std::string a1 = "q; {create:always, assert:always, node:{type:queue, durable:false, x-declare:{arguments:{qpid.max-count:100}}}}"; - Sender s1 = fix.session.createSender(a1); - s1.close(); - Receiver r1 = fix.session.createReceiver(a1); - r1.close(); - - std::string a2 = "q; {assert:receiver, node:{durable:true, x-declare:{arguments:{qpid.max-count:100}}}}"; - Sender s2 = fix.session.createSender(a2); - s2.close(); - BOOST_CHECK_THROW(fix.session.createReceiver(a2), qpid::messaging::AssertionFailed); - - std::string a3 = "q; {assert:sender, node:{x-declare:{arguments:{qpid.max-count:99}}}}"; - BOOST_CHECK_THROW(fix.session.createSender(a3), qpid::messaging::AssertionFailed); - Receiver r3 = fix.session.createReceiver(a3); - r3.close(); - - fix.admin.deleteQueue("q"); -} - -QPID_AUTO_TEST_CASE(testGetSender) -{ - QueueFixture fix; - std::string name = fix.session.createSender(fix.queue).getName(); - Sender sender = fix.session.getSender(name); - BOOST_CHECK_EQUAL(name, sender.getName()); - Message out(Uuid(true).str()); - sender.send(out); - Message in; - BOOST_CHECK(fix.session.createReceiver(fix.queue).fetch(in)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - BOOST_CHECK_THROW(fix.session.getSender("UnknownSender"), qpid::messaging::KeyError); -} - -QPID_AUTO_TEST_CASE(testGetReceiver) -{ - QueueFixture fix; - std::string name = fix.session.createReceiver(fix.queue).getName(); - Receiver receiver = fix.session.getReceiver(name); - BOOST_CHECK_EQUAL(name, receiver.getName()); - Message out(Uuid(true).str()); - fix.session.createSender(fix.queue).send(out); - Message in; - BOOST_CHECK(receiver.fetch(in)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - BOOST_CHECK_THROW(fix.session.getReceiver("UnknownReceiver"), qpid::messaging::KeyError); -} - -QPID_AUTO_TEST_CASE(testGetSessionFromConnection) -{ - QueueFixture fix; - fix.connection.createSession("my-session"); - Session session = fix.connection.getSession("my-session"); - Message out(Uuid(true).str()); - session.createSender(fix.queue).send(out); - Message in; - BOOST_CHECK(session.createReceiver(fix.queue).fetch(in)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - BOOST_CHECK_THROW(fix.connection.getSession("UnknownSession"), qpid::messaging::KeyError); -} - -QPID_AUTO_TEST_CASE(testGetConnectionFromSession) -{ - QueueFixture fix; - Message out(Uuid(true).str()); - Sender sender = fix.session.createSender(fix.queue); - sender.send(out); - Message in; - sender.getSession().getConnection().createSession("incoming"); - BOOST_CHECK(fix.connection.getSession("incoming").createReceiver(fix.queue).fetch(in)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); -} - -QPID_AUTO_TEST_CASE(testTx) -{ - QueueFixture fix; - Session ssn1 = fix.connection.createTransactionalSession(); - Session ssn2 = fix.connection.createTransactionalSession(); - Sender sender1 = ssn1.createSender(fix.queue); - Sender sender2 = ssn2.createSender(fix.queue); - Receiver receiver1 = ssn1.createReceiver(fix.queue); - Receiver receiver2 = ssn2.createReceiver(fix.queue); - Message in; - - send(sender1, 5, 1, "A"); - send(sender2, 5, 1, "B"); - ssn2.commit(); - receive(receiver1, 5, 1, "B");//(only those from sender2 should be received) - BOOST_CHECK(!receiver1.fetch(in, Duration::IMMEDIATE));//check there are no more messages - ssn1.rollback(); - receive(receiver2, 5, 1, "B"); - BOOST_CHECK(!receiver2.fetch(in, Duration::IMMEDIATE));//check there are no more messages - ssn2.rollback(); - receive(receiver1, 5, 1, "B"); - BOOST_CHECK(!receiver1.fetch(in, Duration::IMMEDIATE));//check there are no more messages - ssn1.commit(); - //check neither receiver gets any more messages: - BOOST_CHECK(!receiver1.fetch(in, Duration::IMMEDIATE)); - BOOST_CHECK(!receiver2.fetch(in, Duration::IMMEDIATE)); -} - -QPID_AUTO_TEST_CASE(testRelease) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - sender.send(out, true); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message m1 = receiver.fetch(Duration::IMMEDIATE); - fix.session.release(m1); - Message m2 = receiver.fetch(Duration::SECOND * 1); - BOOST_CHECK_EQUAL(m1.getContent(), out.getContent()); - BOOST_CHECK_EQUAL(m1.getContent(), m2.getContent()); - fix.session.acknowledge(true); -} - -QPID_AUTO_TEST_CASE(testOptionVerification) -{ - MessagingFixture fix; - fix.session.createReceiver("my-queue; {create: always, assert: always, delete: always, node: {type: queue, durable: false, x-declare: {arguments: {a: b}}, x-bindings: [{exchange: amq.fanout}]}, link: {name: abc, durable: false, reliability: exactly-once, x-subscribe: {arguments:{a:b}}, x-bindings:[{exchange: amq.fanout}]}, mode: browse}"); - BOOST_CHECK_THROW(fix.session.createReceiver("my-queue; {invalid-option:blah}"), qpid::messaging::AddressError); -} - -QPID_AUTO_TEST_CASE(testReceiveSpecialProperties) -{ - QueueFixture fix; - - qpid::client::Message out; - out.getDeliveryProperties().setRoutingKey(fix.queue); - out.getMessageProperties().setAppId("my-app-id"); - out.getMessageProperties().setMessageId(qpid::framing::Uuid(true)); - out.getMessageProperties().setContentEncoding("my-content-encoding"); - fix.admin.send(out); - - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::SECOND * 5); - BOOST_CHECK_EQUAL(in.getProperties()["x-amqp-0-10.routing-key"].asString(), out.getDeliveryProperties().getRoutingKey()); - BOOST_CHECK_EQUAL(in.getProperties()["x-amqp-0-10.app-id"].asString(), out.getMessageProperties().getAppId()); - BOOST_CHECK_EQUAL(in.getProperties()["x-amqp-0-10.content-encoding"].asString(), out.getMessageProperties().getContentEncoding()); - BOOST_CHECK_EQUAL(in.getMessageId(), out.getMessageProperties().getMessageId().str()); - fix.session.acknowledge(true); -} - -QPID_AUTO_TEST_CASE(testSendSpecialProperties) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("test-message"); - std::string appId = "my-app-id"; - std::string contentEncoding = "my-content-encoding"; - out.getProperties()["x-amqp-0-10.app-id"] = appId; - out.getProperties()["x-amqp-0-10.content-encoding"] = contentEncoding; - out.setMessageId(qpid::framing::Uuid(true).str()); - sender.send(out, true); - - qpid::client::LocalQueue q; - qpid::client::SubscriptionManager subs(fix.admin.session); - qpid::client::Subscription s = subs.subscribe(q, fix.queue); - qpid::client::Message in = q.get(); - s.cancel(); - fix.admin.session.sync(); - - BOOST_CHECK_EQUAL(in.getMessageProperties().getAppId(), appId); - BOOST_CHECK_EQUAL(in.getMessageProperties().getContentEncoding(), contentEncoding); - BOOST_CHECK_EQUAL(in.getMessageProperties().getMessageId().str(), out.getMessageId()); -} - -QPID_AUTO_TEST_CASE(testExclusiveSubscriber) -{ - QueueFixture fix; - std::string address = (boost::format("%1%; { link: { x-subscribe : { exclusive:true } } }") % fix.queue).str(); - Receiver receiver = fix.session.createReceiver(address); - ScopedSuppressLogging sl; - try { - fix.session.createReceiver(address); - fix.session.sync(); - BOOST_FAIL("Expected exception."); - } catch (const MessagingException& /*e*/) {} -} - - -QPID_AUTO_TEST_CASE(testExclusiveQueueSubscriberAndBrowser) -{ - MessagingFixture fix; - - std::string address = "exclusive-queue; { create: receiver, node : { x-declare : { auto-delete: true, exclusive: true } } }"; - std::string browseAddress = "exclusive-queue; { mode: browse }"; - - Receiver receiver = fix.session.createReceiver(address); - fix.session.sync(); - - Connection c2 = fix.newConnection(); - c2.open(); - Session s2 = c2.createSession(); - - BOOST_CHECK_NO_THROW(Receiver browser = s2.createReceiver(browseAddress)); - c2.close(); -} - - -QPID_AUTO_TEST_CASE(testDeleteQueueWithUnackedMessages) -{ - MessagingFixture fix; - const uint capacity = 5; - - Sender sender = fix.session.createSender("test.ex;{create:always,node:{type:topic}}"); - Receiver receiver2 = fix.session.createReceiver("alternate.ex;{create:always,node:{type:topic}}"); - Receiver receiver1 = fix.session.createReceiver("test.q;{create:always, delete:always,node:{type:queue, x-declare:{alternate-exchange:alternate.ex}},link:{x-bindings:[{exchange:test.ex,queue:test.q,key:#}]}}"); - - receiver1.setCapacity(capacity); - receiver2.setCapacity(capacity*2); - - Message out("test-message"); - for (uint i = 0; i < capacity*2; ++i) { - sender.send(out); - } - - receiver1.close(); - - // Make sure all pending messages were sent to the alternate - // exchange when the queue was deleted. - Message in; - for (uint i = 0; i < capacity*2; ++i) { - in = receiver2.fetch(Duration::SECOND * 5); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - } -} - -QPID_AUTO_TEST_CASE(testAuthenticatedUsername) -{ - MessagingFixture fix; - Connection connection = fix.newConnection(); - connection.setOption("sasl-mechanism", "PLAIN"); - connection.setOption("username", "test-user"); - connection.setOption("password", "ignored"); - connection.open(); - BOOST_CHECK_EQUAL(connection.getAuthenticatedUsername(), std::string("test-user")); -} - -QPID_AUTO_TEST_CASE(testExceptionOnClosedConnection) -{ - MessagingFixture fix; - fix.connection.close(); - BOOST_CHECK_THROW(fix.connection.createSession(), MessagingException); - Connection connection("blah"); - BOOST_CHECK_THROW(connection.createSession(), MessagingException); -} - -QPID_AUTO_TEST_CASE(testAcknowledge) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - const uint count(20); - for (uint i = 0; i < count; ++i) { - sender.send(Message((boost::format("Message_%1%") % (i+1)).str())); - } - - Session other = fix.connection.createSession(); - Receiver receiver = other.createReceiver(fix.queue); - std::vector<Message> messages; - for (uint i = 0; i < count; ++i) { - Message msg = receiver.fetch(); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1)).str()); - messages.push_back(msg); - } - const uint batch(10); //acknowledge first 10 messages only - for (uint i = 0; i < batch; ++i) { - other.acknowledge(messages[i]); - } - messages.clear(); - other.sync(); - other.close(); - - other = fix.connection.createSession(); - receiver = other.createReceiver(fix.queue); - for (uint i = 0; i < (count-batch); ++i) { - Message msg = receiver.fetch(); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1+batch)).str()); - if (i % 2) other.acknowledge(msg); //acknowledge every other message - } - other.sync(); - other.close(); - - //check unacknowledged messages are still enqueued - other = fix.connection.createSession(); - receiver = other.createReceiver(fix.queue); - for (uint i = 0; i < ((count-batch)/2); ++i) { - Message msg = receiver.fetch(); - BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % ((i*2)+1+batch)).str()); - } - other.acknowledge();//acknowledge all messages - other.sync(); - other.close(); - - Message m; - //check queue is empty - BOOST_CHECK(!fix.session.createReceiver(fix.queue).fetch(m, Duration::IMMEDIATE)); -} - -QPID_AUTO_TEST_CASE(testQmfCreateAndDelete) -{ - MessagingFixture fix(Broker::Options(), true/*enable management*/); - MethodInvoker control(fix.session); - control.createQueue("my-queue"); - control.createExchange("my-exchange", "topic"); - control.bind("my-exchange", "my-queue", "subject1"); - - Sender sender = fix.session.createSender("my-exchange"); - Receiver receiver = fix.session.createReceiver("my-queue"); - Message out; - out.setSubject("subject1"); - out.setContent("one"); - sender.send(out); - Message in; - BOOST_CHECK(receiver.fetch(in, Duration::SECOND*5)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - control.unbind("my-exchange", "my-queue", "subject1"); - control.bind("my-exchange", "my-queue", "subject2"); - - out.setContent("two"); - sender.send(out);//should be dropped - - out.setSubject("subject2"); - out.setContent("three"); - sender.send(out);//should not be dropped - - BOOST_CHECK(receiver.fetch(in, Duration::SECOND*5)); - BOOST_CHECK_EQUAL(out.getContent(), in.getContent()); - BOOST_CHECK(!receiver.fetch(in, Duration::IMMEDIATE)); - sender.close(); - receiver.close(); - - control.deleteExchange("my-exchange"); - messaging::Session other = fix.connection.createSession(); - { - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(other.createSender("my-exchange"), qpid::messaging::NotFound); - } - control.deleteQueue("my-queue"); - other = fix.connection.createSession(); - { - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(other.createReceiver("my-queue"), qpid::messaging::NotFound); - } -} - -QPID_AUTO_TEST_CASE(testRejectAndCredit) -{ - //Ensure credit is restored on completing rejected messages - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Receiver receiver = fix.session.createReceiver(fix.queue); - - const uint count(10); - receiver.setCapacity(count); - for (uint i = 0; i < count; i++) { - sender.send(Message((boost::format("Message_%1%") % (i+1)).str())); - } - - Message in; - for (uint i = 0; i < count; ++i) { - if (receiver.fetch(in, Duration::SECOND)) { - BOOST_CHECK_EQUAL(in.getContent(), (boost::format("Message_%1%") % (i+1)).str()); - fix.session.reject(in); - } else { - BOOST_FAIL((boost::format("Message_%1% not received as expected") % (i+1)).str()); - break; - } - } - //send another batch of messages - for (uint i = 0; i < count; i++) { - sender.send(Message((boost::format("Message_%1%") % (i+count)).str())); - } - - for (uint i = 0; i < count; ++i) { - if (receiver.fetch(in, Duration::SECOND)) { - BOOST_CHECK_EQUAL(in.getContent(), (boost::format("Message_%1%") % (i+count)).str()); - } else { - BOOST_FAIL((boost::format("Message_%1% not received as expected") % (i+count)).str()); - break; - } - } - fix.session.acknowledge(); - receiver.close(); - sender.close(); -} - -QPID_AUTO_TEST_CASE(testTtlForever) -{ - QueueFixture fix; - Sender sender = fix.session.createSender(fix.queue); - Message out("I want to live forever!"); - out.setTtl(Duration::FOREVER); - sender.send(out, true); - Receiver receiver = fix.session.createReceiver(fix.queue); - Message in = receiver.fetch(Duration::IMMEDIATE); - fix.session.acknowledge(); - BOOST_CHECK_EQUAL(in.getContent(), out.getContent()); - BOOST_CHECK(in.getTtl() == Duration::FOREVER); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/MessagingThreadTests.cpp b/cpp/src/tests/MessagingThreadTests.cpp deleted file mode 100644 index 48264735b1..0000000000 --- a/cpp/src/tests/MessagingThreadTests.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "MessagingFixture.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include <boost/lexical_cast.hpp> - -namespace qpid { -namespace tests { -QPID_AUTO_TEST_SUITE(MessagingThreadTests) - -using namespace messaging; -using namespace boost::assign; -using namespace std; - -struct ReceiveThread : public sys::Runnable { - Receiver receiver; - vector<string> received; - string error; - - ReceiveThread(Receiver s) : receiver(s) {} - void run() { - try { - while(true) { - Message m = receiver.fetch(Duration::SECOND*5); - if (m.getContent() == "END") break; - received.push_back(m.getContent()); - } - } catch (const NoMessageAvailable& e) { - // Indicates that fetch timed out OR receiver was closed by other thread. - if (!receiver.isClosed()) // timeout - error = e.what(); - } catch (const std::exception& e) { - error = e.what(); - } - } -}; - -struct NextReceiverThread : public sys::Runnable { - Session session; - vector<string> received; - string error; - - NextReceiverThread(Session s) : session(s) {} - void run() { - try { - while(true) { - Message m = session.nextReceiver(Duration::SECOND*5).fetch(); - if (m.getContent() == "END") break; - received.push_back(m.getContent()); - } - } catch (const std::exception& e) { - error = e.what(); - } - } -}; - - -QPID_AUTO_TEST_CASE(testConcurrentSendReceive) { - MessagingFixture fix; - Sender s = fix.session.createSender("concurrent;{create:always}"); - Receiver r = fix.session.createReceiver("concurrent;{create:always,link:{reliability:unreliable}}"); - ReceiveThread rt(r); - sys::Thread thread(rt); - const size_t COUNT=100; - for (size_t i = 0; i < COUNT; ++i) { - s.send(Message()); - } - s.send(Message("END")); - thread.join(); - BOOST_CHECK_EQUAL(rt.error, string()); - BOOST_CHECK_EQUAL(COUNT, rt.received.size()); -} - -QPID_AUTO_TEST_CASE(testCloseBusyReceiver) { - MessagingFixture fix; - Receiver r = fix.session.createReceiver("closeReceiver;{create:always}"); - ReceiveThread rt(r); - sys::Thread thread(rt); - sys::usleep(1000); // Give the receive thread time to block. - r.close(); - thread.join(); - BOOST_CHECK_EQUAL(rt.error, string()); - - // Fetching on closed receiver should fail. - Message m; - BOOST_CHECK(!r.fetch(m, Duration(0))); - BOOST_CHECK_THROW(r.fetch(Duration(0)), NoMessageAvailable); -} - -QPID_AUTO_TEST_CASE(testCloseSessionBusyReceiver) { - MessagingFixture fix; - Receiver r = fix.session.createReceiver("closeSession;{create:always}"); - ReceiveThread rt(r); - sys::Thread thread(rt); - sys::usleep(1000); // Give the receive thread time to block. - fix.session.close(); - thread.join(); - BOOST_CHECK_EQUAL(rt.error, string()); - - // Fetching on closed receiver should fail. - Message m; - BOOST_CHECK(!r.fetch(m, Duration(0))); - BOOST_CHECK_THROW(r.fetch(Duration(0)), NoMessageAvailable); -} - -QPID_AUTO_TEST_CASE(testConcurrentSendNextReceiver) { - MessagingFixture fix; - Receiver r = fix.session.createReceiver("concurrent;{create:always,link:{reliability:unreliable}}"); - const size_t COUNT=100; - r.setCapacity(COUNT); - NextReceiverThread rt(fix.session); - sys::Thread thread(rt); - sys::usleep(1000); // Give the receive thread time to block. - Sender s = fix.session.createSender("concurrent;{create:always}"); - for (size_t i = 0; i < COUNT; ++i) { - s.send(Message()); - } - s.send(Message("END")); - thread.join(); - BOOST_CHECK_EQUAL(rt.error, string()); - BOOST_CHECK_EQUAL(COUNT, rt.received.size()); -} - -QPID_AUTO_TEST_SUITE_END() -}} // namespace qpid::tests diff --git a/cpp/src/tests/PartialFailure.cpp b/cpp/src/tests/PartialFailure.cpp deleted file mode 100644 index 63ee28017a..0000000000 --- a/cpp/src/tests/PartialFailure.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/**@file Tests for partial failure in a cluster. - * Partial failure means some nodes experience a failure while others do not. - * In this case the failed nodes must shut down. - */ - -#include "test_tools.h" -#include "unit_test.h" -#include "ClusterFixture.h" -#include <boost/assign.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/bind.hpp> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(PartialFailureTestSuite) - -using namespace std; -using namespace qpid; -using namespace qpid::cluster; -using namespace qpid::framing; -using namespace qpid::client; -using namespace qpid::client::arg; -using namespace boost::assign; -using broker::Broker; -using boost::shared_ptr; - -// Timeout for tests that wait for messages -const sys::Duration TIMEOUT=sys::TIME_SEC/4; - -static bool isLogOption(const std::string& s) { return boost::starts_with(s, "--log-enable"); } - -void updateArgs(ClusterFixture::Args& args, size_t index) { - ostringstream clusterLib, testStoreLib, storeName; - clusterLib << getLibPath("CLUSTER_LIB"); - testStoreLib << getLibPath("TEST_STORE_LIB"); - storeName << "s" << index; - args.push_back("--auth"); - args.push_back("no"); - args.push_back("--no-module-dir"); - args.push_back("--load-module"); - args.push_back(clusterLib.str()); - args.push_back("--load-module"); - args.push_back(testStoreLib.str()); - args.push_back("--test-store-name"); - args.push_back(storeName.str()); - args.push_back("TMP_DATA_DIR"); - - // These tests generate errors deliberately, disable error logging unless a log env var is set. - if (!::getenv("QPID_TRACE") && !::getenv("QPID_LOG_ENABLE")) { - remove_if(args.begin(), args.end(), isLogOption); - args.push_back("--log-enable=critical+:DISABLED"); // hacky way to disable logs. - } -} - -Message pMessage(string data, string q) { - Message msg(data, q); - msg.getDeliveryProperties().setDeliveryMode(PERSISTENT); - return msg; -} - -void queueAndSub(Client& c) { - c.session.queueDeclare(c.name, durable=true); - c.subs.subscribe(c.lq, c.name); -} - -// Handle near-simultaneous errors -QPID_AUTO_TEST_CASE(testCoincidentErrors) { - ClusterFixture cluster(2, updateArgs, -1); - Client c0(cluster[0], "c0"); - Client c1(cluster[1], "c1"); - - c0.session.queueDeclare("q", durable=true); - { - ScopedSuppressLogging allQuiet; - async(c0.session).messageTransfer(content=pMessage("TEST_STORE_DO: s0[exception]", "q")); - async(c1.session).messageTransfer(content=pMessage("TEST_STORE_DO: s1[exception]", "q")); - - int alive=0; - try { Client c00(cluster[0], "c00"); ++alive; c00.close(); } catch (...) {} - try { Client c11(cluster[1], "c11"); ++alive; c11.close(); } catch (...) {} - - BOOST_CHECK_EQUAL(alive, 1); - - // Close inside ScopedSuppressLogging to avoid warnings - c0.close(); - c1.close(); - } -} - -// Verify normal cluster-wide errors. -QPID_AUTO_TEST_CASE(testNormalErrors) { - // FIXME aconway 2009-04-10: Would like to put a scope just around - // the statements expected to fail (in BOOST_CHECK_yTHROW) but that - // sproadically lets out messages, possibly because they're in - // Connection thread. - - ClusterFixture cluster(3, updateArgs, -1); - Client c0(cluster[0], "c0"); - Client c1(cluster[1], "c1"); - Client c2(cluster[2], "c2"); - - { - ScopedSuppressLogging allQuiet; - queueAndSub(c0); - c0.session.messageTransfer(content=Message("x", "c0")); - BOOST_CHECK_EQUAL(c0.lq.get(TIMEOUT).getData(), "x"); - - // Session error. - BOOST_CHECK_THROW(c0.session.exchangeBind(), SessionException); - c1.session.messageTransfer(content=Message("stay", "c0")); // Will stay on queue, session c0 is dead. - - // Connection error, kill c1 on all members. - queueAndSub(c1); - BOOST_CHECK_THROW( - c1.session.messageTransfer( - content=pMessage("TEST_STORE_DO: s0[exception] s1[exception] s2[exception] testNormalErrors", "c1")), - ConnectionException); - c2.session.messageTransfer(content=Message("stay", "c1")); // Will stay on queue, session/connection c1 is dead. - - BOOST_CHECK_EQUAL(3u, knownBrokerPorts(c2.connection, 3).size()); - BOOST_CHECK_EQUAL(c2.subs.get("c0", TIMEOUT).getData(), "stay"); - BOOST_CHECK_EQUAL(c2.subs.get("c1", TIMEOUT).getData(), "stay"); - - // Close inside ScopedSuppressLogging to avoid warnings - c0.close(); - c1.close(); - c2.close(); - } -} - - -// Test errors after a new member joins to verify frame-sequence-numbers are ok in update. -QPID_AUTO_TEST_CASE(testErrorAfterJoin) { - ClusterFixture cluster(1, updateArgs, -1); - Client c0(cluster[0]); - { - ScopedSuppressLogging allQuiet; - - c0.session.queueDeclare("q", durable=true); - c0.session.messageTransfer(content=pMessage("a", "q")); - - // Kill the new guy - cluster.add(); - Client c1(cluster[1]); - c0.session.messageTransfer(content=pMessage("TEST_STORE_DO: s1[exception] testErrorAfterJoin", "q")); - BOOST_CHECK_THROW(c1.session.messageTransfer(content=pMessage("xxx", "q")), TransportFailure); - BOOST_CHECK_EQUAL(1u, knownBrokerPorts(c0.connection, 1).size()); - - // Kill the old guy - cluster.add(); - Client c2(cluster[2]); - c2.session.messageTransfer(content=pMessage("TEST_STORE_DO: s0[exception] testErrorAfterJoin2", "q")); - BOOST_CHECK_THROW(c0.session.messageTransfer(content=pMessage("xxx", "q")), TransportFailure); - - BOOST_CHECK_EQUAL(1u, knownBrokerPorts(c2.connection, 1).size()); - - // Close inside ScopedSuppressLogging to avoid warnings - c0.close(); - c1.close(); - c2.close(); - } -} - -// Test that if one member fails and others do not, the failure leaves the cluster. -QPID_AUTO_TEST_CASE(testSinglePartialFailure) { - ClusterFixture cluster(3, updateArgs, -1); - Client c0(cluster[0], "c0"); - Client c1(cluster[1], "c1"); - Client c2(cluster[2], "c2"); - - { - ScopedSuppressLogging allQuiet; - - c0.session.queueDeclare("q", durable=true); - c0.session.messageTransfer(content=pMessage("a", "q")); - // Cause partial failure on c1 - c0.session.messageTransfer(content=pMessage("TEST_STORE_DO: s1[exception] testSinglePartialFailure", "q")); - BOOST_CHECK_THROW(c1.session.queueQuery("q"), TransportFailure); - - c0.session.messageTransfer(content=pMessage("b", "q")); - BOOST_CHECK_EQUAL(c0.session.queueQuery("q").getMessageCount(), 3u); - BOOST_CHECK_EQUAL(2u, knownBrokerPorts(c0.connection, 2).size()); - - // Cause partial failure on c2 - c0.session.messageTransfer(content=pMessage("TEST_STORE_DO: s2[exception] testSinglePartialFailure2", "q")); - BOOST_CHECK_THROW(c2.session.queueQuery("q"), TransportFailure); - - c0.session.messageTransfer(content=pMessage("c", "q")); - BOOST_CHECK_EQUAL(c0.session.queueQuery("q").getMessageCount(), 5u); - BOOST_CHECK_EQUAL(1u, knownBrokerPorts(c0.connection, 1).size()); - - // Close inside ScopedSuppressLogging to avoid warnings - c0.close(); - c1.close(); - c2.close(); - } -} - -// Test multiple partial falures: 2 fail 2 pass -QPID_AUTO_TEST_CASE(testMultiPartialFailure) { - ClusterFixture cluster(4, updateArgs, -1); - Client c0(cluster[0], "c0"); - Client c1(cluster[1], "c1"); - Client c2(cluster[2], "c2"); - Client c3(cluster[3], "c3"); - - { - ScopedSuppressLogging allQuiet; - - c0.session.queueDeclare("q", durable=true); - c0.session.messageTransfer(content=pMessage("a", "q")); - - // Cause partial failure on c1, c2 - c0.session.messageTransfer(content=pMessage("TEST_STORE_DO: s1[exception] s2[exception] testMultiPartialFailure", "q")); - BOOST_CHECK_THROW(c1.session.queueQuery("q"), TransportFailure); - BOOST_CHECK_THROW(c2.session.queueQuery("q"), TransportFailure); - - c0.session.messageTransfer(content=pMessage("b", "q")); - c3.session.messageTransfer(content=pMessage("c", "q")); - BOOST_CHECK_EQUAL(c3.session.queueQuery("q").getMessageCount(), 4u); - // FIXME aconway 2009-06-30: This check fails sporadically with 2 != 3. - // It should pass reliably. - // BOOST_CHECK_EQUAL(2u, knownBrokerPorts(c0.connection, 2).size()); - - // Close inside ScopedSuppressLogging to avoid warnings - c0.close(); - c1.close(); - c2.close(); - c3.close(); - } -} - -/** FIXME aconway 2009-04-10: - * The current approach to shutting down a process in test_store - * sometimes leads to assertion failures and errors in the shut-down - * process. Need a cleaner solution - */ -#if 0 -QPID_AUTO_TEST_CASE(testPartialFailureMemberLeaves) { - ClusterFixture cluster(2, updateArgs, -1); - Client c0(cluster[0], "c0"); - Client c1(cluster[1], "c1"); - - { - ScopedSuppressLogging allQuiet; - - c0.session.queueDeclare("q", durable=true); - c0.session.messageTransfer(content=pMessage("a", "q")); - - // Cause failure on member 0 and simultaneous crash on member 1. - BOOST_CHECK_THROW( - c0.session.messageTransfer( - content=pMessage("TEST_STORE_DO: s0[exception] s1[exit_process] testPartialFailureMemberLeaves", "q")), - ConnectionException); - cluster.wait(1); - - Client c00(cluster[0], "c00"); // Old connection is dead. - BOOST_CHECK_EQUAL(c00.session.queueQuery("q").getMessageCount(), 1u); - BOOST_CHECK_EQUAL(1u, knownBrokerPorts(c00.connection, 1).size()); - - // Close inside ScopedSuppressLogging to avoid warnings - c0.close(); - } -} -#endif - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/PollableCondition.cpp b/cpp/src/tests/PollableCondition.cpp deleted file mode 100644 index f9b3c25c93..0000000000 --- a/cpp/src/tests/PollableCondition.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "test_tools.h" -#include "unit_test.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/PollableCondition.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(PollableConditionTest) - -using namespace qpid::sys; - -const Duration SHORT = TIME_SEC/100; -const Duration LONG = TIME_SEC/10; - -class Callback { - public: - enum Action { NONE, CLEAR }; - - Callback() : count(), action(NONE) {} - - void call(PollableCondition& pc) { - Mutex::ScopedLock l(lock); - ++count; - switch(action) { - case NONE: break; - case CLEAR: pc.clear(); break; - } - action = NONE; - lock.notify(); - } - - bool isCalling() { Mutex::ScopedLock l(lock); return wait(LONG); } - - bool isNotCalling() { Mutex::ScopedLock l(lock); return !wait(SHORT); } - - bool nextCall(Action a=NONE) { - Mutex::ScopedLock l(lock); - action = a; - return wait(LONG); - } - - private: - bool wait(Duration timeout) { - int n = count; - AbsTime deadline(now(), timeout); - while (n == count && lock.wait(deadline)) - ; - return n != count; - } - - Monitor lock; - int count; - Action action; -}; - -QPID_AUTO_TEST_CASE(testPollableCondition) { - boost::shared_ptr<Poller> poller(new Poller()); - Callback callback; - PollableCondition pc(boost::bind(&Callback::call, &callback, _1), poller); - - Thread runner = Thread(*poller); - - BOOST_CHECK(callback.isNotCalling()); // condition is not set. - - pc.set(); - BOOST_CHECK(callback.isCalling()); // Set. - BOOST_CHECK(callback.isCalling()); // Still set. - - callback.nextCall(Callback::CLEAR); - BOOST_CHECK(callback.isNotCalling()); // Cleared - - pc.set(); - BOOST_CHECK(callback.isCalling()); // Set. - callback.nextCall(Callback::CLEAR); - BOOST_CHECK(callback.isNotCalling()); // Cleared. - - poller->shutdown(); - runner.join(); -} - -QPID_AUTO_TEST_SUITE_END() - -}} //namespace qpid::tests diff --git a/cpp/src/tests/PollerTest.cpp b/cpp/src/tests/PollerTest.cpp deleted file mode 100644 index 9fa5689c5f..0000000000 --- a/cpp/src/tests/PollerTest.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * Use socketpair to test the poller - */ - -#include "qpid/sys/IOHandle.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/posix/PrivatePosix.h" - -#include <string> -#include <iostream> -#include <memory> -#include <exception> - -#include <assert.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> - -using namespace std; -using namespace qpid::sys; - -int writeALot(int fd, const string& s) { - int bytesWritten = 0; - do { - errno = 0; - int lastWrite = ::write(fd, s.c_str(), s.size()); - if ( lastWrite >= 0) { - bytesWritten += lastWrite; - } - } while (errno != EAGAIN); - return bytesWritten; -} - -int readALot(int fd) { - int bytesRead = 0; - char buf[1024]; - - do { - errno = 0; - int lastRead = ::read(fd, buf, sizeof(buf)); - if ( lastRead >= 0) { - bytesRead += lastRead; - } - } while (errno != EAGAIN); - return bytesRead; -} - -void makesocketpair(int (&sv)[2]) { - int rc = ::socketpair(AF_UNIX, SOCK_STREAM, 0, sv); - assert(rc >= 0); - - // Set non-blocking - rc = ::fcntl(sv[0], F_SETFL, O_NONBLOCK); - assert(rc >= 0); - - rc = ::fcntl(sv[1], F_SETFL, O_NONBLOCK); - assert(rc >= 0); -} - -int main(int /*argc*/, char** /*argv*/) -{ - try - { - int sv[2]; - makesocketpair(sv); - - // Make up a large string - string testString = "This is only a test ... 1,2,3,4,5,6,7,8,9,10;"; - for (int i = 0; i < 6; i++) - testString += testString; - - // Read as much as we can from socket 0 - int bytesRead = readALot(sv[0]); - assert(bytesRead == 0); - - // Write as much as we can to socket 0 - int bytesWritten = writeALot(sv[0], testString); - - // Read as much as we can from socket 1 - bytesRead = readALot(sv[1]); - assert(bytesRead == bytesWritten); - - auto_ptr<Poller> poller(new Poller); - - PosixIOHandle f0(sv[0]); - PosixIOHandle f1(sv[1]); - - PollerHandle h0(f0); - PollerHandle h1(f1); - - poller->registerHandle(h0); - poller->monitorHandle(h0, Poller::INOUT); - - // h0 should be writable - Poller::Event event = poller->wait(); - assert(event.handle == &h0); - assert(event.type == Poller::WRITABLE); - - // Write as much as we can to socket 0 - bytesWritten = writeALot(sv[0], testString); - - // Wait for 500ms - h0 no longer writable - event = poller->wait(500000000); - assert(event.handle == 0); - - // Test we can read it all now - poller->registerHandle(h1); - poller->monitorHandle(h1, Poller::INOUT); - event = poller->wait(); - assert(event.handle == &h1); - assert(event.type == Poller::READ_WRITABLE); - - bytesRead = readALot(sv[1]); - assert(bytesRead == bytesWritten); - - // Test poller interrupt - assert(poller->interrupt(h0) == true); - event = poller->wait(); - assert(event.handle == &h0); - assert(event.type == Poller::INTERRUPTED); - - // Test multiple interrupts - assert(poller->interrupt(h0) == true); - assert(poller->interrupt(h1) == true); - - // Make sure we can interrupt them again - assert(poller->interrupt(h0) == true); - assert(poller->interrupt(h1) == true); - - // Make sure that they both come out - event = poller->wait(); - assert(event.type == Poller::INTERRUPTED); - assert(event.handle == &h0 || event.handle == &h1); - if (event.handle == &h0) { - event = poller->wait(); - assert(event.type == Poller::INTERRUPTED); - assert(event.handle == &h1); - } else { - event = poller->wait(); - assert(event.type == Poller::INTERRUPTED); - assert(event.handle == &h0); - } - - poller->unmonitorHandle(h1, Poller::INOUT); - - event = poller->wait(); - assert(event.handle == &h0); - assert(event.type == Poller::WRITABLE); - - // We didn't write anything so it should still be writable - event = poller->wait(); - assert(event.handle == &h0); - assert(event.type == Poller::WRITABLE); - - poller->unmonitorHandle(h0, Poller::INOUT); - - event = poller->wait(500000000); - assert(event.handle == 0); - - poller->unregisterHandle(h1); - assert(poller->interrupt(h1) == false); - - // close the other end to force a disconnect - ::close(sv[1]); - - // Now make sure that we are readable followed by disconnected - // and after that we never return again - poller->monitorHandle(h0, Poller::INOUT); - event = poller->wait(500000000); - assert(event.handle == &h0); - assert(event.type == Poller::READABLE); - event = poller->wait(500000000); - assert(event.handle == &h0); - assert(event.type == Poller::DISCONNECTED); - event = poller->wait(1500000000); - assert(event.handle == 0); - - // Now we're disconnected monitoring should have no effect at all - poller->unmonitorHandle(h0, Poller::INOUT); - event = poller->wait(1500000000); - assert(event.handle == 0); - - poller->unregisterHandle(h0); - assert(poller->interrupt(h0) == false); - - // Test shutdown - poller->shutdown(); - event = poller->wait(); - assert(event.handle == 0); - assert(event.type == Poller::SHUTDOWN); - - event = poller->wait(); - assert(event.handle == 0); - assert(event.type == Poller::SHUTDOWN); - - ::close(sv[0]); - - // Test for correct interaction of shutdown and interrupts - need to have new poller - // etc. for this - makesocketpair(sv); - - auto_ptr<Poller> poller1(new Poller); - - PosixIOHandle f2(sv[0]); - PosixIOHandle f3(sv[1]); - - PollerHandle h2(f2); - PollerHandle h3(f3); - - poller1->registerHandle(h2); - poller1->monitorHandle(h2, Poller::INOUT); - event = poller1->wait(); - assert(event.handle == &h2); - assert(event.type == Poller::WRITABLE); - - // Shutdown - poller1->shutdown(); - event = poller1->wait(); - assert(event.handle == 0); - assert(event.type == Poller::SHUTDOWN); - - assert(poller1->interrupt(h2) == true); - event = poller1->wait(); - assert(event.handle == &h2); - assert(event.type == Poller::INTERRUPTED); - poller1->unmonitorHandle(h2, Poller::INOUT); - - event = poller1->wait(); - assert(event.handle == 0); - assert(event.type == Poller::SHUTDOWN); - - poller1->unregisterHandle(h2); - return 0; - } catch (exception& e) { - cout << "Caught exception " << e.what() << "\n"; - } -} - - diff --git a/cpp/src/tests/ProxyTest.cpp b/cpp/src/tests/ProxyTest.cpp deleted file mode 100644 index a926b28395..0000000000 --- a/cpp/src/tests/ProxyTest.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/ExecutionSyncBody.h" -#include "qpid/framing/Proxy.h" - -#include "unit_test.h" - -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ProxyTestSuite) - - -QPID_AUTO_TEST_CASE(testScopedSync) -{ - struct DummyHandler : FrameHandler - { - void handle(AMQFrame& f) { - AMQMethodBody* m = f.getMethod(); - BOOST_CHECK(m); - BOOST_CHECK(m->isA<ExecutionSyncBody>()); - BOOST_CHECK(m->isSync()); - } - }; - DummyHandler f; - Proxy p(f); - Proxy::ScopedSync s(p); - p.send(ExecutionSyncBody(p.getVersion())); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/Qmf2.cpp b/cpp/src/tests/Qmf2.cpp deleted file mode 100644 index 66c774accd..0000000000 --- a/cpp/src/tests/Qmf2.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/types/Variant.h" -#include "qmf/QueryImpl.h" -#include "qmf/SchemaImpl.h" -#include "qmf/exceptions.h" - -#include "unit_test.h" - -using namespace qpid::types; -using namespace qmf; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(Qmf2Suite) - -QPID_AUTO_TEST_CASE(testQuery) -{ - Query query(QUERY_OBJECT, "class_name", "package_name", "[and, [eq, name, [quote, smith]], [lt, age, [quote, 27]]]"); - Query newQuery(new QueryImpl(QueryImplAccess::get(query).asMap())); - - BOOST_CHECK_EQUAL(newQuery.getTarget(), QUERY_OBJECT); - BOOST_CHECK_EQUAL(newQuery.getSchemaId().getName(), "class_name"); - BOOST_CHECK_EQUAL(newQuery.getSchemaId().getPackageName(), "package_name"); - - Variant::List pred(newQuery.getPredicate()); - BOOST_CHECK_EQUAL(pred.size(), size_t(3)); - - Variant::List::iterator iter(pred.begin()); - BOOST_CHECK_EQUAL(iter->asString(), "and"); - iter++; - BOOST_CHECK_EQUAL(iter->getType(), VAR_LIST); - iter++; - BOOST_CHECK_EQUAL(iter->getType(), VAR_LIST); - iter = iter->asList().begin(); - BOOST_CHECK_EQUAL(iter->asString(), "lt"); - iter++; - BOOST_CHECK_EQUAL(iter->asString(), "age"); - iter++; - BOOST_CHECK_EQUAL(iter->getType(), VAR_LIST); - iter = iter->asList().begin(); - BOOST_CHECK_EQUAL(iter->asString(), "quote"); - iter++; - BOOST_CHECK_EQUAL(iter->asUint32(), uint32_t(27)); - - Query query2(QUERY_OBJECT_ID); - Query newQuery2(new QueryImpl(QueryImplAccess::get(query2).asMap())); - BOOST_CHECK_EQUAL(newQuery2.getTarget(), QUERY_OBJECT_ID); - - Query query3(QUERY_SCHEMA); - Query newQuery3(new QueryImpl(QueryImplAccess::get(query3).asMap())); - BOOST_CHECK_EQUAL(newQuery3.getTarget(), QUERY_SCHEMA); - - Query query4(QUERY_SCHEMA_ID); - Query newQuery4(new QueryImpl(QueryImplAccess::get(query4).asMap())); - BOOST_CHECK_EQUAL(newQuery4.getTarget(), QUERY_SCHEMA_ID); - - DataAddr addr("name", "agent_name", 34); - Query query5(addr); - Query newQuery5(new QueryImpl(QueryImplAccess::get(query5).asMap())); - BOOST_CHECK_EQUAL(newQuery5.getTarget(), QUERY_OBJECT); - BOOST_CHECK_EQUAL(newQuery5.getDataAddr().getName(), "name"); - BOOST_CHECK_EQUAL(newQuery5.getDataAddr().getAgentName(), "agent_name"); - BOOST_CHECK_EQUAL(newQuery5.getDataAddr().getAgentEpoch(), uint32_t(34)); -} - -QPID_AUTO_TEST_CASE(testQueryPredicateErrors) -{ - Query query; - Variant::Map map; - - BOOST_CHECK_THROW(Query(QUERY_OBJECT, "INVALID"), QmfException); - query = Query(QUERY_OBJECT, "[unknown, one, two]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[exists]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first, [quote, 1, 2, 3]]]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first, [unexpected, 3]]]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first, {}]]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[eq, first, second, third]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); - - query = Query(QUERY_OBJECT, "[and, first, second, third]"); - BOOST_CHECK_THROW(query.matchesPredicate(map), QmfException); -} - -QPID_AUTO_TEST_CASE(testQueryPredicate) -{ - Query query; - Variant::Map map; - - map["forty"] = 40; - map["fifty"] = 50; - map["minus_ten"] = -10; - map["pos_float"] = 100.05; - map["neg_float"] = -1000.33; - map["name"] = "jones"; - map["bool_t"] = true; - map["bool_f"] = false; - - BOOST_CHECK_THROW(Query(QUERY_OBJECT, "INVALID"), QmfException); - - query = Query(QUERY_OBJECT); - BOOST_CHECK_EQUAL(query.matchesPredicate(Variant::Map()), true); - - query = Query(QUERY_OBJECT, "[eq, forty, [quote, 40]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[eq, forty, [quote, 41]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[le, forty, fifty]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[and, [eq, forty, [quote, 40]], [eq, name, [quote, jones]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[and, [eq, forty, [quote, 40]], [eq, name, [quote, smith]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[or, [eq, forty, [quote, 40]], [eq, name, [quote, smith]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[or, [eq, forty, [quote, 41]], [eq, name, [quote, smith]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[not, [le, forty, [quote, 40]]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[le, forty, [quote, 40]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[ge, forty, [quote, 40]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[lt, forty, [quote, 45]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[lt, [quote, 45], forty]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[gt, forty, [quote, 45]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[gt, [quote, 45], forty]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[eq, bool_t, [quote, True]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[eq, bool_t, [quote, False]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[eq, bool_f, [quote, True]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[eq, bool_f, [quote, False]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[eq, minus_ten, [quote, -10]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[lt, minus_ten, [quote, -20]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[lt, [quote, -20], minus_ten]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[exists, name]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); - - query = Query(QUERY_OBJECT, "[exists, nonexfield]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), false); - - query = Query(QUERY_OBJECT, "[eq, pos_float, [quote, 100.05]]"); - BOOST_CHECK_EQUAL(query.matchesPredicate(map), true); -} - -QPID_AUTO_TEST_CASE(testSchema) -{ - Schema in(SCHEMA_TYPE_DATA, "package", "class"); - in.addProperty(SchemaProperty("prop1", SCHEMA_DATA_BOOL, "{desc:'Property One'}")); - in.addProperty(SchemaProperty("prop2", SCHEMA_DATA_INT, "{desc:'Property Two',unit:'Furlong'}")); - in.addProperty(SchemaProperty("prop3", SCHEMA_DATA_STRING, "{desc:'Property Three'}")); - - SchemaMethod method1("method1", "{desc:'Method One'}"); - method1.addArgument(SchemaProperty("arg1", SCHEMA_DATA_BOOL, "{desc:'Argument One',dir:IN}")); - method1.addArgument(SchemaProperty("arg2", SCHEMA_DATA_INT, "{desc:'Argument Two',dir:OUT}")); - method1.addArgument(SchemaProperty("arg3", SCHEMA_DATA_FLOAT, "{desc:'Argument Three',dir:INOUT}")); - in.addMethod(method1); - - SchemaMethod method2("method2", "{desc:'Method Two'}"); - method2.addArgument(SchemaProperty("arg21", SCHEMA_DATA_BOOL, "{desc:'Argument One',dir:IN}")); - method2.addArgument(SchemaProperty("arg22", SCHEMA_DATA_INT, "{desc:'Argument Two',dir:OUT}")); - method2.addArgument(SchemaProperty("arg23", SCHEMA_DATA_FLOAT, "{desc:'Argument Three',dir:INOUT}")); - in.addMethod(method2); - - BOOST_CHECK(!in.isFinalized()); - in.finalize(); - BOOST_CHECK(in.isFinalized()); - - Variant::Map map(SchemaImplAccess::get(in).asMap()); - Schema out(new SchemaImpl(map)); - - BOOST_CHECK(out.isFinalized()); - BOOST_CHECK_EQUAL(out.getSchemaId().getType(), SCHEMA_TYPE_DATA); - BOOST_CHECK_EQUAL(out.getSchemaId().getPackageName(), "package"); - BOOST_CHECK_EQUAL(out.getSchemaId().getName(), "class"); - BOOST_CHECK_EQUAL(out.getSchemaId().getHash(), in.getSchemaId().getHash()); - - BOOST_CHECK_EQUAL(out.getPropertyCount(), uint32_t(3)); - SchemaProperty prop; - - prop = out.getProperty(0); - BOOST_CHECK_EQUAL(prop.getName(), "prop1"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_BOOL); - BOOST_CHECK_EQUAL(prop.getDesc(), "Property One"); - - prop = out.getProperty(1); - BOOST_CHECK_EQUAL(prop.getName(), "prop2"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_INT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Property Two"); - BOOST_CHECK_EQUAL(prop.getUnit(), "Furlong"); - BOOST_CHECK(!prop.isIndex()); - - prop = out.getProperty(2); - BOOST_CHECK_EQUAL(prop.getName(), "prop3"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_STRING); - BOOST_CHECK_EQUAL(prop.getDesc(), "Property Three"); - - BOOST_CHECK_THROW(out.getProperty(3), QmfException); - - BOOST_CHECK_EQUAL(out.getMethodCount(), uint32_t(2)); - SchemaMethod method; - - method = out.getMethod(0); - BOOST_CHECK_EQUAL(method.getName(), "method1"); - BOOST_CHECK_EQUAL(method.getDesc(), "Method One"); - BOOST_CHECK_EQUAL(method.getArgumentCount(), uint32_t(3)); - - prop = method.getArgument(0); - BOOST_CHECK_EQUAL(prop.getName(), "arg1"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_BOOL); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument One"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_IN); - - prop = method.getArgument(1); - BOOST_CHECK_EQUAL(prop.getName(), "arg2"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_INT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument Two"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_OUT); - - prop = method.getArgument(2); - BOOST_CHECK_EQUAL(prop.getName(), "arg3"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_FLOAT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument Three"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_IN_OUT); - - BOOST_CHECK_THROW(method.getArgument(3), QmfException); - - method = out.getMethod(1); - BOOST_CHECK_EQUAL(method.getName(), "method2"); - BOOST_CHECK_EQUAL(method.getDesc(), "Method Two"); - BOOST_CHECK_EQUAL(method.getArgumentCount(), uint32_t(3)); - - prop = method.getArgument(0); - BOOST_CHECK_EQUAL(prop.getName(), "arg21"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_BOOL); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument One"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_IN); - - prop = method.getArgument(1); - BOOST_CHECK_EQUAL(prop.getName(), "arg22"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_INT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument Two"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_OUT); - - prop = method.getArgument(2); - BOOST_CHECK_EQUAL(prop.getName(), "arg23"); - BOOST_CHECK_EQUAL(prop.getType(), SCHEMA_DATA_FLOAT); - BOOST_CHECK_EQUAL(prop.getDesc(), "Argument Three"); - BOOST_CHECK_EQUAL(prop.getDirection(), DIR_IN_OUT); - - BOOST_CHECK_THROW(method.getArgument(3), QmfException); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/QueueEvents.cpp b/cpp/src/tests/QueueEvents.cpp deleted file mode 100644 index bd18fa45fb..0000000000 --- a/cpp/src/tests/QueueEvents.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "MessageUtils.h" -#include "unit_test.h" -#include "BrokerFixture.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueEvents.h" -#include "qpid/client/QueueOptions.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/sys/Dispatcher.h" -#include <boost/bind.hpp> -#include <boost/format.hpp> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueueEventsSuite) - -using namespace qpid::client; -using namespace qpid::broker; -using namespace qpid::sys; -using qpid::framing::SequenceNumber; - -struct EventChecker -{ - typedef std::deque<QueueEvents::Event> Events; - - Events events; - boost::shared_ptr<Poller> poller; - - void handle(QueueEvents::Event e) - { - if (events.empty()) { - BOOST_FAIL("Unexpected event received"); - } else { - BOOST_CHECK_EQUAL(events.front().type, e.type); - BOOST_CHECK_EQUAL(events.front().msg.queue, e.msg.queue); - BOOST_CHECK_EQUAL(events.front().msg.payload, e.msg.payload); - BOOST_CHECK_EQUAL(events.front().msg.position, e.msg.position); - events.pop_front(); - } - if (events.empty() && poller) poller->shutdown(); - } - - void expect(QueueEvents::Event e) - { - events.push_back(e); - } -}; - -QPID_AUTO_TEST_CASE(testBasicEventProcessing) -{ - boost::shared_ptr<Poller> poller(new Poller()); - sys::Dispatcher dispatcher(poller); - Thread dispatchThread(dispatcher); - QueueEvents events(poller); - EventChecker listener; - listener.poller = poller; - events.registerListener("dummy", boost::bind(&EventChecker::handle, &listener, _1)); - //signal occurence of some events: - Queue queue("queue1"); - SequenceNumber id; - QueuedMessage event1(&queue, MessageUtils::createMessage(), id); - QueuedMessage event2(&queue, MessageUtils::createMessage(), ++id); - - //define events expected by listener: - listener.expect(QueueEvents::Event(QueueEvents::ENQUEUE, event1)); - listener.expect(QueueEvents::Event(QueueEvents::ENQUEUE, event2)); - listener.expect(QueueEvents::Event(QueueEvents::DEQUEUE, event1)); - - events.enqueued(event1); - events.enqueued(event2); - events.dequeued(event1); - - dispatchThread.join(); - events.shutdown(); - events.unregisterListener("dummy"); -} - - -struct EventRecorder -{ - struct EventRecord - { - QueueEvents::EventType type; - std::string queue; - std::string content; - SequenceNumber position; - }; - - typedef std::deque<EventRecord> Events; - - Events events; - - void handle(QueueEvents::Event event) - { - EventRecord record; - record.type = event.type; - record.queue = event.msg.queue->getName(); - event.msg.payload->getFrames().getContent(record.content); - record.position = event.msg.position; - events.push_back(record); - } - - void check(QueueEvents::EventType type, const std::string& queue, const std::string& content, const SequenceNumber& position) - { - if (events.empty()) { - BOOST_FAIL("Missed event"); - } else { - BOOST_CHECK_EQUAL(events.front().type, type); - BOOST_CHECK_EQUAL(events.front().queue, queue); - BOOST_CHECK_EQUAL(events.front().content, content); - BOOST_CHECK_EQUAL(events.front().position, position); - events.pop_front(); - } - } - void checkEnqueue(const std::string& queue, const std::string& data, const SequenceNumber& position) - { - check(QueueEvents::ENQUEUE, queue, data, position); - } - - void checkDequeue(const std::string& queue, const std::string& data, const SequenceNumber& position) - { - check(QueueEvents::DEQUEUE, queue, data, position); - } -}; - -QPID_AUTO_TEST_CASE(testSystemLevelEventProcessing) -{ - ProxySessionFixture fixture; - //register dummy event listener to broker - EventRecorder listener; - fixture.broker->getQueueEvents().registerListener("recorder", boost::bind(&EventRecorder::handle, &listener, _1)); - - //declare queue with event options specified - QueueOptions options; - options.enableQueueEvents(false); - std::string q("queue-events-test"); - fixture.session.queueDeclare(arg::queue=q, arg::arguments=options); - //send and consume some messages - LocalQueue incoming; - Subscription sub = fixture.subs.subscribe(incoming, q); - for (int i = 0; i < 5; i++) { - fixture.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 0; i < 3; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - for (int i = 5; i < 10; i++) { - fixture.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 3; i < 10; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - fixture.connection.close(); - fixture.broker->getQueueEvents().shutdown(); - - //check listener was notified of all events, and in correct order - SequenceNumber enqueueId(1); - SequenceNumber dequeueId(1); - for (int i = 0; i < 5; i++) { - listener.checkEnqueue(q, (boost::format("%1%_%2%") % "Message" % (i+1)).str(), enqueueId++); - } - for (int i = 0; i < 3; i++) { - listener.checkDequeue(q, (boost::format("%1%_%2%") % "Message" % (i+1)).str(), dequeueId++); - } - for (int i = 5; i < 10; i++) { - listener.checkEnqueue(q, (boost::format("%1%_%2%") % "Message" % (i+1)).str(), enqueueId++); - } - for (int i = 3; i < 10; i++) { - listener.checkDequeue(q, (boost::format("%1%_%2%") % "Message" % (i+1)).str(), dequeueId++); - } -} - -QPID_AUTO_TEST_CASE(testSystemLevelEventProcessing_enqueuesOnly) -{ - ProxySessionFixture fixture; - //register dummy event listener to broker - EventRecorder listener; - fixture.broker->getQueueEvents().registerListener("recorder", boost::bind(&EventRecorder::handle, &listener, _1)); - - //declare queue with event options specified - QueueOptions options; - options.enableQueueEvents(true); - std::string q("queue-events-test"); - fixture.session.queueDeclare(arg::queue=q, arg::arguments=options); - //send and consume some messages - LocalQueue incoming; - Subscription sub = fixture.subs.subscribe(incoming, q); - for (int i = 0; i < 5; i++) { - fixture.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 0; i < 3; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - for (int i = 5; i < 10; i++) { - fixture.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 3; i < 10; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - fixture.connection.close(); - fixture.broker->getQueueEvents().shutdown(); - - //check listener was notified of all events, and in correct order - SequenceNumber enqueueId(1); - SequenceNumber dequeueId(1); - for (int i = 0; i < 5; i++) { - listener.checkEnqueue(q, (boost::format("%1%_%2%") % "Message" % (i+1)).str(), enqueueId++); - } - for (int i = 5; i < 10; i++) { - listener.checkEnqueue(q, (boost::format("%1%_%2%") % "Message" % (i+1)).str(), enqueueId++); - } -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/QueueFlowLimitTest.cpp b/cpp/src/tests/QueueFlowLimitTest.cpp deleted file mode 100644 index 8a6923fb09..0000000000 --- a/cpp/src/tests/QueueFlowLimitTest.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <sstream> -#include <deque> -#include "unit_test.h" -#include "test_tools.h" - -#include "qpid/broker/QueuePolicy.h" -#include "qpid/broker/QueueFlowLimit.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/reply_exceptions.h" -#include "MessageUtils.h" -#include "BrokerFixture.h" - -using namespace qpid::broker; -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueueFlowLimitTestSuite) - -namespace { - -class TestFlow : public QueueFlowLimit -{ -public: - TestFlow(uint32_t flowStopCount, uint32_t flowResumeCount, - uint64_t flowStopSize, uint64_t flowResumeSize) : - QueueFlowLimit(0, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize) - {} - virtual ~TestFlow() {} - - static TestFlow *createTestFlow(const qpid::framing::FieldTable& settings) - { - FieldTable::ValuePtr v; - - v = settings.get(flowStopCountKey); - uint32_t flowStopCount = (v) ? (uint32_t)v->get<int64_t>() : 0; - v = settings.get(flowResumeCountKey); - uint32_t flowResumeCount = (v) ? (uint32_t)v->get<int64_t>() : 0; - v = settings.get(flowStopSizeKey); - uint64_t flowStopSize = (v) ? (uint64_t)v->get<int64_t>() : 0; - v = settings.get(flowResumeSizeKey); - uint64_t flowResumeSize = (v) ? (uint64_t)v->get<int64_t>() : 0; - - return new TestFlow(flowStopCount, flowResumeCount, flowStopSize, flowResumeSize); - } - - static QueueFlowLimit *getQueueFlowLimit(const qpid::framing::FieldTable& settings) - { - return QueueFlowLimit::createLimit(0, settings); - } -}; - - - -QueuedMessage createMessage(uint32_t size) -{ - static uint32_t seqNum; - QueuedMessage msg; - msg.payload = MessageUtils::createMessage(); - msg.position = ++seqNum; - MessageUtils::addContent(msg.payload, std::string (size, 'x')); - return msg; -} -} - -QPID_AUTO_TEST_CASE(testFlowCount) -{ - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 7); - args.setInt(QueueFlowLimit::flowResumeCountKey, 5); - - std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args)); - - BOOST_CHECK_EQUAL((uint32_t) 7, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 5, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - - std::deque<QueuedMessage> msgs; - for (size_t i = 0; i < 6; i++) { - msgs.push_back(createMessage(10)); - flow->enqueued(msgs.back()); - BOOST_CHECK(!flow->isFlowControlActive()); - } - BOOST_CHECK(!flow->isFlowControlActive()); // 6 on queue - msgs.push_back(createMessage(10)); - flow->enqueued(msgs.back()); - BOOST_CHECK(!flow->isFlowControlActive()); // 7 on queue - msgs.push_back(createMessage(10)); - flow->enqueued(msgs.back()); - BOOST_CHECK(flow->isFlowControlActive()); // 8 on queue, ON - msgs.push_back(createMessage(10)); - flow->enqueued(msgs.back()); - BOOST_CHECK(flow->isFlowControlActive()); // 9 on queue, no change to flow control - - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 8 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 7 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 6 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 5 on queue, no change - - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); // 4 on queue, OFF -} - - -QPID_AUTO_TEST_CASE(testFlowSize) -{ - FieldTable args; - args.setUInt64(QueueFlowLimit::flowStopSizeKey, 70); - args.setUInt64(QueueFlowLimit::flowResumeSizeKey, 50); - - std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args)); - - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint32_t) 70, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint32_t) 50, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - - std::deque<QueuedMessage> msgs; - for (size_t i = 0; i < 6; i++) { - msgs.push_back(createMessage(10)); - flow->enqueued(msgs.back()); - BOOST_CHECK(!flow->isFlowControlActive()); - } - BOOST_CHECK(!flow->isFlowControlActive()); // 60 on queue - BOOST_CHECK_EQUAL(6u, flow->getFlowCount()); - BOOST_CHECK_EQUAL(60u, flow->getFlowSize()); - - QueuedMessage msg_9 = createMessage(9); - flow->enqueued(msg_9); - BOOST_CHECK(!flow->isFlowControlActive()); // 69 on queue - QueuedMessage tinyMsg_1 = createMessage(1); - flow->enqueued(tinyMsg_1); - BOOST_CHECK(!flow->isFlowControlActive()); // 70 on queue - - QueuedMessage tinyMsg_2 = createMessage(1); - flow->enqueued(tinyMsg_2); - BOOST_CHECK(flow->isFlowControlActive()); // 71 on queue, ON - msgs.push_back(createMessage(10)); - flow->enqueued(msgs.back()); - BOOST_CHECK(flow->isFlowControlActive()); // 81 on queue - BOOST_CHECK_EQUAL(10u, flow->getFlowCount()); - BOOST_CHECK_EQUAL(81u, flow->getFlowSize()); - - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 71 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 61 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // 51 on queue - - flow->dequeued(tinyMsg_1); - BOOST_CHECK(flow->isFlowControlActive()); // 50 on queue - flow->dequeued(tinyMsg_2); - BOOST_CHECK(!flow->isFlowControlActive()); // 49 on queue, OFF - - flow->dequeued(msg_9); - BOOST_CHECK(!flow->isFlowControlActive()); // 40 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); // 30 on queue - flow->dequeued(msgs.front()); - msgs.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); // 20 on queue - BOOST_CHECK_EQUAL(2u, flow->getFlowCount()); - BOOST_CHECK_EQUAL(20u, flow->getFlowSize()); -} - -QPID_AUTO_TEST_CASE(testFlowArgs) -{ - FieldTable args; - const uint64_t stop(0x2FFFFFFFFull); - const uint64_t resume(0x1FFFFFFFFull); - args.setInt(QueueFlowLimit::flowStopCountKey, 30); - args.setInt(QueueFlowLimit::flowResumeCountKey, 21); - args.setUInt64(QueueFlowLimit::flowStopSizeKey, stop); - args.setUInt64(QueueFlowLimit::flowResumeSizeKey, resume); - - std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args)); - - BOOST_CHECK_EQUAL((uint32_t) 30, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 21, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL(stop, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL(resume, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); -} - - -QPID_AUTO_TEST_CASE(testFlowCombo) -{ - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 10); - args.setInt(QueueFlowLimit::flowResumeCountKey, 5); - args.setUInt64(QueueFlowLimit::flowStopSizeKey, 200); - args.setUInt64(QueueFlowLimit::flowResumeSizeKey, 100); - - std::deque<QueuedMessage> msgs_1; - std::deque<QueuedMessage> msgs_10; - std::deque<QueuedMessage> msgs_50; - std::deque<QueuedMessage> msgs_100; - - QueuedMessage msg; - - std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args)); - BOOST_CHECK(!flow->isFlowControlActive()); // count:0 size:0 - - // verify flow control comes ON when only count passes its stop point. - - for (size_t i = 0; i < 10; i++) { - msgs_10.push_back(createMessage(10)); - flow->enqueued(msgs_10.back()); - BOOST_CHECK(!flow->isFlowControlActive()); - } - // count:10 size:100 - - msgs_1.push_back(createMessage(1)); - flow->enqueued(msgs_1.back()); // count:11 size: 101 ->ON - BOOST_CHECK(flow->isFlowControlActive()); - - for (size_t i = 0; i < 6; i++) { - flow->dequeued(msgs_10.front()); - msgs_10.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - } - // count:5 size: 41 - - flow->dequeued(msgs_1.front()); // count: 4 size: 40 ->OFF - msgs_1.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); - - for (size_t i = 0; i < 4; i++) { - flow->dequeued(msgs_10.front()); - msgs_10.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); - } - // count:0 size:0 - - // verify flow control comes ON when only size passes its stop point. - - msgs_100.push_back(createMessage(100)); - flow->enqueued(msgs_100.back()); // count:1 size: 100 - BOOST_CHECK(!flow->isFlowControlActive()); - - msgs_50.push_back(createMessage(50)); - flow->enqueued(msgs_50.back()); // count:2 size: 150 - BOOST_CHECK(!flow->isFlowControlActive()); - - msgs_50.push_back(createMessage(50)); - flow->enqueued(msgs_50.back()); // count:3 size: 200 - BOOST_CHECK(!flow->isFlowControlActive()); - - msgs_1.push_back(createMessage(1)); - flow->enqueued(msgs_1.back()); // count:4 size: 201 ->ON - BOOST_CHECK(flow->isFlowControlActive()); - - flow->dequeued(msgs_100.front()); // count:3 size:101 - msgs_100.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - - flow->dequeued(msgs_1.front()); // count:2 size:100 - msgs_1.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - - flow->dequeued(msgs_50.front()); // count:1 size:50 ->OFF - msgs_50.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); - - // verify flow control remains ON until both thresholds drop below their - // resume point. - - for (size_t i = 0; i < 8; i++) { - msgs_10.push_back(createMessage(10)); - flow->enqueued(msgs_10.back()); - BOOST_CHECK(!flow->isFlowControlActive()); - } - // count:9 size:130 - - msgs_10.push_back(createMessage(10)); - flow->enqueued(msgs_10.back()); // count:10 size: 140 - BOOST_CHECK(!flow->isFlowControlActive()); - - msgs_1.push_back(createMessage(1)); - flow->enqueued(msgs_1.back()); // count:11 size: 141 ->ON - BOOST_CHECK(flow->isFlowControlActive()); - - msgs_100.push_back(createMessage(100)); - flow->enqueued(msgs_100.back()); // count:12 size: 241 (both thresholds crossed) - BOOST_CHECK(flow->isFlowControlActive()); - - // at this point: 9@10 + 1@50 + 1@100 + 1@1 == 12@241 - - flow->dequeued(msgs_50.front()); // count:11 size:191 - msgs_50.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - - for (size_t i = 0; i < 9; i++) { - flow->dequeued(msgs_10.front()); - msgs_10.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); - } - // count:2 size:101 - flow->dequeued(msgs_1.front()); // count:1 size:100 - msgs_1.pop_front(); - BOOST_CHECK(flow->isFlowControlActive()); // still active due to size - - flow->dequeued(msgs_100.front()); // count:0 size:0 ->OFF - msgs_100.pop_front(); - BOOST_CHECK(!flow->isFlowControlActive()); -} - - -QPID_AUTO_TEST_CASE(testFlowDefaultArgs) -{ - QueueFlowLimit::setDefaults(2950001, // max queue byte count - 80, // 80% stop threshold - 70); // 70% resume threshold - FieldTable args; - QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args); - - BOOST_CHECK(ptr); - std::auto_ptr<QueueFlowLimit> flow(ptr); - BOOST_CHECK_EQUAL((uint64_t) 2360001, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint64_t) 2065000, flow->getFlowResumeSize()); - BOOST_CHECK_EQUAL( 0u, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL( 0u, flow->getFlowResumeCount()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); -} - - -QPID_AUTO_TEST_CASE(testFlowOverrideArgs) -{ - QueueFlowLimit::setDefaults(2950001, // max queue byte count - 80, // 80% stop threshold - 70); // 70% resume threshold - { - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 35000); - args.setInt(QueueFlowLimit::flowResumeCountKey, 30000); - - QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(ptr); - std::auto_ptr<QueueFlowLimit> flow(ptr); - - BOOST_CHECK_EQUAL((uint32_t) 35000, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 30000, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint64_t) 0, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint64_t) 0, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - } - { - FieldTable args; - args.setInt(QueueFlowLimit::flowStopSizeKey, 350000); - args.setInt(QueueFlowLimit::flowResumeSizeKey, 300000); - - QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(ptr); - std::auto_ptr<QueueFlowLimit> flow(ptr); - - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint64_t) 350000, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint64_t) 300000, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - } - { - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 35000); - args.setInt(QueueFlowLimit::flowResumeCountKey, 30000); - args.setInt(QueueFlowLimit::flowStopSizeKey, 350000); - args.setInt(QueueFlowLimit::flowResumeSizeKey, 300000); - - QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(ptr); - std::auto_ptr<QueueFlowLimit> flow(ptr); - - BOOST_CHECK_EQUAL((uint32_t) 35000, flow->getFlowStopCount()); - BOOST_CHECK_EQUAL((uint32_t) 30000, flow->getFlowResumeCount()); - BOOST_CHECK_EQUAL((uint64_t) 350000, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint64_t) 300000, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); - } -} - - -QPID_AUTO_TEST_CASE(testFlowOverrideDefaults) -{ - QueueFlowLimit::setDefaults(2950001, // max queue byte count - 97, // stop threshold - 73); // resume threshold - FieldTable args; - QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(ptr); - std::auto_ptr<QueueFlowLimit> flow(ptr); - - BOOST_CHECK_EQUAL((uint32_t) 2861501, flow->getFlowStopSize()); - BOOST_CHECK_EQUAL((uint32_t) 2153500, flow->getFlowResumeSize()); - BOOST_CHECK(!flow->isFlowControlActive()); - BOOST_CHECK(flow->monitorFlowControl()); -} - - -QPID_AUTO_TEST_CASE(testFlowDisable) -{ - { - FieldTable args; - args.setInt(QueueFlowLimit::flowStopCountKey, 0); - QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(!ptr); - } - { - FieldTable args; - args.setInt(QueueFlowLimit::flowStopSizeKey, 0); - QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args); - BOOST_CHECK(!ptr); - } -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/QueueOptionsTest.cpp b/cpp/src/tests/QueueOptionsTest.cpp deleted file mode 100644 index f2fbaba2c1..0000000000 --- a/cpp/src/tests/QueueOptionsTest.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/framing/Array.h" -#include "qpid/client/QueueOptions.h" - -#include "unit_test.h" - -using namespace qpid::client; - - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueueOptionsTestSuite) - -QPID_AUTO_TEST_CASE(testSizePolicy) -{ - QueueOptions ft; - - ft.setSizePolicy(REJECT,1,2); - - BOOST_CHECK(QueueOptions::strREJECT == ft.getAsString(QueueOptions::strTypeKey)); - BOOST_CHECK(1 == ft.getAsInt(QueueOptions::strMaxSizeKey)); - BOOST_CHECK(2 == ft.getAsInt(QueueOptions::strMaxCountKey)); - - ft.setSizePolicy(FLOW_TO_DISK,0,2); - BOOST_CHECK(QueueOptions::strFLOW_TO_DISK == ft.getAsString(QueueOptions::strTypeKey)); - BOOST_CHECK(1 == ft.getAsInt(QueueOptions::strMaxSizeKey)); - BOOST_CHECK(2 == ft.getAsInt(QueueOptions::strMaxCountKey)); - - ft.setSizePolicy(RING,1,0); - BOOST_CHECK(QueueOptions::strRING == ft.getAsString(QueueOptions::strTypeKey)); - - ft.setSizePolicy(RING_STRICT,1,0); - BOOST_CHECK(QueueOptions::strRING_STRICT == ft.getAsString(QueueOptions::strTypeKey)); - - ft.clearSizePolicy(); - BOOST_CHECK(!ft.isSet(QueueOptions::strTypeKey)); - BOOST_CHECK(!ft.isSet(QueueOptions::strMaxSizeKey)); - BOOST_CHECK(!ft.isSet(QueueOptions::strMaxCountKey)); -} - -QPID_AUTO_TEST_CASE(testFlags) -{ - QueueOptions ft; - - ft.setPersistLastNode(); - ft.setOrdering(LVQ); - - BOOST_CHECK(1 == ft.getAsInt(QueueOptions::strPersistLastNode)); - BOOST_CHECK(1 == ft.getAsInt(QueueOptions::strLastValueQueue)); - - ft.clearPersistLastNode(); - ft.setOrdering(FIFO); - - BOOST_CHECK(!ft.isSet(QueueOptions::strPersistLastNode)); - BOOST_CHECK(!ft.isSet(QueueOptions::strLastValueQueue)); - -} - -QPID_AUTO_TEST_CASE(testSetOrdering) -{ - //ensure setOrdering(FIFO) works even if not preceded by a call to - //setOrdering(LVQ) - QueueOptions ft; - ft.setOrdering(FIFO); - BOOST_CHECK(!ft.isSet(QueueOptions::strLastValueQueue)); - -} - -QPID_AUTO_TEST_CASE(testClearPersistLastNode) -{ - //ensure clear works even if not preceded by the setting on the - //option - QueueOptions ft; - ft.clearPersistLastNode(); - BOOST_CHECK(!ft.isSet(QueueOptions::strPersistLastNode)); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/QueuePolicyTest.cpp b/cpp/src/tests/QueuePolicyTest.cpp deleted file mode 100644 index 5455105078..0000000000 --- a/cpp/src/tests/QueuePolicyTest.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <sstream> -#include "unit_test.h" -#include "test_tools.h" - -#include "qpid/broker/QueuePolicy.h" -#include "qpid/broker/QueueFlowLimit.h" -#include "qpid/client/QueueOptions.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/reply_exceptions.h" -#include "MessageUtils.h" -#include "BrokerFixture.h" - -using namespace qpid::broker; -using namespace qpid::client; -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueuePolicyTestSuite) - -namespace { -QueuedMessage createMessage(uint32_t size) -{ - QueuedMessage msg; - msg.payload = MessageUtils::createMessage(); - MessageUtils::addContent(msg.payload, std::string (size, 'x')); - return msg; -} -} - -QPID_AUTO_TEST_CASE(testCount) -{ - std::auto_ptr<QueuePolicy> policy(QueuePolicy::createQueuePolicy("test", 5, 0)); - BOOST_CHECK_EQUAL((uint64_t) 0, policy->getMaxSize()); - BOOST_CHECK_EQUAL((uint32_t) 5, policy->getMaxCount()); - - QueuedMessage msg = createMessage(10); - for (size_t i = 0; i < 5; i++) { - policy->tryEnqueue(msg.payload); - } - try { - policy->tryEnqueue(msg.payload); - BOOST_FAIL("Policy did not fail on enqueuing sixth message"); - } catch (const ResourceLimitExceededException&) {} - - policy->dequeued(msg); - policy->tryEnqueue(msg.payload); - - try { - policy->tryEnqueue(msg.payload); - BOOST_FAIL("Policy did not fail on enqueuing sixth message (after dequeue)"); - } catch (const ResourceLimitExceededException&) {} -} - -QPID_AUTO_TEST_CASE(testSize) -{ - std::auto_ptr<QueuePolicy> policy(QueuePolicy::createQueuePolicy("test", 0, 50)); - QueuedMessage msg = createMessage(10); - - for (size_t i = 0; i < 5; i++) { - policy->tryEnqueue(msg.payload); - } - try { - policy->tryEnqueue(msg.payload); - BOOST_FAIL("Policy did not fail on aggregate size exceeding 50. " << *policy); - } catch (const ResourceLimitExceededException&) {} - - policy->dequeued(msg); - policy->tryEnqueue(msg.payload); - - try { - policy->tryEnqueue(msg.payload); - BOOST_FAIL("Policy did not fail on aggregate size exceeding 50 (after dequeue). " << *policy); - } catch (const ResourceLimitExceededException&) {} -} - -QPID_AUTO_TEST_CASE(testBoth) -{ - std::auto_ptr<QueuePolicy> policy(QueuePolicy::createQueuePolicy("test", 5, 50)); - try { - QueuedMessage msg = createMessage(51); - policy->tryEnqueue(msg.payload); - BOOST_FAIL("Policy did not fail on single message exceeding 50. " << *policy); - } catch (const ResourceLimitExceededException&) {} - - std::vector<QueuedMessage> messages; - messages.push_back(createMessage(15)); - messages.push_back(createMessage(10)); - messages.push_back(createMessage(11)); - messages.push_back(createMessage(2)); - messages.push_back(createMessage(7)); - for (size_t i = 0; i < messages.size(); i++) { - policy->tryEnqueue(messages[i].payload); - } - //size = 45 at this point, count = 5 - try { - QueuedMessage msg = createMessage(5); - policy->tryEnqueue(msg.payload); - BOOST_FAIL("Policy did not fail on count exceeding 6. " << *policy); - } catch (const ResourceLimitExceededException&) {} - try { - QueuedMessage msg = createMessage(10); - policy->tryEnqueue(msg.payload); - BOOST_FAIL("Policy did not fail on aggregate size exceeding 50. " << *policy); - } catch (const ResourceLimitExceededException&) {} - - - policy->dequeued(messages[0]); - try { - QueuedMessage msg = createMessage(20); - policy->tryEnqueue(msg.payload); - } catch (const ResourceLimitExceededException&) { - BOOST_FAIL("Policy failed incorrectly after dequeue. " << *policy); - } -} - -QPID_AUTO_TEST_CASE(testSettings) -{ - //test reading and writing the policy from/to field table - std::auto_ptr<QueuePolicy> a(QueuePolicy::createQueuePolicy("test", 101, 303)); - FieldTable settings; - a->update(settings); - std::auto_ptr<QueuePolicy> b(QueuePolicy::createQueuePolicy("test", settings)); - BOOST_CHECK_EQUAL(a->getMaxCount(), b->getMaxCount()); - BOOST_CHECK_EQUAL(a->getMaxSize(), b->getMaxSize()); -} - -QPID_AUTO_TEST_CASE(testRingPolicyCount) -{ - FieldTable args; - std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::RING); - policy->update(args); - - ProxySessionFixture f; - std::string q("my-ring-queue"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - for (int i = 0; i < 10; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - client::Message msg; - for (int i = 5; i < 10; i++) { - BOOST_CHECK(f.subs.get(msg, q, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL((boost::format("%1%_%2%") % "Message" % (i+1)).str(), msg.getData()); - } - BOOST_CHECK(!f.subs.get(msg, q)); - - for (int i = 10; i < 20; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 15; i < 20; i++) { - BOOST_CHECK(f.subs.get(msg, q, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL((boost::format("%1%_%2%") % "Message" % (i+1)).str(), msg.getData()); - } - BOOST_CHECK(!f.subs.get(msg, q)); -} - -QPID_AUTO_TEST_CASE(testRingPolicySize) -{ - std::string hundredBytes = std::string(100, 'h'); - std::string fourHundredBytes = std::string (400, 'f'); - std::string thousandBytes = std::string(1000, 't'); - - // Ring queue, 500 bytes maxSize - - FieldTable args; - std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 0, 500, QueuePolicy::RING); - policy->update(args); - - ProxySessionFixture f; - std::string q("my-ring-queue"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - - // A. Send messages 0 .. 5, each 100 bytes - - client::Message m(hundredBytes, q); - - for (int i = 0; i < 6; i++) { - std::stringstream id; - id << i; - m.getMessageProperties().setCorrelationId(id.str()); - f.session.messageTransfer(arg::content=m); - } - - // should find 1 .. 5 on the queue, 0 is displaced by 5 - client::Message msg; - for (int i = 1; i < 6; i++) { - std::stringstream id; - id << i; - BOOST_CHECK(f.subs.get(msg, q, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL(msg.getMessageProperties().getCorrelationId(), id.str()); - } - BOOST_CHECK(!f.subs.get(msg, q)); - - // B. Now make sure that one 400 byte message displaces four 100 byte messages - - // Send messages 0 .. 5, each 100 bytes - for (int i = 0; i < 6; i++) { - client::Message m(hundredBytes, q); - std::stringstream id; - id << i; - m.getMessageProperties().setCorrelationId(id.str()); - f.session.messageTransfer(arg::content=m); - } - - // Now send one 400 byte message - client::Message m2(fourHundredBytes, q); - m2.getMessageProperties().setCorrelationId("6"); - f.session.messageTransfer(arg::content=m2); - - // expect to see 5, 6 on the queue - for (int i = 5; i < 7; i++) { - std::stringstream id; - id << i; - BOOST_CHECK(f.subs.get(msg, q, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL(msg.getMessageProperties().getCorrelationId(), id.str()); - } - BOOST_CHECK(!f.subs.get(msg, q)); - - - // C. Try sending a 1000-byte message, should fail - exceeds maxSize of queue - - client::Message m3(thousandBytes, q); - m3.getMessageProperties().setCorrelationId("6"); - try { - ScopedSuppressLogging sl; - f.session.messageTransfer(arg::content=m3); - BOOST_FAIL("Ooops - successfully added a 1000 byte message to a 512 byte ring queue ..."); - } - catch (...) { - } - -} - - -QPID_AUTO_TEST_CASE(testStrictRingPolicy) -{ - FieldTable args; - std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::RING_STRICT); - policy->update(args); - - ProxySessionFixture f; - std::string q("my-ring-queue"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - LocalQueue incoming; - SubscriptionSettings settings(FlowControl::unlimited()); - settings.autoAck = 0; // no auto ack. - Subscription sub = f.subs.subscribe(incoming, q, settings); - for (int i = 0; i < 5; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 0; i < 5; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f.session.messageTransfer(arg::content=client::Message("Message_6", q)); - BOOST_FAIL("expecting ResourceLimitExceededException."); - } catch (const ResourceLimitExceededException&) {} -} - -QPID_AUTO_TEST_CASE(testPolicyWithDtx) -{ - FieldTable args; - std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::REJECT); - policy->update(args); - - ProxySessionFixture f; - std::string q("my-policy-queue"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - LocalQueue incoming; - SubscriptionSettings settings(FlowControl::unlimited()); - settings.autoAck = 0; // no auto ack. - Subscription sub = f.subs.subscribe(incoming, q, settings); - f.session.dtxSelect(); - Xid tx1(1, "test-dtx-mgr", "tx1"); - f.session.dtxStart(arg::xid=tx1); - for (int i = 0; i < 5; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - f.session.dtxEnd(arg::xid=tx1); - f.session.dtxCommit(arg::xid=tx1, arg::onePhase=true); - - Xid tx2(1, "test-dtx-mgr", "tx2"); - f.session.dtxStart(arg::xid=tx2); - for (int i = 0; i < 5; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - SequenceSet accepting=sub.getUnaccepted(); - f.session.messageAccept(accepting); - f.session.dtxEnd(arg::xid=tx2); - f.session.dtxPrepare(arg::xid=tx2); - f.session.dtxRollback(arg::xid=tx2); - f.session.messageRelease(accepting); - - Xid tx3(1, "test-dtx-mgr", "tx3"); - f.session.dtxStart(arg::xid=tx3); - for (int i = 0; i < 5; i++) { - incoming.pop(); - } - accepting=sub.getUnaccepted(); - f.session.messageAccept(accepting); - f.session.dtxEnd(arg::xid=tx3); - f.session.dtxPrepare(arg::xid=tx3); - - Session other = f.connection.newSession(); - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - other.messageTransfer(arg::content=client::Message("Message_6", q)); - BOOST_FAIL("expecting ResourceLimitExceededException."); - } catch (const ResourceLimitExceededException&) {} - - f.session.dtxCommit(arg::xid=tx3); - //now retry and this time should succeed - other = f.connection.newSession(); - other.messageTransfer(arg::content=client::Message("Message_6", q)); -} - -QPID_AUTO_TEST_CASE(testFlowToDiskWithNoStore) -{ - //Ensure that with no store loaded, we don't flow to disk but - //fallback to rejecting messages - QueueOptions args; - args.setSizePolicy(FLOW_TO_DISK, 0, 5); - // Disable flow control, or else we'll never hit the max limit - args.setInt(QueueFlowLimit::flowStopCountKey, 0); - - ProxySessionFixture f; - std::string q("my-queue"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - LocalQueue incoming; - SubscriptionSettings settings(FlowControl::unlimited()); - settings.autoAck = 0; // no auto ack. - Subscription sub = f.subs.subscribe(incoming, q, settings); - for (int i = 0; i < 5; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - for (int i = 0; i < 5; i++) { - BOOST_CHECK_EQUAL(incoming.pop().getData(), (boost::format("%1%_%2%") % "Message" % (i+1)).str()); - } - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f.session.messageTransfer(arg::content=client::Message("Message_6", q)); - BOOST_FAIL("expecting ResourceLimitExceededException."); - } catch (const ResourceLimitExceededException&) {} -} - -QPID_AUTO_TEST_CASE(testPolicyFailureOnCommit) -{ - FieldTable args; - std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::REJECT); - policy->update(args); - - ProxySessionFixture f; - std::string q("q"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - f.session.txSelect(); - for (int i = 0; i < 10; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - ScopedSuppressLogging sl; // Suppress messages for expected errors. - BOOST_CHECK_THROW(f.session.txCommit(), InternalErrorException); -} - -QPID_AUTO_TEST_CASE(testCapacityConversion) -{ - FieldTable args; - args.setString("qpid.max_count", "5"); - args.setString("qpid.flow_stop_count", "0"); - - ProxySessionFixture f; - std::string q("q"); - f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - for (int i = 0; i < 5; i++) { - f.session.messageTransfer(arg::content=client::Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), q)); - } - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f.session.messageTransfer(arg::content=client::Message("Message_6", q)); - BOOST_FAIL("expecting ResourceLimitExceededException."); - } catch (const ResourceLimitExceededException&) {} -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/QueueRegistryTest.cpp b/cpp/src/tests/QueueRegistryTest.cpp deleted file mode 100644 index ae555539a4..0000000000 --- a/cpp/src/tests/QueueRegistryTest.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/Queue.h" -#include "unit_test.h" -#include <string> - -using namespace qpid::broker; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(QueueRegistryTest) - -QPID_AUTO_TEST_CASE(testDeclare) -{ - std::string foo("foo"); - std::string bar("bar"); - QueueRegistry reg; - std::pair<Queue::shared_ptr, bool> qc; - - qc = reg.declare(foo, false, 0, 0); - Queue::shared_ptr q = qc.first; - BOOST_CHECK(q); - BOOST_CHECK(qc.second); // New queue - BOOST_CHECK_EQUAL(foo, q->getName()); - - qc = reg.declare(foo, false, 0, 0); - BOOST_CHECK_EQUAL(q, qc.first); - BOOST_CHECK(!qc.second); - - qc = reg.declare(bar, false, 0, 0); - q = qc.first; - BOOST_CHECK(q); - BOOST_CHECK_EQUAL(true, qc.second); - BOOST_CHECK_EQUAL(bar, q->getName()); -} - -QPID_AUTO_TEST_CASE(testDeclareTmp) -{ - QueueRegistry reg; - std::pair<Queue::shared_ptr, bool> qc; - - qc = reg.declare(std::string(), false, 0, 0); - BOOST_CHECK(qc.second); - BOOST_CHECK_EQUAL(std::string("tmp_1"), qc.first->getName()); -} - -QPID_AUTO_TEST_CASE(testFind) -{ - std::string foo("foo"); - std::string bar("bar"); - QueueRegistry reg; - std::pair<Queue::shared_ptr, bool> qc; - - BOOST_CHECK(reg.find(foo) == 0); - - reg.declare(foo, false, 0, 0); - reg.declare(bar, false, 0, 0); - Queue::shared_ptr q = reg.find(bar); - BOOST_CHECK(q); - BOOST_CHECK_EQUAL(bar, q->getName()); -} - -QPID_AUTO_TEST_CASE(testDestroy) -{ - std::string foo("foo"); - QueueRegistry reg; - std::pair<Queue::shared_ptr, bool> qc; - - qc = reg.declare(foo, false, 0, 0); - reg.destroy(foo); - // Queue is gone from the registry. - BOOST_CHECK(reg.find(foo) == 0); - // Queue is not actually destroyed till we drop our reference. - BOOST_CHECK_EQUAL(foo, qc.first->getName()); - // We shoud be the only reference. - BOOST_CHECK_EQUAL(1L, qc.first.use_count()); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/QueueTest.cpp b/cpp/src/tests/QueueTest.cpp deleted file mode 100644 index 34e4592a15..0000000000 --- a/cpp/src/tests/QueueTest.cpp +++ /dev/null @@ -1,1124 +0,0 @@ - /* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "MessageUtils.h" -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/Exception.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/client/QueueOptions.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/broker/QueuePolicy.h" -#include "qpid/broker/QueueFlowLimit.h" - -#include <iostream> -#include "boost/format.hpp" - -using boost::intrusive_ptr; -using namespace qpid; -using namespace qpid::broker; -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -class TestConsumer : public virtual Consumer{ -public: - typedef boost::shared_ptr<TestConsumer> shared_ptr; - - intrusive_ptr<Message> last; - bool received; - TestConsumer(bool acquire = true):Consumer(acquire), received(false) {}; - - virtual bool deliver(QueuedMessage& msg){ - last = msg.payload; - received = true; - return true; - }; - void notify() {} - OwnershipToken* getSession() { return 0; } -}; - -class FailOnDeliver : public Deliverable -{ - boost::intrusive_ptr<Message> msg; -public: - FailOnDeliver() : msg(MessageUtils::createMessage()) {} - void deliverTo(const boost::shared_ptr<Queue>& queue) - { - throw Exception(QPID_MSG("Invalid delivery to " << queue->getName())); - } - Message& getMessage() { return *(msg.get()); } -}; - -intrusive_ptr<Message> create_message(std::string exchange, std::string routingKey) { - intrusive_ptr<Message> msg(new Message()); - AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange, 0, 0))); - AMQFrame header((AMQHeaderBody())); - msg->getFrames().append(method); - msg->getFrames().append(header); - msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setRoutingKey(routingKey); - return msg; -} - -QPID_AUTO_TEST_SUITE(QueueTestSuite) - -QPID_AUTO_TEST_CASE(testAsyncMessage) { - Queue::shared_ptr queue(new Queue("my_test_queue", true)); - intrusive_ptr<Message> received; - - TestConsumer::shared_ptr c1(new TestConsumer()); - queue->consume(c1); - - - //Test basic delivery: - intrusive_ptr<Message> msg1 = create_message("e", "A"); - msg1->enqueueAsync(queue, 0);//this is done on enqueue which is not called from process - queue->process(msg1); - sleep(2); - - BOOST_CHECK(!c1->received); - msg1->enqueueComplete(); - - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg1.get(), received.get()); -} - - -QPID_AUTO_TEST_CASE(testAsyncMessageCount){ - Queue::shared_ptr queue(new Queue("my_test_queue", true)); - intrusive_ptr<Message> msg1 = create_message("e", "A"); - msg1->enqueueAsync(queue, 0);//this is done on enqueue which is not called from process - - queue->process(msg1); - sleep(2); - uint32_t compval=0; - BOOST_CHECK_EQUAL(compval, queue->getEnqueueCompleteMessageCount()); - msg1->enqueueComplete(); - compval=1; - BOOST_CHECK_EQUAL(compval, queue->getEnqueueCompleteMessageCount()); - BOOST_CHECK_EQUAL(compval, queue->getMessageCount()); -} - -QPID_AUTO_TEST_CASE(testConsumers){ - Queue::shared_ptr queue(new Queue("my_queue", true)); - - //Test adding consumers: - TestConsumer::shared_ptr c1(new TestConsumer()); - TestConsumer::shared_ptr c2(new TestConsumer()); - queue->consume(c1); - queue->consume(c2); - - BOOST_CHECK_EQUAL(uint32_t(2), queue->getConsumerCount()); - - //Test basic delivery: - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "B"); - intrusive_ptr<Message> msg3 = create_message("e", "C"); - - queue->deliver(msg1); - BOOST_CHECK(queue->dispatch(c1)); - BOOST_CHECK_EQUAL(msg1.get(), c1->last.get()); - - queue->deliver(msg2); - BOOST_CHECK(queue->dispatch(c2)); - BOOST_CHECK_EQUAL(msg2.get(), c2->last.get()); - - c1->received = false; - queue->deliver(msg3); - BOOST_CHECK(queue->dispatch(c1)); - BOOST_CHECK_EQUAL(msg3.get(), c1->last.get()); - - //Test cancellation: - queue->cancel(c1); - BOOST_CHECK_EQUAL(uint32_t(1), queue->getConsumerCount()); - queue->cancel(c2); - BOOST_CHECK_EQUAL(uint32_t(0), queue->getConsumerCount()); -} - -QPID_AUTO_TEST_CASE(testRegistry){ - //Test use of queues in registry: - QueueRegistry registry; - registry.declare("queue1", true, true); - registry.declare("queue2", true, true); - registry.declare("queue3", true, true); - - BOOST_CHECK(registry.find("queue1")); - BOOST_CHECK(registry.find("queue2")); - BOOST_CHECK(registry.find("queue3")); - - registry.destroy("queue1"); - registry.destroy("queue2"); - registry.destroy("queue3"); - - BOOST_CHECK(!registry.find("queue1")); - BOOST_CHECK(!registry.find("queue2")); - BOOST_CHECK(!registry.find("queue3")); -} - -QPID_AUTO_TEST_CASE(testDequeue){ - Queue::shared_ptr queue(new Queue("my_queue", true)); - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "B"); - intrusive_ptr<Message> msg3 = create_message("e", "C"); - intrusive_ptr<Message> received; - - queue->deliver(msg1); - queue->deliver(msg2); - queue->deliver(msg3); - - BOOST_CHECK_EQUAL(uint32_t(3), queue->getMessageCount()); - - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg1.get(), received.get()); - BOOST_CHECK_EQUAL(uint32_t(2), queue->getMessageCount()); - - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg2.get(), received.get()); - BOOST_CHECK_EQUAL(uint32_t(1), queue->getMessageCount()); - - TestConsumer::shared_ptr consumer(new TestConsumer()); - queue->consume(consumer); - queue->dispatch(consumer); - if (!consumer->received) - sleep(2); - - BOOST_CHECK_EQUAL(msg3.get(), consumer->last.get()); - BOOST_CHECK_EQUAL(uint32_t(0), queue->getMessageCount()); - - received = queue->get().payload; - BOOST_CHECK(!received); - BOOST_CHECK_EQUAL(uint32_t(0), queue->getMessageCount()); - -} - -QPID_AUTO_TEST_CASE(testBound){ - //test the recording of bindings, and use of those to allow a queue to be unbound - string key("my-key"); - FieldTable args; - - Queue::shared_ptr queue(new Queue("my-queue", true)); - ExchangeRegistry exchanges; - //establish bindings from exchange->queue and notify the queue as it is bound: - Exchange::shared_ptr exchange1 = exchanges.declare("my-exchange-1", "direct").first; - exchange1->bind(queue, key, &args); - queue->bound(exchange1->getName(), key, args); - - Exchange::shared_ptr exchange2 = exchanges.declare("my-exchange-2", "fanout").first; - exchange2->bind(queue, key, &args); - queue->bound(exchange2->getName(), key, args); - - Exchange::shared_ptr exchange3 = exchanges.declare("my-exchange-3", "topic").first; - exchange3->bind(queue, key, &args); - queue->bound(exchange3->getName(), key, args); - - //delete one of the exchanges: - exchanges.destroy(exchange2->getName()); - exchange2.reset(); - - //unbind the queue from all exchanges it knows it has been bound to: - queue->unbind(exchanges); - - //ensure the remaining exchanges don't still have the queue bound to them: - FailOnDeliver deliverable; - exchange1->route(deliverable, key, &args); - exchange3->route(deliverable, key, &args); -} - -QPID_AUTO_TEST_CASE(testPersistLastNodeStanding){ - client::QueueOptions args; - args.setPersistLastNode(); - - Queue::shared_ptr queue(new Queue("my-queue", true)); - queue->configure(args); - - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "B"); - intrusive_ptr<Message> msg3 = create_message("e", "C"); - - //enqueue 2 messages - queue->deliver(msg1); - queue->deliver(msg2); - - //change mode - queue->setLastNodeFailure(); - - //enqueue 1 message - queue->deliver(msg3); - - //check all have persistent ids. - BOOST_CHECK(msg1->isPersistent()); - BOOST_CHECK(msg2->isPersistent()); - BOOST_CHECK(msg3->isPersistent()); - -} - - -QPID_AUTO_TEST_CASE(testSeek){ - - Queue::shared_ptr queue(new Queue("my-queue", true)); - - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "B"); - intrusive_ptr<Message> msg3 = create_message("e", "C"); - - //enqueue 2 messages - queue->deliver(msg1); - queue->deliver(msg2); - queue->deliver(msg3); - - TestConsumer::shared_ptr consumer(new TestConsumer(false)); - SequenceNumber seq(2); - consumer->position = seq; - - QueuedMessage qm; - queue->dispatch(consumer); - - BOOST_CHECK_EQUAL(msg3.get(), consumer->last.get()); - queue->dispatch(consumer); - queue->dispatch(consumer); // make sure over-run is safe - -} - -QPID_AUTO_TEST_CASE(testSearch){ - - Queue::shared_ptr queue(new Queue("my-queue", true)); - - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "B"); - intrusive_ptr<Message> msg3 = create_message("e", "C"); - - //enqueue 2 messages - queue->deliver(msg1); - queue->deliver(msg2); - queue->deliver(msg3); - - SequenceNumber seq(2); - QueuedMessage qm = queue->find(seq); - - BOOST_CHECK_EQUAL(seq.getValue(), qm.position.getValue()); - - queue->acquire(qm); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 2u); - SequenceNumber seq1(3); - QueuedMessage qm1 = queue->find(seq1); - BOOST_CHECK_EQUAL(seq1.getValue(), qm1.position.getValue()); - -} -const std::string nullxid = ""; - -class SimpleDummyCtxt : public TransactionContext {}; - -class DummyCtxt : public TPCTransactionContext -{ - const std::string xid; - public: - DummyCtxt(const std::string& _xid) : xid(_xid) {} - static std::string getXid(TransactionContext& ctxt) - { - DummyCtxt* c(dynamic_cast<DummyCtxt*>(&ctxt)); - return c ? c->xid : nullxid; - } -}; - -class TestMessageStoreOC : public MessageStore -{ - std::set<std::string> prepared; - uint64_t nextPersistenceId; - public: - - uint enqCnt; - uint deqCnt; - bool error; - - TestMessageStoreOC() : MessageStore(),nextPersistenceId(1),enqCnt(0),deqCnt(0),error(false) {} - ~TestMessageStoreOC(){} - - virtual void dequeue(TransactionContext*, - const boost::intrusive_ptr<PersistableMessage>& /*msg*/, - const PersistableQueue& /*queue*/) - { - if (error) throw Exception("Dequeue error test"); - deqCnt++; - } - - virtual void enqueue(TransactionContext*, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& /* queue */) - { - if (error) throw Exception("Enqueue error test"); - enqCnt++; - msg->enqueueComplete(); - } - - void createError() - { - error=true; - } - - bool init(const Options*) { return true; } - void truncateInit(const bool) {} - void create(PersistableQueue& queue, const framing::FieldTable&) { queue.setPersistenceId(nextPersistenceId++); } - void destroy(PersistableQueue&) {} - void create(const PersistableExchange& exchange, const framing::FieldTable&) { exchange.setPersistenceId(nextPersistenceId++); } - void destroy(const PersistableExchange&) {} - void bind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&) {} - void unbind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&) {} - void create(const PersistableConfig& config) { config.setPersistenceId(nextPersistenceId++); } - void destroy(const PersistableConfig&) {} - void stage(const boost::intrusive_ptr<PersistableMessage>&) {} - void destroy(PersistableMessage&) {} - void appendContent(const boost::intrusive_ptr<const PersistableMessage>&, const std::string&) {} - void loadContent(const qpid::broker::PersistableQueue&, const boost::intrusive_ptr<const PersistableMessage>&, - std::string&, uint64_t, uint32_t) { throw qpid::framing::InternalErrorException("Can't load content; persistence not enabled"); } - void flush(const qpid::broker::PersistableQueue&) {} - uint32_t outstandingQueueAIO(const PersistableQueue&) { return 0; } - - std::auto_ptr<TransactionContext> begin() { return std::auto_ptr<TransactionContext>(new SimpleDummyCtxt()); } - std::auto_ptr<TPCTransactionContext> begin(const std::string& xid) { return std::auto_ptr<TPCTransactionContext>(new DummyCtxt(xid)); } - void prepare(TPCTransactionContext& ctxt) { prepared.insert(DummyCtxt::getXid(ctxt)); } - void commit(TransactionContext& ctxt) { prepared.erase(DummyCtxt::getXid(ctxt)); } - void abort(TransactionContext& ctxt) { prepared.erase(DummyCtxt::getXid(ctxt)); } - void collectPreparedXids(std::set<std::string>& out) { out.insert(prepared.begin(), prepared.end()); } - - void recover(RecoveryManager&) {} -}; - - -QPID_AUTO_TEST_CASE(testLVQOrdering){ - - client::QueueOptions args; - // set queue mode - args.setOrdering(client::LVQ); - - Queue::shared_ptr queue(new Queue("my-queue", true )); - queue->configure(args); - - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "B"); - intrusive_ptr<Message> msg3 = create_message("e", "C"); - intrusive_ptr<Message> msg4 = create_message("e", "D"); - intrusive_ptr<Message> received; - - //set deliever match for LVQ a,b,c,a - - string key; - args.getLVQKey(key); - BOOST_CHECK_EQUAL(key, "qpid.LVQ_key"); - - - msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b"); - msg3->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c"); - msg4->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - - //enqueue 4 message - queue->deliver(msg1); - queue->deliver(msg2); - queue->deliver(msg3); - queue->deliver(msg4); - - BOOST_CHECK_EQUAL(queue->getMessageCount(), 3u); - - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg4.get(), received.get()); - - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg2.get(), received.get()); - - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg3.get(), received.get()); - - intrusive_ptr<Message> msg5 = create_message("e", "A"); - intrusive_ptr<Message> msg6 = create_message("e", "B"); - intrusive_ptr<Message> msg7 = create_message("e", "C"); - msg5->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - msg6->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b"); - msg7->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c"); - queue->deliver(msg5); - queue->deliver(msg6); - queue->deliver(msg7); - - BOOST_CHECK_EQUAL(queue->getMessageCount(), 3u); - - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg5.get(), received.get()); - - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg6.get(), received.get()); - - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg7.get(), received.get()); - -} - -QPID_AUTO_TEST_CASE(testLVQEmptyKey){ - - client::QueueOptions args; - // set queue mode - args.setOrdering(client::LVQ); - - Queue::shared_ptr queue(new Queue("my-queue", true )); - queue->configure(args); - - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "B"); - - string key; - args.getLVQKey(key); - BOOST_CHECK_EQUAL(key, "qpid.LVQ_key"); - - - msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - queue->deliver(msg1); - queue->deliver(msg2); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 2u); - -} - -QPID_AUTO_TEST_CASE(testLVQAcquire){ - - client::QueueOptions args; - // set queue mode - args.setOrdering(client::LVQ); - // disable flow control, as this test violates the enqueue/dequeue sequence. - args.setInt(QueueFlowLimit::flowStopCountKey, 0); - - Queue::shared_ptr queue(new Queue("my-queue", true )); - queue->configure(args); - - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "B"); - intrusive_ptr<Message> msg3 = create_message("e", "C"); - intrusive_ptr<Message> msg4 = create_message("e", "D"); - intrusive_ptr<Message> msg5 = create_message("e", "F"); - intrusive_ptr<Message> msg6 = create_message("e", "G"); - - //set deliever match for LVQ a,b,c,a - - string key; - args.getLVQKey(key); - BOOST_CHECK_EQUAL(key, "qpid.LVQ_key"); - - - msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b"); - msg3->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c"); - msg4->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - msg5->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b"); - msg6->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c"); - - //enqueue 4 message - queue->deliver(msg1); - queue->deliver(msg2); - queue->deliver(msg3); - queue->deliver(msg4); - - BOOST_CHECK_EQUAL(queue->getMessageCount(), 3u); - - framing::SequenceNumber sequence(1); - QueuedMessage qmsg(queue.get(), msg1, sequence); - QueuedMessage qmsg2(queue.get(), msg2, ++sequence); - framing::SequenceNumber sequence1(10); - QueuedMessage qmsg3(queue.get(), 0, sequence1); - - BOOST_CHECK(!queue->acquire(qmsg)); - BOOST_CHECK(queue->acquire(qmsg2)); - // Acquire the massage again to test failure case. - BOOST_CHECK(!queue->acquire(qmsg2)); - BOOST_CHECK(!queue->acquire(qmsg3)); - - BOOST_CHECK_EQUAL(queue->getMessageCount(), 2u); - - queue->deliver(msg5); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 3u); - - // set mode to no browse and check - args.setOrdering(client::LVQ_NO_BROWSE); - queue->configure(args); - TestConsumer::shared_ptr c1(new TestConsumer(false)); - - queue->dispatch(c1); - queue->dispatch(c1); - queue->dispatch(c1); - - queue->deliver(msg6); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 3u); - - intrusive_ptr<Message> received; - received = queue->get().payload; - BOOST_CHECK_EQUAL(msg4.get(), received.get()); - -} - -QPID_AUTO_TEST_CASE(testLVQMultiQueue){ - - client::QueueOptions args; - // set queue mode - args.setOrdering(client::LVQ); - - Queue::shared_ptr queue1(new Queue("my-queue", true )); - Queue::shared_ptr queue2(new Queue("my-queue", true )); - intrusive_ptr<Message> received; - queue1->configure(args); - queue2->configure(args); - - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "A"); - - string key; - args.getLVQKey(key); - BOOST_CHECK_EQUAL(key, "qpid.LVQ_key"); - - msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - - queue1->deliver(msg1); - queue2->deliver(msg1); - queue1->deliver(msg2); - - received = queue1->get().payload; - BOOST_CHECK_EQUAL(msg2.get(), received.get()); - - received = queue2->get().payload; - BOOST_CHECK_EQUAL(msg1.get(), received.get()); - -} - -QPID_AUTO_TEST_CASE(testLVQRecover){ - -/* simulate this - 1. start 2 nodes - 2. create cluster durable lvq - 3. send a transient message to the queue - 4. kill one of the nodes (to trigger force persistent behaviour)... - 5. then restart it (to turn off force persistent behaviour) - 6. send another transient message with same lvq key as in 3 - 7. kill the second node again (retrigger force persistent) - 8. stop and recover the first node -*/ - TestMessageStoreOC testStore; - client::QueueOptions args; - // set queue mode - args.setOrdering(client::LVQ); - args.setPersistLastNode(); - - Queue::shared_ptr queue1(new Queue("my-queue", true, &testStore)); - intrusive_ptr<Message> received; - queue1->create(args); - - intrusive_ptr<Message> msg1 = create_message("e", "A"); - intrusive_ptr<Message> msg2 = create_message("e", "A"); - // 2 - string key; - args.getLVQKey(key); - BOOST_CHECK_EQUAL(key, "qpid.LVQ_key"); - - msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a"); - // 3 - queue1->deliver(msg1); - // 4 - queue1->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 1u); - // 5 - queue1->clearLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 1u); - // 6 - queue1->deliver(msg2); - BOOST_CHECK_EQUAL(testStore.enqCnt, 1u); - queue1->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 2u); - BOOST_CHECK_EQUAL(testStore.deqCnt, 1u); -} - -void addMessagesToQueue(uint count, Queue& queue, uint oddTtl = 200, uint evenTtl = 0) -{ - for (uint i = 0; i < count; i++) { - intrusive_ptr<Message> m = create_message("exchange", "key"); - if (i % 2) { - if (oddTtl) m->getProperties<DeliveryProperties>()->setTtl(oddTtl); - } else { - if (evenTtl) m->getProperties<DeliveryProperties>()->setTtl(evenTtl); - } - m->setTimestamp(new broker::ExpiryPolicy); - queue.deliver(m); - } -} - -QPID_AUTO_TEST_CASE(testPurgeExpired) { - Queue queue("my-queue"); - addMessagesToQueue(10, queue); - BOOST_CHECK_EQUAL(queue.getMessageCount(), 10u); - ::usleep(300*1000); - queue.purgeExpired(); - BOOST_CHECK_EQUAL(queue.getMessageCount(), 5u); -} - -QPID_AUTO_TEST_CASE(testQueueCleaner) { - Timer timer; - QueueRegistry queues; - Queue::shared_ptr queue = queues.declare("my-queue").first; - addMessagesToQueue(10, *queue, 200, 400); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 10u); - - QueueCleaner cleaner(queues, timer); - cleaner.start(100 * qpid::sys::TIME_MSEC); - ::usleep(300*1000); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 5u); - ::usleep(300*1000); - BOOST_CHECK_EQUAL(queue->getMessageCount(), 0u); -} - -QPID_AUTO_TEST_CASE(testMultiQueueLastNode){ - - TestMessageStoreOC testStore; - client::QueueOptions args; - args.setPersistLastNode(); - - Queue::shared_ptr queue1(new Queue("queue1", true, &testStore )); - queue1->create(args); - Queue::shared_ptr queue2(new Queue("queue2", true, &testStore )); - queue2->create(args); - - intrusive_ptr<Message> msg1 = create_message("e", "A"); - - queue1->deliver(msg1); - queue2->deliver(msg1); - - //change mode - queue1->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 1u); - queue2->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 2u); - - // check they don't get stored twice - queue1->setLastNodeFailure(); - queue2->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 2u); - - intrusive_ptr<Message> msg2 = create_message("e", "B"); - queue1->deliver(msg2); - queue2->deliver(msg2); - - queue1->clearLastNodeFailure(); - queue2->clearLastNodeFailure(); - // check only new messages get forced - queue1->setLastNodeFailure(); - queue2->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 4u); - - // check no failure messages are stored - queue1->clearLastNodeFailure(); - queue2->clearLastNodeFailure(); - - intrusive_ptr<Message> msg3 = create_message("e", "B"); - queue1->deliver(msg3); - queue2->deliver(msg3); - BOOST_CHECK_EQUAL(testStore.enqCnt, 4u); - queue1->setLastNodeFailure(); - queue2->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 6u); - - // check requeue 1 - intrusive_ptr<Message> msg4 = create_message("e", "C"); - intrusive_ptr<Message> msg5 = create_message("e", "D"); - - framing::SequenceNumber sequence(1); - QueuedMessage qmsg1(queue1.get(), msg4, sequence); - QueuedMessage qmsg2(queue2.get(), msg5, ++sequence); - - queue1->requeue(qmsg1); - BOOST_CHECK_EQUAL(testStore.enqCnt, 7u); - - // check requeue 2 - queue2->clearLastNodeFailure(); - queue2->requeue(qmsg2); - BOOST_CHECK_EQUAL(testStore.enqCnt, 7u); - queue2->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 8u); - - queue2->clearLastNodeFailure(); - queue2->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 8u); -} - -QPID_AUTO_TEST_CASE(testLastNodeRecoverAndFail){ -/* -simulate this: - 1. start two nodes - 2. create cluster durable queue and add some messages - 3. kill one node (trigger force-persistent behaviour) - 4. stop and recover remaining node - 5. add another node - 6. kill that new node again -make sure that an attempt to re-enqueue a message does not happen which will -result in the last man standing exiting with an error. - -we need to make sure that recover is safe, i.e. messages are -not requeued to the store. -*/ - TestMessageStoreOC testStore; - client::QueueOptions args; - // set queue mode - args.setPersistLastNode(); - - Queue::shared_ptr queue1(new Queue("my-queue", true, &testStore)); - intrusive_ptr<Message> received; - queue1->create(args); - - // check requeue 1 - intrusive_ptr<Message> msg1 = create_message("e", "C"); - intrusive_ptr<Message> msg2 = create_message("e", "D"); - - queue1->recover(msg1); - - queue1->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 0u); - - queue1->clearLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 0u); - - queue1->deliver(msg2); - BOOST_CHECK_EQUAL(testStore.enqCnt, 0u); - queue1->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 1u); - -} - -QPID_AUTO_TEST_CASE(testLastNodeJournalError){ -/* -simulate store exception going into last node standing - -*/ - TestMessageStoreOC testStore; - client::QueueOptions args; - // set queue mode - args.setPersistLastNode(); - - Queue::shared_ptr queue1(new Queue("my-queue", true, &testStore)); - intrusive_ptr<Message> received; - queue1->configure(args); - - // check requeue 1 - intrusive_ptr<Message> msg1 = create_message("e", "C"); - - queue1->deliver(msg1); - testStore.createError(); - - ScopedSuppressLogging sl; // Suppress messages for expected errors. - queue1->setLastNodeFailure(); - BOOST_CHECK_EQUAL(testStore.enqCnt, 0u); - -} - -intrusive_ptr<Message> mkMsg(MessageStore& store, std::string content = "", bool durable = false) -{ - intrusive_ptr<Message> msg = MessageUtils::createMessage("", "", durable); - if (content.size()) MessageUtils::addContent(msg, content); - msg->setStore(&store); - return msg; -} - -QPID_AUTO_TEST_CASE(testFlowToDiskBlocking){ - - TestMessageStoreOC testStore; - client::QueueOptions args0; // No size policy - client::QueueOptions args1; - args1.setSizePolicy(FLOW_TO_DISK, 0, 1); - client::QueueOptions args2; - args2.setSizePolicy(FLOW_TO_DISK, 0, 2); - - // --- Fanout exchange bound to single transient queue ------------------------------------------------------------- - - FanOutExchange sbtFanout1("sbtFanout1", false, args0); // single binding to transient queue - Queue::shared_ptr tq1(new Queue("tq1", true)); // transient w/ limit - tq1->configure(args1); - sbtFanout1.bind(tq1, "", 0); - - intrusive_ptr<Message> msg01 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content - DeliverableMessage dmsg01(msg01); - sbtFanout1.route(dmsg01, "", 0); // Brings queue 1 to capacity limit - msg01->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg01->isContentReleased(), false); - BOOST_CHECK_EQUAL(1u, tq1->getMessageCount()); - - intrusive_ptr<Message> msg02 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content - DeliverableMessage dmsg02(msg02); - { - ScopedSuppressLogging sl; // suppress expected error messages. - BOOST_CHECK_THROW(sbtFanout1.route(dmsg02, "", 0), ResourceLimitExceededException); - } - msg02->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg02->isContentReleased(), false); - BOOST_CHECK_EQUAL(1u, tq1->getMessageCount()); - - intrusive_ptr<Message> msg03 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content - DeliverableMessage dmsg03(msg03); - { - ScopedSuppressLogging sl; // suppress expected error messages. - BOOST_CHECK_THROW(sbtFanout1.route(dmsg03, "", 0), ResourceLimitExceededException); - } - msg03->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg03->isContentReleased(), false); - BOOST_CHECK_EQUAL(1u, tq1->getMessageCount()); - - intrusive_ptr<Message> msg04 = mkMsg(testStore); // transient no content - DeliverableMessage dmsg04(msg04); - { - ScopedSuppressLogging sl; // suppress expected error messages. - BOOST_CHECK_THROW(sbtFanout1.route(dmsg04, "", 0), ResourceLimitExceededException); - } - msg04->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg04->isContentReleased(), false); - BOOST_CHECK_EQUAL(1u, tq1->getMessageCount()); - - intrusive_ptr<Message> msg05 = mkMsg(testStore, "", true); // durable no content - DeliverableMessage dmsg05(msg05); - { - ScopedSuppressLogging sl; // suppress expected error messages. - BOOST_CHECK_THROW(sbtFanout1.route(dmsg05, "", 0), ResourceLimitExceededException); - } - msg05->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg05->isContentReleased(), false); - BOOST_CHECK_EQUAL(1u, tq1->getMessageCount()); - - // --- Fanout exchange bound to single durable queue --------------------------------------------------------------- - - FanOutExchange sbdFanout2("sbdFanout2", false, args0); // single binding to durable queue - Queue::shared_ptr dq2(new Queue("dq2", true, &testStore)); // durable w/ limit - dq2->configure(args1); - sbdFanout2.bind(dq2, "", 0); - - intrusive_ptr<Message> msg06 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content - DeliverableMessage dmsg06(msg06); - sbdFanout2.route(dmsg06, "", 0); // Brings queue 2 to capacity limit - msg06->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg06->isContentReleased(), false); - BOOST_CHECK_EQUAL(1u, dq2->getMessageCount()); - - intrusive_ptr<Message> msg07 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content - DeliverableMessage dmsg07(msg07); - sbdFanout2.route(dmsg07, "", 0); - msg07->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg07->isContentReleased(), true); - BOOST_CHECK_EQUAL(2u, dq2->getMessageCount()); - - intrusive_ptr<Message> msg08 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content - DeliverableMessage dmsg08(msg08); - sbdFanout2.route(dmsg08, "", 0); - msg08->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg08->isContentReleased(), true); - BOOST_CHECK_EQUAL(3u, dq2->getMessageCount()); - - intrusive_ptr<Message> msg09 = mkMsg(testStore); // transient no content - DeliverableMessage dmsg09(msg09); - sbdFanout2.route(dmsg09, "", 0); - msg09->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg09->isContentReleased(), true); - BOOST_CHECK_EQUAL(4u, dq2->getMessageCount()); - - intrusive_ptr<Message> msg10 = mkMsg(testStore, "", true); // durable no content - DeliverableMessage dmsg10(msg10); - sbdFanout2.route(dmsg10, "", 0); - msg10->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg10->isContentReleased(), true); - BOOST_CHECK_EQUAL(5u, dq2->getMessageCount()); - - // --- Fanout exchange bound to multiple durable queues ------------------------------------------------------------ - - FanOutExchange mbdFanout3("mbdFanout3", false, args0); // multiple bindings to durable queues - Queue::shared_ptr dq3(new Queue("dq3", true, &testStore)); // durable w/ limit 2 - dq3->configure(args2); - mbdFanout3.bind(dq3, "", 0); - Queue::shared_ptr dq4(new Queue("dq4", true, &testStore)); // durable w/ limit 1 - dq4->configure(args1); - mbdFanout3.bind(dq4, "", 0); - Queue::shared_ptr dq5(new Queue("dq5", true, &testStore)); // durable no limit - dq5->configure(args0); - mbdFanout3.bind(dq5, "", 0); - - intrusive_ptr<Message> msg11 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content - DeliverableMessage dmsg11(msg11); - mbdFanout3.route(dmsg11, "", 0); // Brings queues 3 and 4 to capacity limit - msg11->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg11->isContentReleased(), false); - BOOST_CHECK_EQUAL(1u, dq3->getMessageCount()); - BOOST_CHECK_EQUAL(1u, dq4->getMessageCount()); - BOOST_CHECK_EQUAL(1u, dq5->getMessageCount()); - - intrusive_ptr<Message> msg12 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content - DeliverableMessage dmsg12(msg12); - mbdFanout3.route(dmsg12, "", 0); - msg12->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg12->isContentReleased(), false); // XXXX - consequence of transient msg multi-queue ftd policy-handling limitations, fix in broker at some point! - BOOST_CHECK_EQUAL(2u, dq3->getMessageCount()); - BOOST_CHECK_EQUAL(2u, dq4->getMessageCount()); - BOOST_CHECK_EQUAL(2u, dq5->getMessageCount()); - - intrusive_ptr<Message> msg13 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content - DeliverableMessage dmsg13(msg13); - mbdFanout3.route(dmsg13, "", 0); - msg13->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg13->isContentReleased(), true); - BOOST_CHECK_EQUAL(3u, dq3->getMessageCount()); - BOOST_CHECK_EQUAL(3u, dq4->getMessageCount()); - BOOST_CHECK_EQUAL(3u, dq5->getMessageCount()); - - intrusive_ptr<Message> msg14 = mkMsg(testStore); // transient no content - DeliverableMessage dmsg14(msg14); - mbdFanout3.route(dmsg14, "", 0); - msg14->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg14->isContentReleased(), false); // XXXX - consequence of transient msg multi-queue ftd policy-handling limitations, fix in broker at some point! - BOOST_CHECK_EQUAL(4u, dq3->getMessageCount()); - BOOST_CHECK_EQUAL(4u, dq4->getMessageCount()); - BOOST_CHECK_EQUAL(4u, dq5->getMessageCount()); - - intrusive_ptr<Message> msg15 = mkMsg(testStore, "", true); // durable no content - DeliverableMessage dmsg15(msg15); - mbdFanout3.route(dmsg15, "", 0); - msg15->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg15->isContentReleased(), true); - BOOST_CHECK_EQUAL(5u, dq3->getMessageCount()); - BOOST_CHECK_EQUAL(5u, dq4->getMessageCount()); - BOOST_CHECK_EQUAL(5u, dq5->getMessageCount()); - - // Bind a transient queue, this should block the release of any further messages. - // Note: this will result in a violation of the count policy of dq3 and dq4 - but this - // is expected until a better overall multi-queue design is implemented. Similarly - // for the other tests in this section. - - Queue::shared_ptr tq6(new Queue("tq6", true)); // transient no limit - tq6->configure(args0); - mbdFanout3.bind(tq6, "", 0); - - intrusive_ptr<Message> msg16 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content - DeliverableMessage dmsg16(msg16); - mbdFanout3.route(dmsg16, "", 0); - msg16->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg16->isContentReleased(), false); - BOOST_CHECK_EQUAL(6u, dq3->getMessageCount()); - BOOST_CHECK_EQUAL(6u, dq4->getMessageCount()); - BOOST_CHECK_EQUAL(6u, dq5->getMessageCount()); - - intrusive_ptr<Message> msg17 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content - DeliverableMessage dmsg17(msg17); - mbdFanout3.route(dmsg17, "", 0); - msg17->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg17->isContentReleased(), false); - BOOST_CHECK_EQUAL(7u, dq3->getMessageCount()); - BOOST_CHECK_EQUAL(7u, dq4->getMessageCount()); - BOOST_CHECK_EQUAL(7u, dq5->getMessageCount()); - - intrusive_ptr<Message> msg18 = mkMsg(testStore); // transient no content - DeliverableMessage dmsg18(msg18); - mbdFanout3.route(dmsg18, "", 0); - msg18->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg18->isContentReleased(), false); - BOOST_CHECK_EQUAL(8u, dq3->getMessageCount()); - BOOST_CHECK_EQUAL(8u, dq4->getMessageCount()); - BOOST_CHECK_EQUAL(8u, dq5->getMessageCount()); - - intrusive_ptr<Message> msg19 = mkMsg(testStore, "", true); // durable no content - DeliverableMessage dmsg19(msg19); - mbdFanout3.route(dmsg19, "", 0); - msg19->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg19->isContentReleased(), false); - BOOST_CHECK_EQUAL(9u, dq3->getMessageCount()); - BOOST_CHECK_EQUAL(9u, dq4->getMessageCount()); - BOOST_CHECK_EQUAL(9u, dq5->getMessageCount()); - - - // --- Fanout exchange bound to multiple durable and transient queues ---------------------------------------------- - - FanOutExchange mbmFanout4("mbmFanout4", false, args0); // multiple bindings to durable/transient queues - Queue::shared_ptr dq7(new Queue("dq7", true, &testStore)); // durable no limit - dq7->configure(args0); - mbmFanout4.bind(dq7, "", 0); - Queue::shared_ptr dq8(new Queue("dq8", true, &testStore)); // durable w/ limit - dq8->configure(args1); - mbmFanout4.bind(dq8, "", 0); - Queue::shared_ptr tq9(new Queue("tq9", true)); // transient no limit - tq9->configure(args0); - mbmFanout4.bind(tq9, "", 0); - - intrusive_ptr<Message> msg20 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content - DeliverableMessage dmsg20(msg20); - mbmFanout4.route(dmsg20, "", 0); // Brings queue 7 to capacity limit - msg20->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg20->isContentReleased(), false); - BOOST_CHECK_EQUAL(1u, dq7->getMessageCount()); - BOOST_CHECK_EQUAL(1u, dq8->getMessageCount()); - BOOST_CHECK_EQUAL(1u, tq9->getMessageCount()); - - intrusive_ptr<Message> msg21 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content - DeliverableMessage dmsg21(msg21); - mbmFanout4.route(dmsg21, "", 0); - msg21->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg21->isContentReleased(), false); - BOOST_CHECK_EQUAL(2u, dq7->getMessageCount()); // over limit - BOOST_CHECK_EQUAL(2u, dq8->getMessageCount()); - BOOST_CHECK_EQUAL(2u, tq9->getMessageCount()); - - intrusive_ptr<Message> msg22 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content - DeliverableMessage dmsg22(msg22); - mbmFanout4.route(dmsg22, "", 0); - msg22->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg22->isContentReleased(), false); - BOOST_CHECK_EQUAL(3u, dq7->getMessageCount()); // over limit - BOOST_CHECK_EQUAL(3u, dq8->getMessageCount()); // over limit - BOOST_CHECK_EQUAL(3u, tq9->getMessageCount()); - - intrusive_ptr<Message> msg23 = mkMsg(testStore); // transient no content - DeliverableMessage dmsg23(msg23); - mbmFanout4.route(dmsg23, "", 0); - msg23->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg23->isContentReleased(), false); - BOOST_CHECK_EQUAL(4u, dq7->getMessageCount()); // over limit - BOOST_CHECK_EQUAL(4u, dq8->getMessageCount()); // over limit - BOOST_CHECK_EQUAL(4u, tq9->getMessageCount()); - - intrusive_ptr<Message> msg24 = mkMsg(testStore, "", true); // durable no content - DeliverableMessage dmsg24(msg24); - mbmFanout4.route(dmsg24, "", 0); - msg24->tryReleaseContent(); - BOOST_CHECK_EQUAL(msg24->isContentReleased(), false); - BOOST_CHECK_EQUAL(5u, dq7->getMessageCount()); // over limit - BOOST_CHECK_EQUAL(5u, dq8->getMessageCount()); // over limit - BOOST_CHECK_EQUAL(5u, tq9->getMessageCount()); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/README.txt b/cpp/src/tests/README.txt deleted file mode 100644 index 0f4edee493..0000000000 --- a/cpp/src/tests/README.txt +++ /dev/null @@ -1,54 +0,0 @@ -= Running Qpid C++ tests = - -General philosophy is that "make check" run all tests by default, but -developers can run tests selectively as explained below. - -== Valgrind == - -By default we run tests under valgrind to detect memory errors if valgrind -is present. ./configure --disable-valgrind will disable it. - -Default valgrind options are specified in .valgrindrc-default, which a -checked-in file. The actual options used are in .valgrindrc which is a -local file. Normally it is a copy of valgrindrc-default but you can -modify at will. - -Supressed errors are listed in .valgrind.supp. If you want to change -suppressions for local testing, just modify .valgrindrc to point to a -different file. Do NOT add suppressions to .valgrindrc.supp unless -they are known problems outside of Qpid that can't reasonably be -worked around in Qpid. - - -== Unit Tests == -Unit tests use the boost test framework, and are compiled to rogram - unit_test -There are several options to control how test results are displayed, -see - http://www.boost.org/doc/libs/1_35_0/libs/test/doc/components/utf/parameters/index.html - -NOTE: some unit tests are written as CppUnit plug-ins, we are moving away -from CppUnit so new tests should use the boost framework. - -CppUnit tests are run by the script run-unit-tests. - -== System Tests == - -System tests are self contained AMQP client executables or scripts. -They are listed in the TESTS make variable, which can be over-ridden. - -The ./start_broker "test" launches the broker, ./stop_broker" stops it. -Tests in between assume the broker is running. - -./python_tests: runs ../python/run_tests. This is the main set of -system testss for the broker. - -Other C++ client test executables and scripts under client/test are -system tests for the client. - -By setting TESTS in a make command you can run a different subset of tests -against an already-running broker. - - - - diff --git a/cpp/src/tests/RangeSet.cpp b/cpp/src/tests/RangeSet.cpp deleted file mode 100644 index db3a964086..0000000000 --- a/cpp/src/tests/RangeSet.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/RangeSet.h" - -using namespace std; -using namespace qpid; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(RangeSetTestSuite) - -typedef qpid::Range<int> TestRange; -typedef qpid::RangeSet<int> TestRangeSet; - -QPID_AUTO_TEST_CASE(testEmptyRange) { - TestRange r; - BOOST_CHECK(r.empty()); - BOOST_CHECK(!r.contains(0)); - // BOOST_CHECK(r.contiguous(0)); -} - -QPID_AUTO_TEST_CASE(testRangeSetAddPoint) { - TestRangeSet r; - BOOST_CHECK(r.empty()); - r += 3; - BOOST_CHECK_MESSAGE(r.contains(3), r); - BOOST_CHECK_MESSAGE(r.contains(TestRange(3,4)), r); - BOOST_CHECK(!r.empty()); - r += 5; - BOOST_CHECK_MESSAGE(r.contains(5), r); - BOOST_CHECK_MESSAGE(r.contains(TestRange(5,6)), r); - BOOST_CHECK_MESSAGE(!r.contains(TestRange(3,6)), r); - r += 4; - BOOST_CHECK_MESSAGE(r.contains(TestRange(3,6)), r); -} - -QPID_AUTO_TEST_CASE(testRangeSetAddRange) { - TestRangeSet r; - r += TestRange(0,3); - BOOST_CHECK(r.contains(TestRange(0,3))); - r += TestRange(4,6); - BOOST_CHECK_MESSAGE(r.contains(TestRange(4,6)), r); - r += 3; - BOOST_CHECK_MESSAGE(r.contains(TestRange(0,6)), r); - BOOST_CHECK(r.front() == 0); - BOOST_CHECK(r.back() == 6); -} - -QPID_AUTO_TEST_CASE(testRangeSetAddSet) { - TestRangeSet r; - TestRangeSet s = TestRangeSet(0,3)+TestRange(5,10); - r += s; - BOOST_CHECK_EQUAL(r,s); - r += TestRangeSet(3,5) + TestRange(7,12) + 15; - BOOST_CHECK_EQUAL(r, TestRangeSet(0,12) + 15); - - r.clear(); - BOOST_CHECK(r.empty()); - r += TestRange::makeClosed(6,10); - BOOST_CHECK_EQUAL(r, TestRangeSet(6,11)); - r += TestRangeSet(2,6)+8; - BOOST_CHECK_EQUAL(r, TestRangeSet(2,11)); -} - -QPID_AUTO_TEST_CASE(testRangeSetIterate) { - TestRangeSet r; - (((r += 1) += 10) += TestRange(4,7)) += 2; - BOOST_MESSAGE(r); - std::vector<int> actual; - std::copy(r.begin(), r.end(), std::back_inserter(actual)); - std::vector<int> expect = boost::assign::list_of(1)(2)(4)(5)(6)(10); - BOOST_CHECK_EQUAL(expect, actual); -} - -QPID_AUTO_TEST_CASE(testRangeSetRemove) { - // points - BOOST_CHECK_EQUAL(TestRangeSet(0,5)-3, TestRangeSet(0,3)+TestRange(4,5)); - BOOST_CHECK_EQUAL(TestRangeSet(1,5)-5, TestRangeSet(1,5)); - BOOST_CHECK_EQUAL(TestRangeSet(1,5)-0, TestRangeSet(1,5)); - - TestRangeSet r(TestRangeSet(0,5)+TestRange(10,15)+TestRange(20,25)); - - // TestRanges - BOOST_CHECK_EQUAL(r-TestRange(0,5), TestRangeSet(10,15)+TestRange(20,25)); - BOOST_CHECK_EQUAL(r-TestRange(10,15), TestRangeSet(0,5)+TestRange(20,25)); - BOOST_CHECK_EQUAL(r-TestRange(20,25), TestRangeSet(0,5)+TestRange(10,15)); - - BOOST_CHECK_EQUAL(r-TestRange(-5, 30), TestRangeSet()); - - BOOST_CHECK_EQUAL(r-TestRange(-5, 7), TestRangeSet(10,15)+TestRange(20,25)); - BOOST_CHECK_EQUAL(r-TestRange(8,19), TestRangeSet(0,5)+TestRange(20,25)); - BOOST_CHECK_EQUAL(r-TestRange(17,30), TestRangeSet(0,5)+TestRange(10,15)); - BOOST_CHECK_EQUAL(r-TestRange(17,30), TestRangeSet(0,5)+TestRange(10,15)); - - BOOST_CHECK_EQUAL(r-TestRange(-5, 5), TestRangeSet(10,15)+TestRange(20,25)); - BOOST_CHECK_EQUAL(r-TestRange(10,19), TestRangeSet(0,5)+TestRange(20,25)); - BOOST_CHECK_EQUAL(r-TestRange(18,25), TestRangeSet(0,5)+TestRange(10,15)); - BOOST_CHECK_EQUAL(r-TestRange(23,25), TestRangeSet(0,5)+TestRange(10,15)+TestRange(20,23)); - - BOOST_CHECK_EQUAL(r-TestRange(-3, 3), TestRangeSet(3,5)+TestRange(10,15)+TestRange(20,25)); - BOOST_CHECK_EQUAL(r-TestRange(3, 7), TestRangeSet(0,2)+TestRange(10,15)+TestRange(20,25)); - BOOST_CHECK_EQUAL(r-TestRange(3, 12), TestRangeSet(0,3)+TestRange(12,15)+TestRange(20,25)); - BOOST_CHECK_EQUAL(r-TestRange(3, 22), TestRangeSet(12,15)+TestRange(22,25)); - BOOST_CHECK_EQUAL(r-TestRange(12, 22), TestRangeSet(0,5)+TestRange(10,11)+TestRange(22,25)); - - // Sets - BOOST_CHECK_EQUAL(r-(TestRangeSet(-1,6)+TestRange(11,14)+TestRange(23,25)), - TestRangeSet(10,11)+TestRange(14,15)+TestRange(20,23)); -} - -QPID_AUTO_TEST_CASE(testRangeContaining) { - TestRangeSet r; - (((r += 1) += TestRange(3,5)) += 7); - BOOST_CHECK_EQUAL(r.rangeContaining(0), TestRange(0,0)); - BOOST_CHECK_EQUAL(r.rangeContaining(1), TestRange(1,2)); - BOOST_CHECK_EQUAL(r.rangeContaining(2), TestRange(2,2)); - BOOST_CHECK_EQUAL(r.rangeContaining(3), TestRange(3,5)); - BOOST_CHECK_EQUAL(r.rangeContaining(4), TestRange(3,5)); - BOOST_CHECK_EQUAL(r.rangeContaining(5), TestRange(5,5)); - BOOST_CHECK_EQUAL(r.rangeContaining(6), TestRange(6,6)); - BOOST_CHECK_EQUAL(r.rangeContaining(7), TestRange(7,8)); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/RateFlowcontrolTest.cpp b/cpp/src/tests/RateFlowcontrolTest.cpp deleted file mode 100644 index 80ad06af8c..0000000000 --- a/cpp/src/tests/RateFlowcontrolTest.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "unit_test.h" - -#include "qpid/broker/RateFlowcontrol.h" -#include "qpid/sys/Time.h" - -using namespace qpid::broker; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(RateFlowcontrolTestSuite) - -QPID_AUTO_TEST_CASE(RateFlowcontrolTest) -{ - // BOOST_CHECK(predicate); - // BOOST_CHECK_EQUAL(a, b); - - RateFlowcontrol fc(100); - AbsTime n=AbsTime::now(); - - BOOST_CHECK_EQUAL( fc.receivedMessage(n, 0), 0U ); - - fc.sentCredit(n, 0); - - BOOST_CHECK_EQUAL( fc.receivedMessage(n, 0), 0U ); - fc.sentCredit(n, 50); - - Duration d=250*TIME_MSEC; - - n = AbsTime(n,d); - BOOST_CHECK_EQUAL( fc.receivedMessage(n, 25), 0U ); - BOOST_CHECK_EQUAL( fc.availableCredit(n), 25U ); - - n = AbsTime(n,d); - BOOST_CHECK_EQUAL( fc.receivedMessage(n, 23), 48U ); - BOOST_CHECK_EQUAL( fc.availableCredit(n), 48U ); - fc.sentCredit(n, 48); - BOOST_CHECK_EQUAL( fc.receivedMessage(n, 50), 0U); - BOOST_CHECK(fc.flowStopped()); - - n = AbsTime(n,d); - BOOST_CHECK_EQUAL( fc.receivedMessage(n, 0), 25U); - n = AbsTime(n,d); - BOOST_CHECK_EQUAL( fc.receivedMessage(n, 0), 50U); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/RefCounted.cpp b/cpp/src/tests/RefCounted.cpp deleted file mode 100644 index e4c1da5696..0000000000 --- a/cpp/src/tests/RefCounted.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/RefCounted.h" -#include <boost/intrusive_ptr.hpp> - -#include "unit_test.h" - -QPID_AUTO_TEST_SUITE(RefCountedTestSuiteTestSuite) - -using boost::intrusive_ptr; -using namespace std; -using namespace qpid; - -namespace qpid { -namespace tests { - -struct CountMe : public RefCounted { - static int instances; - CountMe() { ++instances; } - ~CountMe() { --instances; } -}; - -int CountMe::instances=0; - -QPID_AUTO_TEST_CASE(testRefCounted) { - BOOST_CHECK_EQUAL(0, CountMe::instances); - intrusive_ptr<CountMe> p(new CountMe()); - BOOST_CHECK_EQUAL(1, CountMe::instances); - intrusive_ptr<CountMe> q(p); - BOOST_CHECK_EQUAL(1, CountMe::instances); - q=0; - BOOST_CHECK_EQUAL(1, CountMe::instances); - p=0; - BOOST_CHECK_EQUAL(0, CountMe::instances); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ReplicationTest.cpp b/cpp/src/tests/ReplicationTest.cpp deleted file mode 100644 index 7310a3fe20..0000000000 --- a/cpp/src/tests/ReplicationTest.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "unit_test.h" -#include "test_tools.h" -#include "config.h" -#include "BrokerFixture.h" - -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/client/QueueOptions.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/replication/constants.h" -#include "qpid/sys/Shlib.h" - -#include <string> -#include <sstream> -#include <vector> - -#include <boost/assign.hpp> -#include <boost/bind.hpp> - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::replication::constants; -using boost::assign::list_of; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ReplicationTestSuite) - -// FIXME aconway 2009-11-26: clean this up. -// The CMake-based build passes in the module suffix; if it's not there, this -// is a Linux/UNIX libtool-based build. -#if defined (QPID_MODULE_PREFIX) && defined (QPID_MODULE_SUFFIX) -static const char *default_shlib = - QPID_MODULE_PREFIX "replicating_listener" QPID_MODULE_POSTFIX QPID_MODULE_SUFFIX; -#else -static const char *default_shlib = ".libs/replicating_listener.so"; -#endif -qpid::sys::Shlib plugin(getLibPath("REPLICATING_LISTENER_LIB", default_shlib)); - -qpid::broker::Broker::Options getBrokerOpts(const std::vector<std::string>& args) -{ - std::vector<const char*> argv(args.size()); - transform(args.begin(), args.end(), argv.begin(), boost::bind(&string::c_str, _1)); - - qpid::broker::Broker::Options opts; - qpid::Plugin::addOptions(opts); - opts.parse(argv.size(), &argv[0], "", true); - return opts; -} - -QPID_AUTO_TEST_CASE(testReplicationExchange) -{ - qpid::broker::Broker::Options brokerOpts(getBrokerOpts(list_of<string>("qpidd") - ("--replication-exchange-name=qpid.replication"))); - ProxySessionFixture f(brokerOpts); - - - std::string dataQ("queue-1"); - std::string eventQ("event-queue-1"); - std::string dataQ2("queue-2"); - std::string eventQ2("event-queue-2"); - FieldTable eventQopts; - eventQopts.setString("qpid.insert_sequence_numbers", REPLICATION_EVENT_SEQNO); - - f.session.queueDeclare(arg::queue=eventQ, arg::exclusive=true, arg::autoDelete=true, arg::arguments=eventQopts); - f.session.exchangeBind(arg::exchange="qpid.replication", arg::queue=eventQ, arg::bindingKey=dataQ); - - f.session.queueDeclare(arg::queue=eventQ2, arg::exclusive=true, arg::autoDelete=true, arg::arguments=eventQopts); - f.session.exchangeBind(arg::exchange="qpid.replication", arg::queue=eventQ2, arg::bindingKey=dataQ2); - - QueueOptions args; - args.enableQueueEvents(false); - f.session.queueDeclare(arg::queue=dataQ, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - f.session.queueDeclare(arg::queue=dataQ2, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args); - for (int i = 0; i < 10; i++) { - f.session.messageTransfer(arg::content=Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), dataQ)); - f.session.messageTransfer(arg::content=Message((boost::format("%1%_%2%") % "Message" % (i+1)).str(), dataQ2)); - } - Message msg; - LocalQueue incoming; - Subscription sub = f.subs.subscribe(incoming, dataQ); - for (int i = 0; i < 10; i++) { - BOOST_CHECK(incoming.get(msg, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL((boost::format("%1%_%2%") % "Message" % (i+1)).str(), msg.getData()); - } - BOOST_CHECK(!f.subs.get(msg, dataQ)); - - sub.cancel(); - sub = f.subs.subscribe(incoming, eventQ); - //check that we received enqueue events for first queue: - for (int i = 0; i < 10; i++) { - BOOST_CHECK(incoming.get(msg, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsString(REPLICATION_TARGET_QUEUE), dataQ); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsInt(REPLICATION_EVENT_TYPE), ENQUEUE); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsInt64(REPLICATION_EVENT_SEQNO), (i+1)); - BOOST_CHECK_EQUAL((boost::format("%1%_%2%") % "Message" % (i+1)).str(), msg.getData()); - } - //check that we received dequeue events for first queue: - for (int i = 0; i < 10; i++) { - BOOST_CHECK(incoming.get(msg, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsString(REPLICATION_TARGET_QUEUE), dataQ); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsInt(REPLICATION_EVENT_TYPE), DEQUEUE); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsInt(DEQUEUED_MESSAGE_POSITION), (i+1)); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsInt64(REPLICATION_EVENT_SEQNO), (i+11)); - } - - sub.cancel(); - sub = f.subs.subscribe(incoming, eventQ2); - //check that we received enqueue events for second queue: - for (int i = 0; i < 10; i++) { - BOOST_CHECK(incoming.get(msg, qpid::sys::TIME_SEC)); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsString(REPLICATION_TARGET_QUEUE), dataQ2); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsInt(REPLICATION_EVENT_TYPE), ENQUEUE); - BOOST_CHECK_EQUAL(msg.getHeaders().getAsInt64(REPLICATION_EVENT_SEQNO), (i+1)); - BOOST_CHECK_EQUAL((boost::format("%1%_%2%") % "Message" % (i+1)).str(), msg.getData()); - } -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/RetryList.cpp b/cpp/src/tests/RetryList.cpp deleted file mode 100644 index 50cd5edfe8..0000000000 --- a/cpp/src/tests/RetryList.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/broker/RetryList.h" - -using namespace qpid; -using namespace qpid::broker; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(RetryListTestSuite) - -struct RetryListFixture -{ - RetryList list; - std::vector<Url> urls; - std::vector<Address> expected; - - void addUrl(const std::string& s) - { - urls.push_back(Url(s)); - } - - void addExpectation(const std::string& host, uint16_t port) - { - expected.push_back(Address("tcp", host, port)); - } - - void check() - { - list.reset(urls); - for (int t = 0; t < 2; t++) { - Address next; - for (std::vector<Address>::const_iterator i = expected.begin(); i != expected.end(); ++i) { - BOOST_CHECK(list.next(next)); - BOOST_CHECK_EQUAL(i->host, next.host); - BOOST_CHECK_EQUAL(i->port, next.port); - } - BOOST_CHECK(!list.next(next)); - } - } -}; - -QPID_AUTO_TEST_CASE(testWithSingleAddress) -{ - RetryListFixture test; - test.addUrl("amqp:host:5673"); - test.addExpectation("host", 5673); - test.check(); -} - -QPID_AUTO_TEST_CASE(testWithSingleUrlOfMultipleAddresses) -{ - RetryListFixture test; - test.addUrl("amqp:host1,host2:2222,tcp:host3:5673,host4:1"); - - test.addExpectation("host1", 5672); - test.addExpectation("host2", 2222); - test.addExpectation("host3", 5673); - test.addExpectation("host4", 1); - - test.check(); -} - -QPID_AUTO_TEST_CASE(testWithMultipleUrlsOfMultipleAddresses) -{ - RetryListFixture test; - test.addUrl("amqp:my-host"); - test.addUrl("amqp:host1:6666,host2:2222,tcp:host3:5673,host4:1"); - test.addUrl("amqp:host5,host6:2222,tcp:host7:5673"); - - test.addExpectation("my-host", 5672); - test.addExpectation("host1", 6666); - test.addExpectation("host2", 2222); - test.addExpectation("host3", 5673); - test.addExpectation("host4", 1); - test.addExpectation("host5", 5672); - test.addExpectation("host6", 2222); - test.addExpectation("host7", 5673); - - test.check(); -} - -QPID_AUTO_TEST_CASE(testEmptyList) -{ - RetryListFixture test; - test.check(); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/SequenceNumberTest.cpp b/cpp/src/tests/SequenceNumberTest.cpp deleted file mode 100644 index f3c934e3ca..0000000000 --- a/cpp/src/tests/SequenceNumberTest.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "unit_test.h" -#include <iostream> -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceNumberSet.h" - -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -void checkDifference(SequenceNumber& a, SequenceNumber& b, int gap) -{ - BOOST_CHECK_EQUAL(gap, a - b); - BOOST_CHECK_EQUAL(-gap, b - a); - - //increment until b wraps around - for (int i = 0; i < (gap + 2); i++, ++a, ++b) { - BOOST_CHECK_EQUAL(gap, a - b); - } - //keep incrementing until a also wraps around - for (int i = 0; i < (gap + 2); i++, ++a, ++b) { - BOOST_CHECK_EQUAL(gap, a - b); - } - //let b catch up and overtake - for (int i = 0; i < (gap*2); i++, ++b) { - BOOST_CHECK_EQUAL(gap - i, a - b); - BOOST_CHECK_EQUAL(i - gap, b - a); - } -} - -void checkComparison(SequenceNumber& a, SequenceNumber& b, int gap) -{ - //increment until b wraps around - for (int i = 0; i < (gap + 2); i++) { - BOOST_CHECK(++a < ++b);//test prefix - } - //keep incrementing until a also wraps around - for (int i = 0; i < (gap + 2); i++) { - BOOST_CHECK(a++ < b++);//test postfix - } - //let a 'catch up' - for (int i = 0; i < gap; i++) { - a++; - } - BOOST_CHECK(a == b); - BOOST_CHECK(++a > b); -} - - -QPID_AUTO_TEST_SUITE(SequenceNumberTestSuite) - -QPID_AUTO_TEST_CASE(testIncrementPostfix) -{ - SequenceNumber a; - SequenceNumber b; - BOOST_CHECK(!(a > b)); - BOOST_CHECK(!(b < a)); - BOOST_CHECK(a == b); - - SequenceNumber c = a++; - BOOST_CHECK(a > b); - BOOST_CHECK(b < a); - BOOST_CHECK(a != b); - BOOST_CHECK(c < a); - BOOST_CHECK(a != c); - - b++; - BOOST_CHECK(!(a > b)); - BOOST_CHECK(!(b < a)); - BOOST_CHECK(a == b); - BOOST_CHECK(c < b); - BOOST_CHECK(b != c); -} - -QPID_AUTO_TEST_CASE(testIncrementPrefix) -{ - SequenceNumber a; - SequenceNumber b; - BOOST_CHECK(!(a > b)); - BOOST_CHECK(!(b < a)); - BOOST_CHECK(a == b); - - SequenceNumber c = ++a; - BOOST_CHECK(a > b); - BOOST_CHECK(b < a); - BOOST_CHECK(a != b); - BOOST_CHECK(a == c); - - ++b; - BOOST_CHECK(!(a > b)); - BOOST_CHECK(!(b < a)); - BOOST_CHECK(a == b); -} - -QPID_AUTO_TEST_CASE(testWrapAround) -{ - const uint32_t max = 0xFFFFFFFF; - SequenceNumber a(max - 10); - SequenceNumber b(max - 5); - checkComparison(a, b, 5); - - const uint32_t max_signed = 0x7FFFFFFF; - SequenceNumber c(max_signed - 10); - SequenceNumber d(max_signed - 5); - checkComparison(c, d, 5); -} - -QPID_AUTO_TEST_CASE(testCondense) -{ - SequenceNumberSet set; - for (uint i = 0; i < 6; i++) { - set.push_back(SequenceNumber(i)); - } - set.push_back(SequenceNumber(7)); - for (uint i = 9; i < 13; i++) { - set.push_back(SequenceNumber(i)); - } - set.push_back(SequenceNumber(13)); - SequenceNumberSet actual = set.condense(); - - SequenceNumberSet expected; - expected.addRange(SequenceNumber(0), SequenceNumber(5)); - expected.addRange(SequenceNumber(7), SequenceNumber(7)); - expected.addRange(SequenceNumber(9), SequenceNumber(13)); - BOOST_CHECK_EQUAL(expected, actual); -} - -QPID_AUTO_TEST_CASE(testCondenseSingleRange) -{ - SequenceNumberSet set; - for (uint i = 0; i < 6; i++) { - set.push_back(SequenceNumber(i)); - } - SequenceNumberSet actual = set.condense(); - - SequenceNumberSet expected; - expected.addRange(SequenceNumber(0), SequenceNumber(5)); - BOOST_CHECK_EQUAL(expected, actual); -} - -QPID_AUTO_TEST_CASE(testCondenseSingleItem) -{ - SequenceNumberSet set; - set.push_back(SequenceNumber(1)); - SequenceNumberSet actual = set.condense(); - - SequenceNumberSet expected; - expected.addRange(SequenceNumber(1), SequenceNumber(1)); - BOOST_CHECK_EQUAL(expected, actual); -} - -QPID_AUTO_TEST_CASE(testDifference) -{ - SequenceNumber a; - SequenceNumber b; - - for (int i = 0; i < 10; i++, ++a) { - BOOST_CHECK_EQUAL(i, a - b); - BOOST_CHECK_EQUAL(-i, b - a); - } - - b = a; - - for (int i = 0; i < 10; i++, ++b) { - BOOST_CHECK_EQUAL(-i, a - b); - BOOST_CHECK_EQUAL(i, b - a); - } -} - -QPID_AUTO_TEST_CASE(testDifferenceWithWrapAround1) -{ - const uint32_t max = 0xFFFFFFFF; - SequenceNumber a(max - 5); - SequenceNumber b(max - 10); - checkDifference(a, b, 5); -} - -QPID_AUTO_TEST_CASE(testDifferenceWithWrapAround2) -{ - const uint32_t max_signed = 0x7FFFFFFF; - SequenceNumber c(max_signed - 5); - SequenceNumber d(max_signed - 10); - checkDifference(c, d, 5); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/SequenceSet.cpp b/cpp/src/tests/SequenceSet.cpp deleted file mode 100644 index bc0a8ea509..0000000000 --- a/cpp/src/tests/SequenceSet.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/framing/SequenceSet.h" -#include "unit_test.h" -#include <list> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(SequenceSetTestSuite) - -using namespace qpid::framing; - -struct RangeExpectations -{ - typedef std::pair<SequenceNumber, SequenceNumber> Range; - typedef std::list<Range> Ranges; - - Ranges ranges; - - RangeExpectations& expect(const SequenceNumber& start, const SequenceNumber& end) { - ranges.push_back(Range(start, end)); - return *this; - } - - void operator()(const SequenceNumber& start, const SequenceNumber& end) { - BOOST_CHECK(!ranges.empty()); - if (!ranges.empty()) { - BOOST_CHECK_EQUAL(start, ranges.front().first); - BOOST_CHECK_EQUAL(end, ranges.front().second); - ranges.pop_front(); - } - } - - void check(SequenceSet& set) { - set.for_each(*this); - BOOST_CHECK(ranges.empty()); - } -}; - -QPID_AUTO_TEST_CASE(testAdd) { - SequenceSet s; - s.add(2); - s.add(8,8); - s.add(3,5); - - for (uint32_t i = 0; i <= 1; i++) - BOOST_CHECK(!s.contains(i)); - - for (uint32_t i = 2; i <= 5; i++) - BOOST_CHECK(s.contains(i)); - - for (uint32_t i = 6; i <= 7; i++) - BOOST_CHECK(!s.contains(i)); - - BOOST_CHECK(s.contains(8)); - - for (uint32_t i = 9; i <= 10; i++) - BOOST_CHECK(!s.contains(i)); - - RangeExpectations().expect(2, 5).expect(8, 8).check(s); - - SequenceSet t; - t.add(6, 10); - t.add(s); - - for (uint32_t i = 0; i <= 1; i++) - BOOST_CHECK(!t.contains(i)); - - for (uint32_t i = 2; i <= 10; i++) - BOOST_CHECK_MESSAGE(t.contains(i), t << " contains " << i); - - RangeExpectations().expect(2, 10).check(t); -} - -QPID_AUTO_TEST_CASE(testAdd2) { - SequenceSet s; - s.add(7,6); - s.add(4,4); - s.add(3,10); - s.add(2); - RangeExpectations().expect(2, 10).check(s); -} - -QPID_AUTO_TEST_CASE(testRemove) { - SequenceSet s; - SequenceSet t; - s.add(0, 10); - t.add(0, 10); - - s.remove(7); - s.remove(3, 5); - s.remove(9, 10); - - t.remove(s); - - for (uint32_t i = 0; i <= 2; i++) { - BOOST_CHECK(s.contains(i)); - BOOST_CHECK(!t.contains(i)); - } - - for (uint32_t i = 3; i <= 5; i++) { - BOOST_CHECK(!s.contains(i)); - BOOST_CHECK(t.contains(i)); - } - - BOOST_CHECK(s.contains(6)); - BOOST_CHECK(!t.contains(6)); - - BOOST_CHECK(!s.contains(7)); - BOOST_CHECK(t.contains(7)); - - BOOST_CHECK(s.contains(8)); - BOOST_CHECK(!t.contains(8)); - - for (uint32_t i = 9; i <= 10; i++) { - BOOST_CHECK(!s.contains(i)); - BOOST_CHECK(t.contains(i)); - } - - RangeExpectations().expect(0, 2).expect(6, 6).expect(8, 8).check(s); - RangeExpectations().expect(3, 5).expect(7, 7).expect(9, 10).check(t); -} - - -QPID_AUTO_TEST_CASE(testOutOfOrderRemove) { - - SequenceSet s(2, 20); - - // test remove from middle: - s.remove(7); - RangeExpectations().expect(2, 6).expect(8, 20).check(s); - s.remove(14); - RangeExpectations().expect(2, 6).expect(8, 13).expect(15, 20).check(s); - - // remove from front of subrange: - s.remove(8, 8); - RangeExpectations().expect(2, 6).expect(9, 13).expect(15, 20).check(s); - - // remove from tail of subrange: - s.remove(6); - RangeExpectations().expect(2, 5).expect(9, 13).expect(15, 20).check(s); - - // remove across subrange: - s.remove(13, 15); - RangeExpectations().expect(2, 5).expect(9, 12).expect(16, 20).check(s); - - // remove within subrange: - s.remove(6, 8); - RangeExpectations().expect(2, 5).expect(9, 12).expect(16, 20).check(s); - - // remove overlap subrange tail: - s.remove(11, 15); - RangeExpectations().expect(2, 5).expect(9, 10).expect(16, 20).check(s); - - // remove overlap subrange head: - s.remove(14, 17); - RangeExpectations().expect(2, 5).expect(9, 10).expect(18, 20).check(s); - - // remove overlap sequence tail: - s.remove(20, 22); - RangeExpectations().expect(2, 5).expect(9, 10).expect(18, 19).check(s); - - // remove overlap sequence head: - s.remove(1, 3); - RangeExpectations().expect(4, 5).expect(9, 10).expect(18, 19).check(s); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/SessionState.cpp b/cpp/src/tests/SessionState.cpp deleted file mode 100644 index 157cabfb63..0000000000 --- a/cpp/src/tests/SessionState.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "unit_test.h" - -#include "qpid/SessionState.h" -#include "qpid/Exception.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/SessionFlushBody.h" - -#include <boost/bind.hpp> -#include <algorithm> -#include <functional> -#include <numeric> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(SessionStateTestSuite) - -using namespace std; -using namespace boost; -using namespace qpid::framing; - -// ================================================================ -// Utility functions. - -// Apply f to [begin, end) and accumulate the result -template <class Iter, class T, class F> -T applyAccumulate(Iter begin, Iter end, T seed, const F& f) { - return std::accumulate(begin, end, seed, bind(std::plus<T>(), _1, bind(f, _2))); -} - -// Create a frame with a one-char string. -AMQFrame& frame(char s) { - static AMQFrame frame((AMQContentBody(string(&s, 1)))); - return frame; -} - -// Simple string representation of a frame. -string str(const AMQFrame& f) { - if (f.getMethod()) return "C"; // Command or Control - const AMQContentBody* c = dynamic_cast<const AMQContentBody*>(f.getBody()); - if (c) return c->getData(); // Return data for content frames. - return "H"; // Must be a header. -} -// Make a string from a range of frames. -string str(const boost::iterator_range<vector<AMQFrame>::const_iterator>& frames) { - string (*strFrame)(const AMQFrame&) = str; - return applyAccumulate(frames.begin(), frames.end(), string(), ptr_fun(strFrame)); -} -// Make a transfer command frame. -AMQFrame transferFrame(bool hasContent) { - AMQFrame t((MessageTransferBody())); - t.setFirstFrame(true); - t.setLastFrame(true); - t.setFirstSegment(true); - t.setLastSegment(!hasContent); - return t; -} -// Make a content frame -AMQFrame contentFrame(string content, bool isLast=true) { - AMQFrame f((AMQContentBody(content))); - f.setFirstFrame(true); - f.setLastFrame(true); - f.setFirstSegment(false); - f.setLastSegment(isLast); - return f; -} -AMQFrame contentFrameChar(char content, bool isLast=true) { - return contentFrame(string(1, content), isLast); -} - -// Send frame & return size of frame. -size_t send(qpid::SessionState& s, const AMQFrame& f) { s.senderRecord(f); return f.encodedSize(); } -// Send transfer command with no content. -size_t transfer0(qpid::SessionState& s) { return send(s, transferFrame(false)); } -// Send transfer frame with single content frame. -size_t transfer1(qpid::SessionState& s, string content) { - return send(s,transferFrame(true)) + send(s,contentFrame(content)); -} -size_t transfer1Char(qpid::SessionState& s, char content) { - return transfer1(s, string(1,content)); -} - -// Send transfer frame with multiple single-byte content frames. -size_t transferN(qpid::SessionState& s, string content) { - size_t size=send(s, transferFrame(!content.empty())); - if (!content.empty()) { - char last = content[content.size()-1]; - content.resize(content.size()-1); - size += applyAccumulate(content.begin(), content.end(), 0, - bind(&send, ref(s), - bind(contentFrameChar, _1, false))); - size += send(s, contentFrameChar(last, true)); - } - return size; -} - -// Send multiple transfers with single-byte content. -size_t transfers(qpid::SessionState& s, string content) { - return applyAccumulate(content.begin(), content.end(), 0, - bind(transfer1Char, ref(s), _1)); -} - -size_t contentFrameSize(size_t n=1) { return AMQFrame(( AMQContentBody())).encodedSize() + n; } -size_t transferFrameSize() { return AMQFrame((MessageTransferBody())).encodedSize(); } - -// ==== qpid::SessionState test classes - -using qpid::SessionId; -using qpid::SessionPoint; - - -QPID_AUTO_TEST_CASE(testSendGetReplyList) { - qpid::SessionState s; - s.setTimeout(1); - s.senderGetCommandPoint(); - transfer1(s, "abc"); - transfers(s, "def"); - transferN(s, "xyz"); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(0,0))),"CabcCdCeCfCxyz"); - // Ignore controls. - s.senderRecord(AMQFrame(new SessionFlushBody())); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(2,0))),"CeCfCxyz"); -} - -QPID_AUTO_TEST_CASE(testNeedFlush) { - qpid::SessionState::Configuration c; - // sync after 2 1-byte transfers or equivalent bytes. - c.replayFlushLimit = 2*(transferFrameSize()+contentFrameSize()); - qpid::SessionState s(SessionId(), c); - s.setTimeout(1); - s.senderGetCommandPoint(); - transfers(s, "a"); - BOOST_CHECK(!s.senderNeedFlush()); - transfers(s, "b"); - BOOST_CHECK(s.senderNeedFlush()); - s.senderRecordFlush(); - BOOST_CHECK(!s.senderNeedFlush()); - transfers(s, "c"); - BOOST_CHECK(!s.senderNeedFlush()); - transfers(s, "d"); - BOOST_CHECK(s.senderNeedFlush()); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint())), "CaCbCcCd"); -} - -QPID_AUTO_TEST_CASE(testPeerConfirmed) { - qpid::SessionState::Configuration c; - // sync after 2 1-byte transfers or equivalent bytes. - c.replayFlushLimit = 2*(transferFrameSize()+contentFrameSize()); - qpid::SessionState s(SessionId(), c); - s.setTimeout(1); - s.senderGetCommandPoint(); - transfers(s, "ab"); - BOOST_CHECK(s.senderNeedFlush()); - transfers(s, "cd"); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(0,0))), "CaCbCcCd"); - s.senderConfirmed(SessionPoint(3)); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(3,0))), "Cd"); - BOOST_CHECK(!s.senderNeedFlush()); - - // Multi-frame transfer. - transfer1(s, "efg"); - transfers(s, "xy"); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(3,0))), "CdCefgCxCy"); - BOOST_CHECK(s.senderNeedFlush()); - - s.senderConfirmed(SessionPoint(4)); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(4,0))), "CefgCxCy"); - BOOST_CHECK(s.senderNeedFlush()); - - s.senderConfirmed(SessionPoint(5)); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(5,0))), "CxCy"); - BOOST_CHECK(s.senderNeedFlush()); - - s.senderConfirmed(SessionPoint(6)); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(6,0))), "Cy"); - BOOST_CHECK(!s.senderNeedFlush()); -} - -QPID_AUTO_TEST_CASE(testPeerCompleted) { - qpid::SessionState s; - s.setTimeout(1); - s.senderGetCommandPoint(); - // Completion implies confirmation - transfers(s, "abc"); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(0,0))), "CaCbCc"); - SequenceSet set(SequenceSet() + 0 + 1); - s.senderCompleted(set); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(2,0))), "Cc"); - - transfers(s, "def"); - // We dont do out-of-order confirmation, so this will only confirm up to 3: - set = SequenceSet(SequenceSet() + 2 + 3 + 5); - s.senderCompleted(set); - BOOST_CHECK_EQUAL(str(s.senderExpected(SessionPoint(4,0))), "CeCf"); -} - -QPID_AUTO_TEST_CASE(testReceive) { - // Advance expected/received correctly - qpid::SessionState s; - s.receiverSetCommandPoint(SessionPoint()); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(0)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(0)); - - BOOST_CHECK(s.receiverRecord(transferFrame(false))); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(1)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(1)); - - BOOST_CHECK(s.receiverRecord(transferFrame(true))); - SessionPoint point = SessionPoint(1, transferFrameSize()); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), point); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), point); - BOOST_CHECK(s.receiverRecord(contentFrame("", false))); - point.offset += contentFrameSize(0); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), point); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), point); - BOOST_CHECK(s.receiverRecord(contentFrame("", true))); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(2)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(2)); - - // Idempotence barrier, rewind expected & receive some duplicates. - s.receiverSetCommandPoint(SessionPoint(1)); - BOOST_CHECK(!s.receiverRecord(transferFrame(false))); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(2)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(2)); - BOOST_CHECK(s.receiverRecord(transferFrame(false))); - BOOST_CHECK_EQUAL(s.receiverGetExpected(), SessionPoint(3)); - BOOST_CHECK_EQUAL(s.receiverGetReceived(), SessionPoint(3)); -} - -QPID_AUTO_TEST_CASE(testCompleted) { - // completed & unknownCompleted - qpid::SessionState s; - s.receiverSetCommandPoint(SessionPoint()); - s.receiverRecord(transferFrame(false)); - s.receiverRecord(transferFrame(false)); - s.receiverRecord(transferFrame(false)); - s.receiverCompleted(1); - BOOST_CHECK_EQUAL(s.receiverGetUnknownComplete(), SequenceSet(SequenceSet()+1)); - s.receiverCompleted(0); - BOOST_CHECK_EQUAL(s.receiverGetUnknownComplete(), - SequenceSet(SequenceSet() + qpid::Range<SequenceNumber>(0,2))); - s.receiverKnownCompleted(SequenceSet(SequenceSet()+1)); - BOOST_CHECK_EQUAL(s.receiverGetUnknownComplete(), SequenceSet(SequenceSet()+2)); - // TODO aconway 2008-04-30: missing tests for known-completed. -} - -QPID_AUTO_TEST_CASE(testNeedKnownCompleted) { - size_t flushInterval= 2*(transferFrameSize()+contentFrameSize())+1; - qpid::SessionState::Configuration c(flushInterval); - qpid::SessionState s(qpid::SessionId(), c); - s.senderGetCommandPoint(); - transfers(s, "a"); - SequenceSet set(SequenceSet() + 0); - s.senderCompleted(set); - BOOST_CHECK(!s.senderNeedKnownCompleted()); - - transfers(s, "b"); - set += 1; - s.senderCompleted(set); - BOOST_CHECK(!s.senderNeedKnownCompleted()); - - transfers(s, "c"); - set += 2; - s.senderCompleted(set); - BOOST_CHECK(s.senderNeedKnownCompleted()); - s.senderRecordKnownCompleted(); - BOOST_CHECK(!s.senderNeedKnownCompleted()); - - transfers(s, "de"); - set += 3; - set += 4; - s.senderCompleted(set); - BOOST_CHECK(!s.senderNeedKnownCompleted()); - - transfers(s, "f"); - set += 2; - s.senderCompleted(set); - BOOST_CHECK(s.senderNeedKnownCompleted()); - s.senderRecordKnownCompleted(); - BOOST_CHECK(!s.senderNeedKnownCompleted()); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/Shlib.cpp b/cpp/src/tests/Shlib.cpp deleted file mode 100644 index d8ad4c14d8..0000000000 --- a/cpp/src/tests/Shlib.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "test_tools.h" -#include "config.h" -#include "qpid/sys/Shlib.h" -#include "qpid/Exception.h" - -#include "unit_test.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(ShlibTestSuite) - -using namespace qpid::sys; -typedef void (*CallMe)(int*); - - -QPID_AUTO_TEST_CASE(testShlib) { - // The CMake-based build passes in the shared lib suffix; if it's not - // there, this is a Linux/UNIX libtool-based build. -#if defined (QPID_SHLIB_PREFIX) && defined (QPID_SHLIB_SUFFIX) - Shlib sh("./" QPID_SHLIB_PREFIX "shlibtest" QPID_SHLIB_POSTFIX QPID_SHLIB_SUFFIX); -#else - Shlib sh(".libs/libshlibtest.so"); -#endif - // Double cast to avoid ISO warning. - CallMe callMe=sh.getSymbol<CallMe>("callMe"); - BOOST_REQUIRE(callMe != 0); - int unloaded=0; - callMe(&unloaded); - sh.unload(); - BOOST_CHECK_EQUAL(42, unloaded); - try { - sh.getSymbol("callMe"); - BOOST_FAIL("Expected exception"); - } - catch (const qpid::Exception&) {} -} - -QPID_AUTO_TEST_CASE(testAutoShlib) { - int unloaded = 0; - { -#if defined (QPID_SHLIB_PREFIX) && defined (QPID_SHLIB_SUFFIX) - AutoShlib sh("./" QPID_SHLIB_PREFIX "shlibtest" QPID_SHLIB_POSTFIX QPID_SHLIB_SUFFIX); -#else - AutoShlib sh(".libs/libshlibtest.so"); -#endif - CallMe callMe=sh.getSymbol<CallMe>("callMe"); - BOOST_REQUIRE(callMe != 0); - callMe(&unloaded); - } - BOOST_CHECK_EQUAL(42, unloaded); -} - - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/SocketProxy.h b/cpp/src/tests/SocketProxy.h deleted file mode 100644 index 0c6f39d62e..0000000000 --- a/cpp/src/tests/SocketProxy.h +++ /dev/null @@ -1,181 +0,0 @@ -#ifndef SOCKETPROXY_H -#define SOCKETPROXY_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/IOHandle.h" -#ifdef _WIN32 -# include "qpid/sys/windows/IoHandlePrivate.h" - typedef SOCKET FdType; -#else -# include "qpid/sys/posix/PrivatePosix.h" - typedef int FdType; -#endif -#include "qpid/sys/Socket.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Mutex.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace tests { - -/** - * A simple socket proxy that forwards to another socket. - * Used between client & local broker to simulate network failures. - */ -class SocketProxy : private qpid::sys::Runnable -{ - // Need a Socket we can get the fd from - class LowSocket : public qpid::sys::Socket { - public: -#ifdef _WIN32 - FdType getFd() { return toSocketHandle(*this); } -#else - FdType getFd() { return toFd(impl); } -#endif - }; - - public: - /** Connect to connectPort on host, start a forwarding thread. - * Listen for connection on getPort(). - */ - SocketProxy(int connectPort, const std::string host="localhost") - : closed(false), joined(true), - port(listener.listen()), dropClient(), dropServer() - { - client.connect(host, connectPort); - joined = false; - thread = qpid::sys::Thread(static_cast<qpid::sys::Runnable*>(this)); - } - - ~SocketProxy() { close(); if (!joined) thread.join(); } - - /** Simulate a network disconnect. */ - void close() { - { - qpid::sys::Mutex::ScopedLock l(lock); - if (closed) { return; } - closed=true; - } - if (thread && thread != qpid::sys::Thread::current()) { - thread.join(); - joined = true; - } - client.close(); - } - - /** Simulate lost packets, drop data from client */ - void dropClientData(bool drop=true) { dropClient=drop; } - - /** Simulate lost packets, drop data from server */ - void dropServerData(bool drop=true) { dropServer=drop; } - - bool isClosed() const { - qpid::sys::Mutex::ScopedLock l(lock); - return closed; - } - - uint16_t getPort() const { return port; } - - private: - static void throwErrno(const std::string& msg) { - throw qpid::Exception(msg+":"+qpid::sys::strError(errno)); - } - static void throwIf(bool condition, const std::string& msg) { - if (condition) throw qpid::Exception(msg); - } - - void run() { - std::auto_ptr<LowSocket> server; - try { - fd_set socks; - FdType maxFd = listener.getFd(); - struct timeval tmo; - for (;;) { - FD_ZERO(&socks); - FD_SET(maxFd, &socks); - tmo.tv_sec = 0; - tmo.tv_usec = 500 * 1000; - if (select(maxFd+1, &socks, 0, 0, &tmo) == 0) { - qpid::sys::Mutex::ScopedLock l(lock); - throwIf(closed, "SocketProxy: Closed by close()"); - continue; - } - throwIf(!FD_ISSET(maxFd, &socks), "SocketProxy: Accept failed"); - break; // Accept ready... go to next step - } - server.reset(reinterpret_cast<LowSocket *>(listener.accept())); - maxFd = server->getFd(); - if (client.getFd() > maxFd) - maxFd = client.getFd(); - char buffer[1024]; - for (;;) { - FD_ZERO(&socks); - tmo.tv_sec = 0; - tmo.tv_usec = 500 * 1000; - FD_SET(client.getFd(), &socks); - FD_SET(server->getFd(), &socks); - if (select(maxFd+1, &socks, 0, 0, &tmo) == 0) { - qpid::sys::Mutex::ScopedLock l(lock); - throwIf(closed, "SocketProxy: Closed by close()"); - continue; - } - // Something is set; relay data as needed until something closes - if (FD_ISSET(server->getFd(), &socks)) { - int n = server->read(buffer, sizeof(buffer)); - throwIf(n <= 0, "SocketProxy: server disconnected"); - if (!dropServer) client.write(buffer, n); - } - if (FD_ISSET(client.getFd(), &socks)) { - int n = client.read(buffer, sizeof(buffer)); - throwIf(n <= 0, "SocketProxy: client disconnected"); - if (!dropServer) server->write(buffer, n); - } - if (!FD_ISSET(client.getFd(), &socks) && - !FD_ISSET(server->getFd(), &socks)) - throwIf(true, "SocketProxy: No handle ready"); - } - } - catch (const std::exception& e) { - QPID_LOG(debug, "SocketProxy::run exception: " << e.what()); - } - try { - if (server.get()) server->close(); - close(); - } - catch (const std::exception& e) { - QPID_LOG(debug, "SocketProxy::run exception in client/server close()" << e.what()); - } - } - - mutable qpid::sys::Mutex lock; - mutable bool closed; - bool joined; - LowSocket client, listener; - uint16_t port; - qpid::sys::Thread thread; - bool dropClient, dropServer; -}; - -}} // namespace qpid::tests - -#endif diff --git a/cpp/src/tests/Statistics.cpp b/cpp/src/tests/Statistics.cpp deleted file mode 100644 index 19531762b1..0000000000 --- a/cpp/src/tests/Statistics.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "Statistics.h" -#include <qpid/messaging/Message.h> -#include <ostream> -#include <iomanip> - -namespace qpid { -namespace tests { - -using namespace std; - -Statistic::~Statistic() {} - -Throughput::Throughput() : messages(0), started(false) {} - -void Throughput::message(const messaging::Message&) { - ++messages; - if (!started) { - start = sys::now(); - started = true; - } -} - -void Throughput::header(ostream& o) const { - o << "tp(m/s)"; -} - -void Throughput::report(ostream& o) const { - double elapsed(int64_t(sys::Duration(start, sys::now()))/double(sys::TIME_SEC)); - o << fixed << setprecision(0) << messages/elapsed; -} - -ThroughputAndLatency::ThroughputAndLatency() : - total(0), - min(numeric_limits<double>::max()), - max(numeric_limits<double>::min()), - samples(0) -{} - -const std::string TS = "ts"; - -void ThroughputAndLatency::message(const messaging::Message& m) { - Throughput::message(m); - types::Variant::Map::const_iterator i = m.getProperties().find(TS); - if (i != m.getProperties().end()) { - ++samples; - int64_t start(i->second.asInt64()); - int64_t end(sys::Duration(sys::EPOCH, sys::now())); - double latency = double(end - start)/sys::TIME_MSEC; - if (latency > 0) { - total += latency; - if (latency < min) min = latency; - if (latency > max) max = latency; - } - } -} - -void ThroughputAndLatency::header(ostream& o) const { - Throughput::header(o); - o << '\t' << "l-min" << '\t' << "l-max" << '\t' << "l-avg"; -} - -void ThroughputAndLatency::report(ostream& o) const { - Throughput::report(o); - if (samples) { - o << fixed << setprecision(2) - << '\t' << min << '\t' << max << '\t' << total/samples; - } -} - -ReporterBase::ReporterBase(ostream& o, int batch, bool wantHeader) - : batchSize(batch), batchCount(0), headerPrinted(!wantHeader), out(o) -{} - -ReporterBase::~ReporterBase() {} - -/** Count message in the statistics */ -void ReporterBase::message(const messaging::Message& m) { - if (!overall.get()) overall = create(); - overall->message(m); - if (batchSize) { - if (!batch.get()) batch = create(); - batch->message(m); - if (++batchCount == batchSize) { - header(); - batch->report(out); - out << endl; - batch = create(); - batchCount = 0; - } - } -} - -/** Print overall report. */ -void ReporterBase::report() { - if (!overall.get()) overall = create(); - header(); - overall->report(out); - out << endl; -} - -void ReporterBase::header() { - if (!headerPrinted) { - if (!overall.get()) overall = create(); - overall->header(out); - out << endl; - headerPrinted = true; - } -} - - -}} // namespace qpid::tests diff --git a/cpp/src/tests/Statistics.h b/cpp/src/tests/Statistics.h deleted file mode 100644 index 091046a17f..0000000000 --- a/cpp/src/tests/Statistics.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef TESTS_STATISTICS_H -#define TESTS_STATISTICS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -#include <qpid/sys/Time.h> -#include <limits> -#include <iosfwd> -#include <memory> - -namespace qpid { - -namespace messaging { -class Message; -} - -namespace tests { - -class Statistic { - public: - virtual ~Statistic(); - virtual void message(const messaging::Message&) = 0; - virtual void report(std::ostream&) const = 0; - virtual void header(std::ostream&) const = 0; -}; - -class Throughput : public Statistic { - public: - Throughput(); - virtual void message(const messaging::Message&); - virtual void report(std::ostream&) const; - virtual void header(std::ostream&) const; - - protected: - int messages; - - private: - bool started; - sys::AbsTime start; -}; - -class ThroughputAndLatency : public Throughput { - public: - ThroughputAndLatency(); - virtual void message(const messaging::Message&); - virtual void report(std::ostream&) const; - virtual void header(std::ostream&) const; - - private: - double total, min, max; // Milliseconds - int samples; -}; - -/** Report batch and overall statistics */ -class ReporterBase { - public: - virtual ~ReporterBase(); - - /** Count message in the statistics */ - void message(const messaging::Message& m); - - /** Print overall report. */ - void report(); - - protected: - ReporterBase(std::ostream& o, int batchSize, bool wantHeader); - virtual std::auto_ptr<Statistic> create() = 0; - - private: - void header(); - void report(const Statistic& s); - std::auto_ptr<Statistic> overall; - std::auto_ptr<Statistic> batch; - int batchSize, batchCount; - bool stopped, headerPrinted; - std::ostream& out; -}; - -template <class Stats> class Reporter : public ReporterBase { - public: - Reporter(std::ostream& o, int batchSize, bool wantHeader) - : ReporterBase(o, batchSize, wantHeader) {} - - virtual std::auto_ptr<Statistic> create() { - return std::auto_ptr<Statistic>(new Stats); - } -}; - -}} // namespace qpid::tests - -#endif /*!TESTS_STATISTICS_H*/ diff --git a/cpp/src/tests/StoreStatus.cpp b/cpp/src/tests/StoreStatus.cpp deleted file mode 100644 index 43d4cfd920..0000000000 --- a/cpp/src/tests/StoreStatus.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/cluster/StoreStatus.h" -#include "qpid/framing/Uuid.h" -#include <boost/assign.hpp> -#include <boost/filesystem/operations.hpp> - -using namespace std; -using namespace qpid::cluster; -using namespace qpid::framing; -using namespace qpid::framing::cluster; -using namespace boost::assign; -using namespace boost::filesystem; - - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(StoreStatusTestSuite) - -const char* TEST_DIR = "StoreStatus.tmp"; - -struct TestDir { - TestDir() { - remove_all(TEST_DIR); - create_directory(TEST_DIR); - } - ~TestDir() { - remove_all(TEST_DIR); - } -}; - -QPID_AUTO_TEST_CASE(testLoadEmpty) { - TestDir td; - StoreStatus ss(TEST_DIR); - BOOST_CHECK_EQUAL(ss.getState(), STORE_STATE_NO_STORE); - BOOST_CHECK(!ss.getClusterId()); - BOOST_CHECK(!ss.getShutdownId()); - ss.load(); - BOOST_CHECK_EQUAL(ss.getState(), STORE_STATE_EMPTY_STORE); - BOOST_CHECK(!ss.getShutdownId()); -} - -QPID_AUTO_TEST_CASE(testSaveLoadDirty) { - TestDir td; - Uuid clusterId = Uuid(true); - StoreStatus ss(TEST_DIR); - ss.load(); - ss.setClusterId(clusterId); - ss.dirty(); - BOOST_CHECK_EQUAL(ss.getState(), STORE_STATE_DIRTY_STORE); - - StoreStatus ss2(TEST_DIR); - ss2.load(); - BOOST_CHECK_EQUAL(ss2.getState(), STORE_STATE_DIRTY_STORE); - BOOST_CHECK_EQUAL(ss2.getClusterId(), clusterId); - BOOST_CHECK(!ss2.getShutdownId()); -} - -QPID_AUTO_TEST_CASE(testSaveLoadClean) { - TestDir td; - Uuid clusterId = Uuid(true); - Uuid shutdownId = Uuid(true); - StoreStatus ss(TEST_DIR); - ss.load(); - ss.setClusterId(clusterId); - ss.clean(shutdownId); - BOOST_CHECK_EQUAL(ss.getState(), STORE_STATE_CLEAN_STORE); - - StoreStatus ss2(TEST_DIR); - ss2.load(); - BOOST_CHECK_EQUAL(ss2.getState(), STORE_STATE_CLEAN_STORE); - BOOST_CHECK_EQUAL(ss2.getClusterId(), clusterId); - BOOST_CHECK_EQUAL(ss2.getShutdownId(), shutdownId); -} - -QPID_AUTO_TEST_CASE(testMarkDirty) { - // Save clean then mark to dirty. - TestDir td; - Uuid clusterId = Uuid(true); - Uuid shutdownId = Uuid(true); - StoreStatus ss(TEST_DIR); - ss.load(); - ss.setClusterId(clusterId); - ss.dirty(); - ss.clean(shutdownId); - ss.dirty(); - - StoreStatus ss2(TEST_DIR); - ss2.load(); - BOOST_CHECK_EQUAL(ss2.getState(), STORE_STATE_DIRTY_STORE); - BOOST_CHECK_EQUAL(ss2.getClusterId(), clusterId); - BOOST_CHECK(!ss2.getShutdownId()); -} - -QPID_AUTO_TEST_SUITE_END() - - }} // namespace qpid::tests diff --git a/cpp/src/tests/StringUtils.cpp b/cpp/src/tests/StringUtils.cpp deleted file mode 100644 index 6a19119288..0000000000 --- a/cpp/src/tests/StringUtils.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/StringUtils.h" - -#include "unit_test.h" - -QPID_AUTO_TEST_SUITE(StringUtilsTestSuite) - -using namespace qpid; -using std::string; - -QPID_AUTO_TEST_CASE(testSplit_general) -{ - std::vector<std::string> results = split("a bbbb, car,d123,,,e", ", "); - BOOST_CHECK_EQUAL(5u, results.size()); - BOOST_CHECK_EQUAL(string("a"), results[0]); - BOOST_CHECK_EQUAL(string("bbbb"), results[1]); - BOOST_CHECK_EQUAL(string("car"), results[2]); - BOOST_CHECK_EQUAL(string("d123"), results[3]); - BOOST_CHECK_EQUAL(string("e"), results[4]); -} - -QPID_AUTO_TEST_CASE(testSplit_noDelims) -{ - std::vector<std::string> results = split("abc", ", "); - BOOST_CHECK_EQUAL(1u, results.size()); - BOOST_CHECK_EQUAL(string("abc"), results[0]); -} - -QPID_AUTO_TEST_CASE(testSplit_delimAtEnd) -{ - std::vector<std::string> results = split("abc def,,", ", "); - BOOST_CHECK_EQUAL(2u, results.size()); - BOOST_CHECK_EQUAL(string("abc"), results[0]); - BOOST_CHECK_EQUAL(string("def"), results[1]); -} - -QPID_AUTO_TEST_CASE(testSplit_delimAtStart) -{ - std::vector<std::string> results = split(",,abc def", ", "); - BOOST_CHECK_EQUAL(2u, results.size()); - BOOST_CHECK_EQUAL(string("abc"), results[0]); - BOOST_CHECK_EQUAL(string("def"), results[1]); -} - -QPID_AUTO_TEST_CASE(testSplit_onlyDelims) -{ - std::vector<std::string> results = split(",, , ", ", "); - BOOST_CHECK_EQUAL(0u, results.size()); -} - -QPID_AUTO_TEST_CASE(testSplit_empty) -{ - std::vector<std::string> results = split("", ", "); - BOOST_CHECK_EQUAL(0u, results.size()); -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/cpp/src/tests/TestMessageStore.h b/cpp/src/tests/TestMessageStore.h deleted file mode 100644 index 20e0b755b2..0000000000 --- a/cpp/src/tests/TestMessageStore.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _tests_TestMessageStore_h -#define _tests_TestMessageStore_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/NullMessageStore.h" -#include <vector> - -using namespace qpid; -using namespace qpid::broker; -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -typedef std::pair<string, boost::intrusive_ptr<PersistableMessage> > msg_queue_pair; - -class TestMessageStore : public NullMessageStore -{ - public: - std::vector<boost::intrusive_ptr<PersistableMessage> > dequeued; - std::vector<msg_queue_pair> enqueued; - - void dequeue(TransactionContext*, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& /*queue*/) - { - dequeued.push_back(msg); - } - - void enqueue(TransactionContext*, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) - { - msg->enqueueComplete(); - enqueued.push_back(msg_queue_pair(queue.getName(), msg)); - } - - TestMessageStore() : NullMessageStore() {} - ~TestMessageStore(){} -}; - -}} // namespace qpid::tests - -#endif diff --git a/cpp/src/tests/TestOptions.h b/cpp/src/tests/TestOptions.h deleted file mode 100644 index f8da0f59cf..0000000000 --- a/cpp/src/tests/TestOptions.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef _TestOptions_ -#define _TestOptions_ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Options.h" -#include "qpid/log/Options.h" -#include "qpid/Url.h" -#include "qpid/log/Logger.h" -#include "qpid/client/Connection.h" -#include "ConnectionOptions.h" - -#include <iostream> -#include <exception> - -namespace qpid { - -struct TestOptions : public qpid::Options -{ - TestOptions(const std::string& helpText_=std::string(), - const std::string& argv0=std::string()) - : Options("Test Options"), help(false), log(argv0), helpText(helpText_) - { - addOptions() - ("help", optValue(help), "print this usage statement"); - add(con); - add(log); - } - - /** As well as parsing, throw help message if requested. */ - void parse(int argc, char** argv) { - try { - qpid::Options::parse(argc, argv); - } catch (const std::exception& e) { - std::ostringstream msg; - msg << *this << std::endl << std::endl << e.what() << std::endl; - throw qpid::Options::Exception(msg.str()); - } - qpid::log::Logger::instance().configure(log); - if (help) { - std::ostringstream msg; - msg << *this << std::endl << std::endl << helpText << std::endl; - throw qpid::Options::Exception(msg.str()); - } - } - - /** Open a connection using option values */ - void open(qpid::client::Connection& connection) { - connection.open(con); - } - - - bool help; - ConnectionOptions con; - qpid::log::Options log; - std::string helpText; -}; - -} - -#endif diff --git a/cpp/src/tests/TimerTest.cpp b/cpp/src/tests/TimerTest.cpp deleted file mode 100644 index 6a0a196f4e..0000000000 --- a/cpp/src/tests/TimerTest.cpp +++ /dev/null @@ -1,130 +0,0 @@ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/sys/Timer.h" -#include "qpid/sys/Monitor.h" -#include "unit_test.h" -#include <math.h> -#include <iostream> -#include <memory> -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> - -using namespace qpid::sys; -using boost::intrusive_ptr; -using boost::dynamic_pointer_cast; - -namespace qpid { -namespace tests { - -class Counter -{ - Mutex lock; - uint counter; - public: - Counter() : counter(0) {} - uint next() - { - Mutex::ScopedLock l(lock); - return ++counter; - } -}; - -class TestTask : public TimerTask -{ - const AbsTime start; - const Duration expected; - AbsTime end; - bool fired; - uint position; - Monitor monitor; - Counter& counter; - - public: - TestTask(Duration timeout, Counter& _counter) - : TimerTask(timeout, "Test"), start(now()), expected(timeout), end(start), fired(false), counter(_counter) {} - - void fire() - { - Monitor::ScopedLock l(monitor); - fired = true; - position = counter.next(); - end = now(); - monitor.notify(); - } - - void check(uint expected_position, uint64_t tolerance = 500 * TIME_MSEC) - { - Monitor::ScopedLock l(monitor); - BOOST_CHECK(fired); - BOOST_CHECK_EQUAL(expected_position, position); - Duration actual(start, end); -#ifdef _MSC_VER - uint64_t difference = _abs64(expected - actual); -#elif defined(_WIN32) - uint64_t difference = labs(expected - actual); -#else - uint64_t difference = abs(expected - actual); -#endif - std::string msg(boost::lexical_cast<std::string>(boost::format("tolerance = %1%, difference = %2%") % tolerance % difference)); - BOOST_CHECK_MESSAGE(difference < tolerance, msg); - } - - void wait(Duration d) - { - Monitor::ScopedLock l(monitor); - monitor.wait(AbsTime(now(), d)); - } -}; - -class DummyRunner : public Runnable -{ - public: - void run() {} -}; - -QPID_AUTO_TEST_SUITE(TimerTestSuite) - -QPID_AUTO_TEST_CASE(testGeneral) -{ - Counter counter; - Timer timer; - intrusive_ptr<TestTask> task1(new TestTask(Duration(3 * TIME_SEC), counter)); - intrusive_ptr<TestTask> task2(new TestTask(Duration(1 * TIME_SEC), counter)); - intrusive_ptr<TestTask> task3(new TestTask(Duration(4 * TIME_SEC), counter)); - intrusive_ptr<TestTask> task4(new TestTask(Duration(2 * TIME_SEC), counter)); - - timer.add(task1); - timer.add(task2); - timer.add(task3); - timer.add(task4); - - dynamic_pointer_cast<TestTask>(task3)->wait(Duration(6 * TIME_SEC)); - - dynamic_pointer_cast<TestTask>(task1)->check(3); - dynamic_pointer_cast<TestTask>(task2)->check(1); - dynamic_pointer_cast<TestTask>(task3)->check(4); - dynamic_pointer_cast<TestTask>(task4)->check(2); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/TopicExchangeTest.cpp b/cpp/src/tests/TopicExchangeTest.cpp deleted file mode 100644 index ff8931f9c9..0000000000 --- a/cpp/src/tests/TopicExchangeTest.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#include "qpid/broker/TopicExchange.h" -#include "unit_test.h" -#include "test_tools.h" - -using namespace qpid::broker; -using namespace std; - - -namespace qpid { -namespace broker { - -// Class for exercising the pattern match code in the TopicExchange -class TopicExchange::TopicExchangeTester { - -public: - typedef std::vector<std::string> BindingVec; - -private: - // binding node iterator that collects all routes that are bound - class TestFinder : public TopicExchange::BindingNode::TreeIterator { - public: - TestFinder(BindingVec& m) : bv(m) {}; - ~TestFinder() {}; - bool visit(BindingNode& node) { - if (!node.bindings.bindingVector.empty()) - bv.push_back(node.routePattern); - return true; - } - - BindingVec& bv; - }; - -public: - TopicExchangeTester() {}; - ~TopicExchangeTester() {}; - bool addBindingKey(const std::string& bKey) { - string routingPattern = normalize(bKey); - BindingKey *bk = bindingTree.addBindingKey(routingPattern); - if (bk) { - // push a dummy binding to mark this node as "non-leaf" - bk->bindingVector.push_back(Binding::shared_ptr()); - return true; - } - return false; - } - - bool removeBindingKey(const std::string& bKey){ - string routingPattern = normalize(bKey); - BindingKey *bk = bindingTree.getBindingKey(routingPattern); - if (bk) { - bk->bindingVector.pop_back(); - if (bk->bindingVector.empty()) { - // no more bindings - remove this node - bindingTree.removeBindingKey(routingPattern); - } - return true; - } - return false; - } - - void findMatches(const std::string& rKey, BindingVec& matches) { - TestFinder testFinder(matches); - bindingTree.iterateMatch( rKey, testFinder ); - } - - void getAll(BindingVec& bindings) { - TestFinder testFinder(bindings); - bindingTree.iterateAll( testFinder ); - } - -private: - TopicExchange::BindingNode bindingTree; -}; -} // namespace broker - - -namespace tests { - -QPID_AUTO_TEST_SUITE(TopicExchangeTestSuite) - -#define CHECK_NORMALIZED(expect, pattern) BOOST_CHECK_EQUAL(expect, TopicExchange::normalize(pattern)); - -namespace { - // return the count of bindings that match 'pattern' - int match(TopicExchange::TopicExchangeTester &tt, - const std::string& pattern) - { - TopicExchange::TopicExchangeTester::BindingVec bv; - tt.findMatches(pattern, bv); - return int(bv.size()); - } - - // return true if expected contains exactly all bindings that match - // against pattern. - bool compare(TopicExchange::TopicExchangeTester& tt, - const std::string& pattern, - const TopicExchange::TopicExchangeTester::BindingVec& expected) - { - TopicExchange::TopicExchangeTester::BindingVec bv; - tt.findMatches(pattern, bv); - if (expected.size() != bv.size()) { - // std::cout << "match failed 1 f=[" << bv << "]" << std::endl; - // std::cout << "match failed 1 e=[" << expected << "]" << std::endl; - return false; - } - TopicExchange::TopicExchangeTester::BindingVec::const_iterator i; - for (i = expected.begin(); i != expected.end(); i++) { - TopicExchange::TopicExchangeTester::BindingVec::iterator j; - for (j = bv.begin(); j != bv.end(); j++) { - // std::cout << "matched [" << *j << "]" << std::endl; - if (*i == *j) break; - } - if (j == bv.end()) { - // std::cout << "match failed 2 [" << bv << "]" << std::endl; - return false; - } - } - return true; - } -} - - -QPID_AUTO_TEST_CASE(testNormalize) -{ - CHECK_NORMALIZED("", ""); - CHECK_NORMALIZED("a.b.c", "a.b.c"); - CHECK_NORMALIZED("a.*.c", "a.*.c"); - CHECK_NORMALIZED("#", "#"); - CHECK_NORMALIZED("#", "#.#.#.#"); - CHECK_NORMALIZED("*.*.*.#", "#.*.#.*.#.#.*"); - CHECK_NORMALIZED("a.*.*.*.#", "a.*.#.*.#.*.#"); - CHECK_NORMALIZED("a.*.*.*.#", "a.*.#.*.#.*"); - CHECK_NORMALIZED("*.*.*.#", "*.#.#.*.*.#"); -} - -QPID_AUTO_TEST_CASE(testPlain) -{ - TopicExchange::TopicExchangeTester tt; - string pattern("ab.cd.e"); - - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "ab.cd.e")); - BOOST_CHECK_EQUAL(0, match(tt, "abx.cd.e")); - BOOST_CHECK_EQUAL(0, match(tt, "ab.cd")); - BOOST_CHECK_EQUAL(0, match(tt, "ab.cd..e.")); - BOOST_CHECK_EQUAL(0, match(tt, "ab.cd.e.")); - BOOST_CHECK_EQUAL(0, match(tt, ".ab.cd.e")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = ""; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "."; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, ".")); - BOOST_CHECK(tt.removeBindingKey(pattern)); -} - - -QPID_AUTO_TEST_CASE(testStar) -{ - TopicExchange::TopicExchangeTester tt; - string pattern("a.*.b"); - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.xx.b")); - BOOST_CHECK_EQUAL(0, match(tt, "a.b")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "*.x"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "y.x")); - BOOST_CHECK_EQUAL(1, match(tt, ".x")); - BOOST_CHECK_EQUAL(0, match(tt, "x")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "x.x.*"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "x.x.y")); - BOOST_CHECK_EQUAL(1, match(tt, "x.x.")); - BOOST_CHECK_EQUAL(0, match(tt, "x.x")); - BOOST_CHECK_EQUAL(0, match(tt, "q.x.y")); - BOOST_CHECK(tt.removeBindingKey(pattern)); -} - -QPID_AUTO_TEST_CASE(testHash) -{ - TopicExchange::TopicExchangeTester tt; - string pattern("a.#.b"); - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.b")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.b")); - BOOST_CHECK_EQUAL(1, match(tt, "a..x.y.zz.b")); - BOOST_CHECK_EQUAL(0, match(tt, "a.b.")); - BOOST_CHECK_EQUAL(0, match(tt, "q.x.b")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "a.#"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a")); - BOOST_CHECK_EQUAL(1, match(tt, "a.b")); - BOOST_CHECK_EQUAL(1, match(tt, "a.b.c")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "#.a"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a")); - BOOST_CHECK_EQUAL(1, match(tt, "x.y.a")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "a.#.b.#.c"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.b.c")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.b.y.c")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.x.b.y.y.c")); - BOOST_CHECK(tt.removeBindingKey(pattern)); -} - -QPID_AUTO_TEST_CASE(testMixed) -{ - TopicExchange::TopicExchangeTester tt; - string pattern("*.x.#.y"); - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.y")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.p.qq.y")); - BOOST_CHECK_EQUAL(0, match(tt, "a.a.x.y")); - BOOST_CHECK_EQUAL(0, match(tt, "aa.x.b.c")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "a.#.b.*"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "a.b.x")); - BOOST_CHECK_EQUAL(1, match(tt, "a.x.x.x.b.x")); - BOOST_CHECK(tt.removeBindingKey(pattern)); - - pattern = "*.*.*.#"; - BOOST_CHECK(tt.addBindingKey(pattern)); - BOOST_CHECK_EQUAL(1, match(tt, "x.y.z")); - BOOST_CHECK_EQUAL(1, match(tt, "x.y.z.a.b.c")); - BOOST_CHECK_EQUAL(0, match(tt, "x.y")); - BOOST_CHECK_EQUAL(0, match(tt, "x")); - BOOST_CHECK(tt.removeBindingKey(pattern)); -} - - -QPID_AUTO_TEST_CASE(testMultiple) -{ - TopicExchange::TopicExchangeTester tt; - const std::string bindings[] = - { "a", "b", - "a.b", "b.c", - "a.b.c.d", "b.c.d.e", - "a.*", "a.#", "a.*.#", - "#.b", "*.b", "*.#.b", - "a.*.b", "a.#.b", "a.*.#.b", - "*.b.*", "#.b.#", - }; - const size_t nBindings = sizeof(bindings)/sizeof(bindings[0]); - - // setup bindings - for (size_t idx = 0; idx < nBindings; idx++) { - BOOST_CHECK(tt.addBindingKey(bindings[idx])); - } - - { - // read all bindings, and verify all are present - TopicExchange::TopicExchangeTester::BindingVec b; - tt.getAll(b); - BOOST_CHECK_EQUAL(b.size(), nBindings); - for (size_t idx = 0; idx < nBindings; idx++) { - bool found = false; - for (TopicExchange::TopicExchangeTester::BindingVec::iterator i = b.begin(); - i != b.end(); i++) { - if (*i == bindings[idx]) { - found = true; - break; - } - } - BOOST_CHECK(found); - } - } - - { // test match on pattern "a" - const std::string matches[] = { "a", "a.#" }; - const size_t nMatches = 2; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a", expected)); - } - - { // test match on pattern "a.z" - const std::string matches[] = { "a.*", "a.#", "a.*.#" }; - const size_t nMatches = 3; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.z", expected)); - } - - { // test match on pattern "a.b" - const std::string matches[] = { - "a.b", "a.*", "a.#", "a.*.#", - "#.b", "#.b.#", "*.#.b", "*.b", - "a.#.b" - }; - const size_t nMatches = 9; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.b", expected)); - } - - { // test match on pattern "a.c.c.b" - - const std::string matches[] = { - "#.b", "#.b.#", "*.#.b", "a.#.b", - "a.#", "a.*.#.b", "a.*.#" - }; - const size_t nMatches = 7; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.c.c.b", expected)); - } - - { // test match on pattern "a.b.c" - - const std::string matches[] = { - "#.b.#", "*.b.*", "a.#", "a.*.#" - }; - const size_t nMatches = 4; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.b.c", expected)); - } - - { // test match on pattern "b" - - const std::string matches[] = { - "#.b", "#.b.#", "b" - }; - const size_t nMatches = 3; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "b", expected)); - } - - { // test match on pattern "x.b" - - const std::string matches[] = { - "#.b", "#.b.#", "*.#.b", "*.b" - }; - const size_t nMatches = 4; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "x.b", expected)); - } - - { // test match on pattern "x.y.z.b" - - const std::string matches[] = { - "#.b", "#.b.#", "*.#.b" - }; - const size_t nMatches = 3; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "x.y.z.b", expected)); - } - - { // test match on pattern "x.y.z.b.a.b.c" - - const std::string matches[] = { - "#.b.#", "#.b.#" - }; - const size_t nMatches = 2; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "x.y.z.b.a.b.c", expected)); - } - - { // test match on pattern "a.b.c.d" - - const std::string matches[] = { - "#.b.#", "a.#", "a.*.#", "a.b.c.d", - }; - const size_t nMatches = 4; - TopicExchange::TopicExchangeTester::BindingVec expected(matches, matches + nMatches); - BOOST_CHECK(compare(tt, "a.b.c.d", expected)); - } - - // cleanup bindings - for (size_t idx = 0; idx < nBindings; idx++) { - BOOST_CHECK(tt.removeBindingKey(bindings[idx])); - } -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/TxBufferTest.cpp b/cpp/src/tests/TxBufferTest.cpp deleted file mode 100644 index 4807026ab7..0000000000 --- a/cpp/src/tests/TxBufferTest.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/TxBuffer.h" -#include "unit_test.h" -#include <iostream> -#include <vector> -#include "TxMocks.h" - -using namespace qpid::broker; -using boost::static_pointer_cast; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(TxBufferTestSuite) - -QPID_AUTO_TEST_CASE(testCommitLocal) -{ - MockTransactionalStore store; - store.expectBegin().expectCommit(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectCommit(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare().expectPrepare().expectCommit().expectCommit();//opB enlisted twice to test relative order - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectPrepare().expectCommit(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast<TxOp>(opA)); - buffer.enlist(static_pointer_cast<TxOp>(opB)); - buffer.enlist(static_pointer_cast<TxOp>(opB));//opB enlisted twice - buffer.enlist(static_pointer_cast<TxOp>(opC)); - - BOOST_CHECK(buffer.commitLocal(&store)); - store.check(); - BOOST_CHECK(store.isCommitted()); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testFailOnCommitLocal) -{ - MockTransactionalStore store; - store.expectBegin().expectAbort(); - - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectPrepare().expectRollback(); - MockTxOp::shared_ptr opC(new MockTxOp());//will never get prepare as b will fail - opC->expectRollback(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast<TxOp>(opA)); - buffer.enlist(static_pointer_cast<TxOp>(opB)); - buffer.enlist(static_pointer_cast<TxOp>(opC)); - - BOOST_CHECK(!buffer.commitLocal(&store)); - BOOST_CHECK(store.isAborted()); - store.check(); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testPrepare) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectPrepare(); - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectPrepare(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast<TxOp>(opA)); - buffer.enlist(static_pointer_cast<TxOp>(opB)); - buffer.enlist(static_pointer_cast<TxOp>(opC)); - - BOOST_CHECK(buffer.prepare(0)); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testFailOnPrepare) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectPrepare(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectPrepare(); - MockTxOp::shared_ptr opC(new MockTxOp());//will never get prepare as b will fail - - TxBuffer buffer; - buffer.enlist(static_pointer_cast<TxOp>(opA)); - buffer.enlist(static_pointer_cast<TxOp>(opB)); - buffer.enlist(static_pointer_cast<TxOp>(opC)); - - BOOST_CHECK(!buffer.prepare(0)); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testRollback) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp(true)); - opB->expectRollback(); - MockTxOp::shared_ptr opC(new MockTxOp()); - opC->expectRollback(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast<TxOp>(opA)); - buffer.enlist(static_pointer_cast<TxOp>(opB)); - buffer.enlist(static_pointer_cast<TxOp>(opC)); - - buffer.rollback(); - opA->check(); - opB->check(); - opC->check(); -} - -QPID_AUTO_TEST_CASE(testBufferIsClearedAfterRollback) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectRollback(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectRollback(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast<TxOp>(opA)); - buffer.enlist(static_pointer_cast<TxOp>(opB)); - - buffer.rollback(); - buffer.commit();//second call should not reach ops - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_CASE(testBufferIsClearedAfterCommit) -{ - MockTxOp::shared_ptr opA(new MockTxOp()); - opA->expectCommit(); - MockTxOp::shared_ptr opB(new MockTxOp()); - opB->expectCommit(); - - TxBuffer buffer; - buffer.enlist(static_pointer_cast<TxOp>(opA)); - buffer.enlist(static_pointer_cast<TxOp>(opB)); - - buffer.commit(); - buffer.rollback();//second call should not reach ops - opA->check(); - opB->check(); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/TxMocks.h b/cpp/src/tests/TxMocks.h deleted file mode 100644 index 72cb50cd21..0000000000 --- a/cpp/src/tests/TxMocks.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _tests_TxMocks_h -#define _tests_TxMocks_h - - -#include "qpid/Exception.h" -#include "qpid/Msg.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/broker/TxOp.h" -#include <iostream> -#include <vector> - -using namespace qpid::broker; -using boost::static_pointer_cast; -using std::string; - -namespace qpid { -namespace tests { - -template <class T> void assertEqualVector(std::vector<T>& expected, std::vector<T>& actual){ - unsigned int i = 0; - while(i < expected.size() && i < actual.size()){ - BOOST_CHECK_EQUAL(expected[i], actual[i]); - i++; - } - if (i < expected.size()) { - throw qpid::Exception(QPID_MSG("Missing " << expected[i])); - } else if (i < actual.size()) { - throw qpid::Exception(QPID_MSG("Extra " << actual[i])); - } - BOOST_CHECK_EQUAL(expected.size(), actual.size()); -} - -class TxOpConstants{ -protected: - const string PREPARE; - const string COMMIT; - const string ROLLBACK; - - TxOpConstants() : PREPARE("PREPARE"), COMMIT("COMMIT"), ROLLBACK("ROLLBACK") {} -}; - -class MockTxOp : public TxOp, public TxOpConstants{ - std::vector<string> expected; - std::vector<string> actual; - bool failOnPrepare; - string debugName; -public: - typedef boost::shared_ptr<MockTxOp> shared_ptr; - - MockTxOp() : failOnPrepare(false) {} - MockTxOp(bool _failOnPrepare) : failOnPrepare(_failOnPrepare) {} - - void setDebugName(string name){ - debugName = name; - } - - void printExpected(){ - std::cout << std::endl << "MockTxOp[" << debugName << "] expects: "; - for (std::vector<string>::iterator i = expected.begin(); i < expected.end(); i++) { - if(i != expected.begin()) std::cout << ", "; - std::cout << *i; - } - std::cout << std::endl; - } - - void printActual(){ - std::cout << std::endl << "MockTxOp[" << debugName << "] actual: "; - for (std::vector<string>::iterator i = actual.begin(); i < actual.end(); i++) { - if(i != actual.begin()) std::cout << ", "; - std::cout << *i; - } - std::cout << std::endl; - } - - bool prepare(TransactionContext*) throw(){ - actual.push_back(PREPARE); - return !failOnPrepare; - } - void commit() throw(){ - actual.push_back(COMMIT); - } - void rollback() throw(){ - if(!debugName.empty()) std::cout << std::endl << "MockTxOp[" << debugName << "]::rollback()" << std::endl; - actual.push_back(ROLLBACK); - } - MockTxOp& expectPrepare(){ - expected.push_back(PREPARE); - return *this; - } - MockTxOp& expectCommit(){ - expected.push_back(COMMIT); - return *this; - } - MockTxOp& expectRollback(){ - expected.push_back(ROLLBACK); - return *this; - } - void check(){ - assertEqualVector(expected, actual); - } - - void accept(TxOpConstVisitor&) const {} - - ~MockTxOp(){} -}; - -class MockTransactionalStore : public TransactionalStore{ - const string BEGIN; - const string BEGIN2PC; - const string PREPARE; - const string COMMIT; - const string ABORT; - std::vector<string> expected; - std::vector<string> actual; - - enum states {OPEN = 1, PREPARED = 2, COMMITTED = 3, ABORTED = 4}; - int state; - - class TestTransactionContext : public TPCTransactionContext{ - MockTransactionalStore* store; - public: - TestTransactionContext(MockTransactionalStore* _store) : store(_store) {} - void prepare(){ - if(!store->isOpen()) throw "txn already completed"; - store->state = PREPARED; - } - - void commit(){ - if(!store->isOpen() && !store->isPrepared()) throw "txn already completed"; - store->state = COMMITTED; - } - - void abort(){ - if(!store->isOpen() && !store->isPrepared()) throw "txn already completed"; - store->state = ABORTED; - } - ~TestTransactionContext(){} - }; - -public: - MockTransactionalStore() : - BEGIN("BEGIN"), BEGIN2PC("BEGIN2PC"), PREPARE("PREPARE"), COMMIT("COMMIT"), ABORT("ABORT"), state(OPEN){} - - void collectPreparedXids(std::set<std::string>&) - { - throw "Operation not supported"; - } - - std::auto_ptr<TPCTransactionContext> begin(const std::string&){ - actual.push_back(BEGIN2PC); - std::auto_ptr<TPCTransactionContext> txn(new TestTransactionContext(this)); - return txn; - } - std::auto_ptr<TransactionContext> begin(){ - actual.push_back(BEGIN); - std::auto_ptr<TransactionContext> txn(new TestTransactionContext(this)); - return txn; - } - void prepare(TPCTransactionContext& ctxt){ - actual.push_back(PREPARE); - dynamic_cast<TestTransactionContext&>(ctxt).prepare(); - } - void commit(TransactionContext& ctxt){ - actual.push_back(COMMIT); - dynamic_cast<TestTransactionContext&>(ctxt).commit(); - } - void abort(TransactionContext& ctxt){ - actual.push_back(ABORT); - dynamic_cast<TestTransactionContext&>(ctxt).abort(); - } - MockTransactionalStore& expectBegin(){ - expected.push_back(BEGIN); - return *this; - } - MockTransactionalStore& expectBegin2PC(){ - expected.push_back(BEGIN2PC); - return *this; - } - MockTransactionalStore& expectPrepare(){ - expected.push_back(PREPARE); - return *this; - } - MockTransactionalStore& expectCommit(){ - expected.push_back(COMMIT); - return *this; - } - MockTransactionalStore& expectAbort(){ - expected.push_back(ABORT); - return *this; - } - void check(){ - assertEqualVector(expected, actual); - } - - bool isPrepared(){ - return state == PREPARED; - } - - bool isCommitted(){ - return state == COMMITTED; - } - - bool isAborted(){ - return state == ABORTED; - } - - bool isOpen() const{ - return state == OPEN; - } - ~MockTransactionalStore(){} -}; - -}} // namespace qpid::tests - -#endif diff --git a/cpp/src/tests/TxPublishTest.cpp b/cpp/src/tests/TxPublishTest.cpp deleted file mode 100644 index 210abf0a5b..0000000000 --- a/cpp/src/tests/TxPublishTest.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/RecoveryManager.h" -#include "qpid/broker/TxPublish.h" -#include "unit_test.h" -#include <iostream> -#include <list> -#include <vector> -#include "MessageUtils.h" -#include "TestMessageStore.h" - -using std::list; -using std::pair; -using std::vector; -using boost::intrusive_ptr; -using namespace qpid::broker; -using namespace qpid::framing; - -namespace qpid { -namespace tests { - -struct TxPublishTest -{ - - TestMessageStore store; - Queue::shared_ptr queue1; - Queue::shared_ptr queue2; - intrusive_ptr<Message> msg; - TxPublish op; - - TxPublishTest() : - queue1(new Queue("queue1", false, &store, 0)), - queue2(new Queue("queue2", false, &store, 0)), - msg(MessageUtils::createMessage("exchange", "routing_key", false, "id")), - op(msg) - { - msg->getProperties<DeliveryProperties>()->setDeliveryMode(PERSISTENT); - op.deliverTo(queue1); - op.deliverTo(queue2); - } -}; - - -QPID_AUTO_TEST_SUITE(TxPublishTestSuite) - -QPID_AUTO_TEST_CASE(testPrepare) -{ - TxPublishTest t; - - intrusive_ptr<PersistableMessage> pmsg = boost::static_pointer_cast<PersistableMessage>(t.msg); - //ensure messages are enqueued in store - t.op.prepare(0); - BOOST_CHECK_EQUAL((size_t) 2, t.store.enqueued.size()); - BOOST_CHECK_EQUAL(string("queue1"), t.store.enqueued[0].first); - BOOST_CHECK_EQUAL(pmsg, t.store.enqueued[0].second); - BOOST_CHECK_EQUAL(string("queue2"), t.store.enqueued[1].first); - BOOST_CHECK_EQUAL(pmsg, t.store.enqueued[1].second); - BOOST_CHECK_EQUAL( true, ( boost::static_pointer_cast<PersistableMessage>(t.msg))->isIngressComplete()); -} - -QPID_AUTO_TEST_CASE(testCommit) -{ - TxPublishTest t; - - //ensure messages are delivered to queue - t.op.prepare(0); - t.op.commit(); - BOOST_CHECK_EQUAL((uint32_t) 1, t.queue1->getMessageCount()); - intrusive_ptr<Message> msg_dequeue = t.queue1->get().payload; - - BOOST_CHECK_EQUAL( true, (boost::static_pointer_cast<PersistableMessage>(msg_dequeue))->isIngressComplete()); - BOOST_CHECK_EQUAL(t.msg, msg_dequeue); - - BOOST_CHECK_EQUAL((uint32_t) 1, t.queue2->getMessageCount()); - BOOST_CHECK_EQUAL(t.msg, t.queue2->get().payload); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/Url.cpp b/cpp/src/tests/Url.cpp deleted file mode 100644 index 234a62ee91..0000000000 --- a/cpp/src/tests/Url.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "unit_test.h" -#include "test_tools.h" -#include "qpid/Url.h" -#include <boost/assign.hpp> - -using namespace std; -using namespace qpid; -using namespace boost::assign; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(UrlTestSuite) - -#define URL_CHECK_STR(STR) BOOST_CHECK_EQUAL(Url(STR).str(), STR) -#define URL_CHECK_INVALID(STR) BOOST_CHECK_THROW(Url(STR), Url::Invalid) - -QPID_AUTO_TEST_CASE(TestParseTcp) { - URL_CHECK_STR("amqp:tcp:host:42"); - URL_CHECK_STR("amqp:tcp:host-._~%ff%23:42"); // unreserved chars and pct encoded hex. - // Check defaults - BOOST_CHECK_EQUAL(Url("amqp:host:42").str(), "amqp:tcp:host:42"); - BOOST_CHECK_EQUAL(Url("amqp:tcp:host").str(), "amqp:tcp:host:5672"); - BOOST_CHECK_EQUAL(Url("host").str(), "amqp:tcp:host:5672"); -} - -QPID_AUTO_TEST_CASE(TestParseInvalid) { - //host is required: - URL_CHECK_INVALID("amqp:tcp:"); - URL_CHECK_INVALID("amqp:"); - URL_CHECK_INVALID("amqp::42"); - URL_CHECK_INVALID(""); - - // Port must be numeric - URL_CHECK_INVALID("host:badPort"); -} - -QPID_AUTO_TEST_CASE(TestParseXyz) { - Url::addProtocol("xyz"); - URL_CHECK_STR("amqp:xyz:host:123"); - BOOST_CHECK_EQUAL(Url("xyz:host").str(), "amqp:xyz:host:5672"); -} - -QPID_AUTO_TEST_CASE(TestParseMultiAddress) { - Url::addProtocol("xyz"); - URL_CHECK_STR("amqp:tcp:host:0,xyz:foo:123,tcp:foo:0,xyz:bar:1"); - URL_CHECK_STR("amqp:xyz:foo:222,tcp:foo:0"); - URL_CHECK_INVALID("amqp:tcp:h:0,"); - URL_CHECK_INVALID(",amqp:tcp:h"); -} - -QPID_AUTO_TEST_CASE(TestParseUserPass) { - URL_CHECK_STR("amqp:user/pass@tcp:host:123"); - URL_CHECK_STR("amqp:user@tcp:host:123"); - BOOST_CHECK_EQUAL(Url("user/pass@host").str(), "amqp:user/pass@tcp:host:5672"); - BOOST_CHECK_EQUAL(Url("user@host").str(), "amqp:user@tcp:host:5672"); - - Url u("user/pass@host"); - BOOST_CHECK_EQUAL(u.getUser(), "user"); - BOOST_CHECK_EQUAL(u.getPass(), "pass"); - Url v("foo@host"); - BOOST_CHECK_EQUAL(v.getUser(), "foo"); - BOOST_CHECK_EQUAL(v.getPass(), ""); - u = v; - BOOST_CHECK_EQUAL(u.getUser(), "foo"); - BOOST_CHECK_EQUAL(u.getPass(), ""); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/Uuid.cpp b/cpp/src/tests/Uuid.cpp deleted file mode 100644 index 0195455ca3..0000000000 --- a/cpp/src/tests/Uuid.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/framing/Uuid.h" -#include "qpid/framing/Buffer.h" -#include "qpid/types/Uuid.h" -#include "qpid/sys/alloca.h" - -#include "unit_test.h" - -#include <set> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(UuidTestSuite) - -using namespace std; -using namespace qpid::framing; - -struct UniqueSet : public std::set<Uuid> { - void operator()(const Uuid& uuid) { - BOOST_REQUIRE(find(uuid) == end()); - insert(uuid); - } -}; - -QPID_AUTO_TEST_CASE(testUuidCtor) { - // Uniqueness - boost::array<Uuid,1000> uuids; - for_each(uuids.begin(), uuids.end(), mem_fun_ref(&Uuid::generate)); - UniqueSet unique; - for_each(uuids.begin(), uuids.end(), unique); -} - -boost::array<uint8_t, 16> sample = {{'\x1b', '\x4e', '\x28', '\xba', '\x2f', '\xa1', '\x11', '\xd2', '\x88', '\x3f', '\xb9', '\xa7', '\x61', '\xbd', '\xe3', '\xfb'}}; -const string sampleStr("1b4e28ba-2fa1-11d2-883f-b9a761bde3fb"); -const string zeroStr("00000000-0000-0000-0000-000000000000"); - -QPID_AUTO_TEST_CASE(testUuidIstream) { - Uuid uuid; - istringstream in(sampleStr); - in >> uuid; - BOOST_CHECK(!in.fail()); - BOOST_CHECK(uuid == sample); - - istringstream is(zeroStr); - Uuid zero; - is >> zero; - BOOST_CHECK(!in.fail()); - BOOST_CHECK_EQUAL(zero, Uuid()); -} - -QPID_AUTO_TEST_CASE(testUuidOstream) { - Uuid uuid(sample.c_array()); - ostringstream out; - out << uuid; - BOOST_CHECK(out.good()); - BOOST_CHECK_EQUAL(out.str(), sampleStr); - - ostringstream os; - os << Uuid(); - BOOST_CHECK(out.good()); - BOOST_CHECK_EQUAL(os.str(), zeroStr); -} - -QPID_AUTO_TEST_CASE(testUuidIOstream) { - Uuid a(true), b(true); - ostringstream os; - os << a << endl << b; - Uuid aa, bb; - istringstream is(os.str()); - is >> aa >> ws >> bb; - BOOST_CHECK(os.good()); - BOOST_CHECK_EQUAL(a, aa); - BOOST_CHECK_EQUAL(b, bb); -} - -QPID_AUTO_TEST_CASE(testUuidEncodeDecode) { - char* buff = static_cast<char*>(::alloca(Uuid::size())); - Buffer wbuf(buff, Uuid::size()); - Uuid uuid(sample.c_array()); - uuid.encode(wbuf); - - Buffer rbuf(buff, Uuid::size()); - Uuid decoded; - decoded.decode(rbuf); - BOOST_CHECK_EQUAL(string(sample.begin(), sample.end()), - string(decoded.begin(), decoded.end())); -} - -QPID_AUTO_TEST_CASE(testTypesUuid) -{ - //tests for the Uuid class in the types namespace (introduced - //to avoid pulling in dependencies from framing) - types::Uuid a; - types::Uuid b(true); - types::Uuid c(true); - types::Uuid d(b); - types::Uuid e; - e = c; - - BOOST_CHECK(!a); - BOOST_CHECK(b); - - BOOST_CHECK(a != b); - BOOST_CHECK(b != c); - - BOOST_CHECK_EQUAL(b, d); - BOOST_CHECK_EQUAL(c, e); - - ostringstream out; - out << b; - istringstream in(out.str()); - in >> a; - BOOST_CHECK(!in.fail()); - BOOST_CHECK_EQUAL(a, b); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/Variant.cpp b/cpp/src/tests/Variant.cpp deleted file mode 100644 index 40f1c0cf75..0000000000 --- a/cpp/src/tests/Variant.cpp +++ /dev/null @@ -1,775 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <iostream> -#include "qpid/types/Variant.h" -#include "qpid/amqp_0_10/Codecs.h" - -#include "unit_test.h" - -using namespace qpid::types; -using namespace qpid::amqp_0_10; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(VariantSuite) - -QPID_AUTO_TEST_CASE(testConversions) -{ - Variant value; - - //string to float/double - value = "1.5"; - BOOST_CHECK_EQUAL((float) 1.5, value.asFloat()); - BOOST_CHECK_EQUAL((double) 1.5, value.asDouble()); - - //float to string or double - value = 1.5f; - BOOST_CHECK_EQUAL((float) 1.5, value.asFloat()); - BOOST_CHECK_EQUAL((double) 1.5, value.asDouble()); - BOOST_CHECK_EQUAL(std::string("1.5"), value.asString()); - - //double to string (conversion to float not valid) - value = 1.5; - BOOST_CHECK_THROW(value.asFloat(), InvalidConversion); - BOOST_CHECK_EQUAL((double) 1.5, value.asDouble()); - BOOST_CHECK_EQUAL(std::string("1.5"), value.asString()); - - //uint8 to larger unsigned ints and string - value = (uint8_t) 7; - BOOST_CHECK_EQUAL((uint8_t) 7, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 7, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 7, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 7, value.asUint64()); - BOOST_CHECK_EQUAL(std::string("7"), value.asString()); - - value = (uint16_t) 8; - BOOST_CHECK_EQUAL(std::string("8"), value.asString()); - value = (uint32_t) 9; - BOOST_CHECK_EQUAL(std::string("9"), value.asString()); - - //uint32 to larger unsigned ints and string - value = (uint32_t) 9999999; - BOOST_CHECK_EQUAL((uint32_t) 9999999, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 9999999, value.asUint64()); - BOOST_CHECK_EQUAL(std::string("9999999"), value.asString()); - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - - value = "true"; - BOOST_CHECK(value.asBool()); - value = "false"; - BOOST_CHECK(!value.asBool()); - value = "1"; - BOOST_CHECK(value.asBool()); - value = "0"; - BOOST_CHECK(!value.asBool()); - value = "other"; - BOOST_CHECK_THROW(value.asBool(), InvalidConversion); -} - -QPID_AUTO_TEST_CASE(testConversionsFromString) -{ - Variant value; - value = "5"; - BOOST_CHECK_EQUAL(5, value.asInt16()); - BOOST_CHECK_EQUAL(5u, value.asUint16()); - - value = "-5"; - BOOST_CHECK_EQUAL(-5, value.asInt16()); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - - value = "18446744073709551615"; - BOOST_CHECK_EQUAL(18446744073709551615ull, value.asUint64()); - BOOST_CHECK_THROW(value.asInt64(), InvalidConversion); - - value = "9223372036854775808"; - BOOST_CHECK_EQUAL(9223372036854775808ull, value.asUint64()); - BOOST_CHECK_THROW(value.asInt64(), InvalidConversion); - - value = "-9223372036854775809"; - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt64(), InvalidConversion); - - value = "2147483648"; - BOOST_CHECK_EQUAL(2147483648ul, value.asUint32()); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - - value = "-2147483649"; - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - - value = "32768"; - BOOST_CHECK_EQUAL(32768u, value.asUint16()); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - - value = "-32769"; - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - - value = "-2.5"; - BOOST_CHECK_EQUAL(-2.5, value.asFloat()); - - value = "-0.875432e10"; - BOOST_CHECK_EQUAL(-0.875432e10, value.asDouble()); - - value = "-0"; - BOOST_CHECK_EQUAL(0, value.asInt16()); - BOOST_CHECK_EQUAL(0u, value.asUint16()); - - value = "-000"; - BOOST_CHECK_EQUAL(0, value.asInt16()); - BOOST_CHECK_EQUAL(0u, value.asUint16()); - - value = "-0010"; - BOOST_CHECK_EQUAL(-10, value.asInt16()); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); -} - -QPID_AUTO_TEST_CASE(testSizeConversionsUint) -{ - Variant value; - - //uint8 (in 7 bits) to other uints, ints - value = (uint8_t) 7; - BOOST_CHECK_EQUAL((uint8_t) 7, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 7, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 7, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 7, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 7, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 7, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 7, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 7, value.asInt64()); - - //uint8 (in 8 bits) to other uints, ints - value = (uint8_t) 200; - BOOST_CHECK_EQUAL((uint8_t) 200, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 200, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 200, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 200, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 200, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 200, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 200, value.asInt64()); - - - - //uint16 (in 7 bits) to other uints, ints - value = (uint16_t) 120; - BOOST_CHECK_EQUAL((uint8_t) 120, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 120, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 120, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 120, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 120, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 120, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 120, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 120, value.asInt64()); - - //uint16 (more than 7 bits) to other uints, ints - value = (uint16_t) 240; - BOOST_CHECK_EQUAL((uint8_t) 240, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 240, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 240, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 240, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 240, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 240, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 240, value.asInt64()); - - //uint16 (more than 8 bits) to other uints, ints - value = (uint16_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //uint16 (more than 15 bits) to other uints, ints - value = (uint16_t) 32770; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 32770, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 32770, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 32770, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 32770, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 32770, value.asInt64()); - - - - //uint32 (in 7 bits) to other uints, ints - value = (uint32_t) 120; - BOOST_CHECK_EQUAL((uint8_t) 120, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 120, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 120, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 120, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 120, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 120, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 120, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 120, value.asInt64()); - - //uint32 (more than 7 bits) to other uints, ints - value = (uint32_t) 240; - BOOST_CHECK_EQUAL((uint8_t) 240, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 240, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 240, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 240, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 240, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 240, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 240, value.asInt64()); - - //uint32 (more than 8 bits) to other uints, ints - value = (uint32_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //uint32 (more than 15 bits) to other uints, ints - value = (uint32_t) 32770; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 32770, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 32770, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 32770, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 32770, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 32770, value.asInt64()); - - //uint32 (more than 16 bits) to other uints, ints - value = (uint32_t) 66000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_EQUAL((uint32_t) 66000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 66000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 66000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 66000, value.asInt64()); - - - - //uint64 (in 7 bits) to other uints, ints - value = (uint64_t) 120; - BOOST_CHECK_EQUAL((uint8_t) 120, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 120, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 120, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 120, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 120, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 120, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 120, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 120, value.asInt64()); - - //uint64 (more than 7 bits) to other uints, ints - value = (uint64_t) 240; - BOOST_CHECK_EQUAL((uint8_t) 240, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 240, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 240, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 240, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 240, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 240, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 240, value.asInt64()); - - //uint64 (more than 8 bits) to other uints, ints - value = (uint64_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //uint64 (more than 15 bits) to other uints, ints - value = (uint64_t) 32770; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 32770, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 32770, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 32770, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 32770, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 32770, value.asInt64()); - - //uint64 (more than 16 bits) to other uints, ints - value = (uint64_t) 66000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_EQUAL((uint32_t) 66000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 66000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 66000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 66000, value.asInt64()); - - //uint64 (more than 31 bits) to other uints, ints - value = (uint64_t) 3000000000ul; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_EQUAL((uint32_t) 3000000000ul, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 3000000000ul, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) 3000000000ul, value.asInt64()); - - //uint64 (more than 32 bits) to other uints, ints - value = (uint64_t) 7000000000ull; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_EQUAL((uint64_t) 7000000000ull, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) 7000000000ull, value.asInt64()); - - //uint64 (more than 63 bits) to other uints, ints - value = (uint64_t) 0x8000000000000000ull; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_EQUAL((uint64_t) 0x8000000000000000ull, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt64(), InvalidConversion); -} - -QPID_AUTO_TEST_CASE(testSizeConversionsInt) -{ - Variant value; - - //int8 (positive in 7 bits) - value = (int8_t) 100; - BOOST_CHECK_EQUAL((uint8_t) 100, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 100, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 100, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 100, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 100, value.asInt64()); - - //int8 (negative) - value = (int8_t) -100; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_EQUAL((int8_t) -100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) -100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -100, value.asInt64()); - - - - //int16 (positive in 7 bits) - value = (int16_t) 100; - BOOST_CHECK_EQUAL((uint8_t) 100, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 100, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 100, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 100, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 100, value.asInt64()); - - //int16 (positive in 8 bits) - value = (int16_t) 200; - BOOST_CHECK_EQUAL((uint8_t) 200, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 200, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 200, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 200, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 200, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 200, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 200, value.asInt64()); - - //int16 (positive in more than 8 bits) - value = (int16_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //int16 (negative in 7 bits) - value = (int16_t) -100; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_EQUAL((int8_t) -100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) -100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -100, value.asInt64()); - - //int16 (negative in more than 7 bits) - value = (int16_t) -1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) -1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -1000, value.asInt64()); - - - - //int32 (positive in 7 bits) - value = (int32_t) 100; - BOOST_CHECK_EQUAL((uint8_t) 100, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 100, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 100, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 100, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 100, value.asInt64()); - - //int32 (positive in 8 bits) - value = (int32_t) 200; - BOOST_CHECK_EQUAL((uint8_t) 200, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 200, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 200, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 200, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 200, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 200, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 200, value.asInt64()); - - //int32 (positive in more than 8 bits) - value = (int32_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //int32 (positive in more than 15 bits) - value = (int32_t) 40000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 40000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 40000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 40000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 40000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 40000, value.asInt64()); - - //int32 (negative in 7 bits) - value = (int32_t) -100; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_EQUAL((int8_t) -100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) -100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -100, value.asInt64()); - - //int32 (negative in more than 7 bits) - value = (int32_t) -1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) -1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -1000, value.asInt64()); - - //int32 (negative in more than 15 bits) - value = (int32_t) -40000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) -40000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -40000, value.asInt64()); - - - - //int64 (positive in 7 bits) - value = (int64_t) 100; - BOOST_CHECK_EQUAL((uint8_t) 100, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 100, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 100, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 100, value.asUint64()); - BOOST_CHECK_EQUAL((int8_t) 100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) 100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 100, value.asInt64()); - - //int64 (positive in 8 bits) - value = (int64_t) 200; - BOOST_CHECK_EQUAL((uint8_t) 200, value.asUint8()); - BOOST_CHECK_EQUAL((uint16_t) 200, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 200, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 200, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 200, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 200, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 200, value.asInt64()); - - //int64 (positive in more than 8 bits) - value = (int64_t) 1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 1000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 1000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 1000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) 1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) 1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 1000, value.asInt64()); - - //int64 (positive in more than 15 bits) - value = (int64_t) 40000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_EQUAL((uint16_t) 40000, value.asUint16()); - BOOST_CHECK_EQUAL((uint32_t) 40000, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 40000, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) 40000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) 40000, value.asInt64()); - - //int64 (positive in more than 31 bits) - value = (int64_t) 3000000000ll; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_EQUAL((uint32_t) 3000000000ll, value.asUint32()); - BOOST_CHECK_EQUAL((uint64_t) 3000000000ll, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) 3000000000ll, value.asInt64()); - - //int64 (positive in more than 32 bits) - value = (int64_t) 5000000000ll; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_EQUAL((uint64_t) 5000000000ll, value.asUint64()); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) 5000000000ll, value.asInt64()); - - //int64 (negative in 7 bits) - value = (int64_t) -100; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_EQUAL((int8_t) -100, value.asInt8()); - BOOST_CHECK_EQUAL((int16_t) -100, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -100, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -100, value.asInt64()); - - //int64 (negative in more than 7 bits) - value = (int64_t) -1000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_EQUAL((int16_t) -1000, value.asInt16()); - BOOST_CHECK_EQUAL((int32_t) -1000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -1000, value.asInt64()); - - //int64 (negative in more than 15 bits) - value = (int64_t) -40000; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_EQUAL((int32_t) -40000, value.asInt32()); - BOOST_CHECK_EQUAL((int64_t) -40000, value.asInt64()); - - //int64 (negative in more than 31 bits) - value = (int64_t) -3000000000ll; - BOOST_CHECK_THROW(value.asUint8(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint16(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint32(), InvalidConversion); - BOOST_CHECK_THROW(value.asUint64(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt8(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt16(), InvalidConversion); - BOOST_CHECK_THROW(value.asInt32(), InvalidConversion); - BOOST_CHECK_EQUAL((int64_t) -3000000000ll, value.asInt64()); -} - -QPID_AUTO_TEST_CASE(testAssignment) -{ - Variant value("abc"); - Variant other = value; - BOOST_CHECK_EQUAL(VAR_STRING, value.getType()); - BOOST_CHECK_EQUAL(other.getType(), value.getType()); - BOOST_CHECK_EQUAL(other.asString(), value.asString()); - - const uint32_t i(1000); - value = i; - BOOST_CHECK_EQUAL(VAR_UINT32, value.getType()); - BOOST_CHECK_EQUAL(VAR_STRING, other.getType()); -} - -QPID_AUTO_TEST_CASE(testList) -{ - const std::string s("abc"); - const float f(9.876f); - const int16_t x(1000); - - Variant value = Variant::List(); - value.asList().push_back(Variant(s)); - value.asList().push_back(Variant(f)); - value.asList().push_back(Variant(x)); - BOOST_CHECK_EQUAL(3u, value.asList().size()); - Variant::List::const_iterator i = value.asList().begin(); - - BOOST_CHECK(i != value.asList().end()); - BOOST_CHECK_EQUAL(VAR_STRING, i->getType()); - BOOST_CHECK_EQUAL(s, i->asString()); - i++; - - BOOST_CHECK(i != value.asList().end()); - BOOST_CHECK_EQUAL(VAR_FLOAT, i->getType()); - BOOST_CHECK_EQUAL(f, i->asFloat()); - i++; - - BOOST_CHECK(i != value.asList().end()); - BOOST_CHECK_EQUAL(VAR_INT16, i->getType()); - BOOST_CHECK_EQUAL(x, i->asInt16()); - i++; - - BOOST_CHECK(i == value.asList().end()); -} - -QPID_AUTO_TEST_CASE(testMap) -{ - const std::string red("red"); - const float pi(3.14f); - const int16_t x(1000); - const Uuid u(true); - - Variant value = Variant::Map(); - value.asMap()["colour"] = red; - value.asMap()["pi"] = pi; - value.asMap()["my-key"] = x; - value.asMap()["id"] = u; - BOOST_CHECK_EQUAL(4u, value.asMap().size()); - - BOOST_CHECK_EQUAL(VAR_STRING, value.asMap()["colour"].getType()); - BOOST_CHECK_EQUAL(red, value.asMap()["colour"].asString()); - - BOOST_CHECK_EQUAL(VAR_FLOAT, value.asMap()["pi"].getType()); - BOOST_CHECK_EQUAL(pi, value.asMap()["pi"].asFloat()); - - BOOST_CHECK_EQUAL(VAR_INT16, value.asMap()["my-key"].getType()); - BOOST_CHECK_EQUAL(x, value.asMap()["my-key"].asInt16()); - - BOOST_CHECK_EQUAL(VAR_UUID, value.asMap()["id"].getType()); - BOOST_CHECK_EQUAL(u, value.asMap()["id"].asUuid()); - - value.asMap()["my-key"] = "now it's a string"; - BOOST_CHECK_EQUAL(VAR_STRING, value.asMap()["my-key"].getType()); - BOOST_CHECK_EQUAL(std::string("now it's a string"), value.asMap()["my-key"].asString()); -} - -QPID_AUTO_TEST_CASE(testIsEqualTo) -{ - BOOST_CHECK_EQUAL(Variant("abc"), Variant("abc")); - BOOST_CHECK_EQUAL(Variant(1234), Variant(1234)); - - Variant a = Variant::Map(); - a.asMap()["colour"] = "red"; - a.asMap()["pi"] = 3.14f; - a.asMap()["my-key"] = 1234; - Variant b = Variant::Map(); - b.asMap()["colour"] = "red"; - b.asMap()["pi"] = 3.14f; - b.asMap()["my-key"] = 1234; - BOOST_CHECK_EQUAL(a, b); -} - -QPID_AUTO_TEST_CASE(testEncoding) -{ - Variant a("abc"); - a.setEncoding("utf8"); - Variant b = a; - Variant map = Variant::Map(); - map.asMap()["a"] = a; - map.asMap()["b"] = b; - BOOST_CHECK_EQUAL(a.getEncoding(), std::string("utf8")); - BOOST_CHECK_EQUAL(a.getEncoding(), b.getEncoding()); - BOOST_CHECK_EQUAL(a.getEncoding(), map.asMap()["a"].getEncoding()); - BOOST_CHECK_EQUAL(b.getEncoding(), map.asMap()["b"].getEncoding()); - BOOST_CHECK_EQUAL(map.asMap()["a"].getEncoding(), map.asMap()["b"].getEncoding()); -} - -QPID_AUTO_TEST_CASE(testBufferEncoding) -{ - Variant a("abc"); - a.setEncoding("utf8"); - std::string buffer; - - Variant::Map inMap, outMap; - inMap["a"] = a; - - MapCodec::encode(inMap, buffer); - MapCodec::decode(buffer, outMap); - BOOST_CHECK_EQUAL(inMap, outMap); - - inMap["b"] = Variant(std::string(65535, 'X')); - inMap["b"].setEncoding("utf16"); - MapCodec::encode(inMap, buffer); - MapCodec::decode(buffer, outMap); - BOOST_CHECK_EQUAL(inMap, outMap); - - inMap["fail"] = Variant(std::string(65536, 'X')); - inMap["fail"].setEncoding("utf16"); - BOOST_CHECK_THROW(MapCodec::encode(inMap, buffer), std::exception); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/XmlClientSessionTest.cpp b/cpp/src/tests/XmlClientSessionTest.cpp deleted file mode 100644 index b3b7f12b53..0000000000 --- a/cpp/src/tests/XmlClientSessionTest.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* - * - * Licensed to the Apachef Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "unit_test.h" -#include "test_tools.h" -#include "BrokerFixture.h" -#include "qpid/sys/Shlib.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/client/Message.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/LocalQueue.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" - -#include <boost/optional.hpp> -#include <boost/lexical_cast.hpp> - -#include <vector> - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(XmlClientSessionTest) - -using namespace qpid::client; - -using namespace qpid::client::arg; -using namespace qpid::framing; -using namespace qpid; -using qpid::sys::Shlib; -using qpid::sys::Monitor; -using std::string; -using std::cout; -using std::endl; - - -Shlib shlib(getLibPath("XML_LIB")); - -class SubscribedLocalQueue : public LocalQueue { - private: - SubscriptionManager& subscriptions; - public: - SubscribedLocalQueue(SubscriptionManager& subs) : subscriptions(subs) {} - Message get () { return pop(); } - Message get (sys::Duration timeout) { return pop(timeout); } - virtual ~SubscribedLocalQueue() {} -}; - - -struct SimpleListener : public MessageListener -{ - Monitor lock; - std::vector<Message> messages; - - void received(Message& msg) - { - Monitor::ScopedLock l(lock); - messages.push_back(msg); - lock.notifyAll(); - } - - void waitFor(const uint n) - { - Monitor::ScopedLock l(lock); - while (messages.size() < n) { - lock.wait(); - } - } -}; - -struct ClientSessionFixture : public ProxySessionFixture -{ - void declareSubscribe(const string& q="odd_blue", - const string& dest="xml") - { - session.queueDeclare(queue=q); - session.messageSubscribe(queue=q, destination=dest, acquireMode=1); - session.messageFlow(destination=dest, unit=0, value=0xFFFFFFFF);//messages - session.messageFlow(destination=dest, unit=1, value=0xFFFFFFFF);//bytes - } -}; - -// ########### START HERE #################################### - -QPID_AUTO_TEST_CASE(testXmlBinding) { - ClientSessionFixture f; - - SubscriptionManager subscriptions(f.session); - SubscribedLocalQueue localQueue(subscriptions); - - f.session.exchangeDeclare(qpid::client::arg::exchange="xml", qpid::client::arg::type="xml"); - f.session.queueDeclare(qpid::client::arg::queue="odd_blue"); - subscriptions.subscribe(localQueue, "odd_blue"); - - FieldTable binding; - binding.setString("xquery", "declare variable $color external;" - "(./message/id mod 2 = 1) and ($color = 'blue')"); - f.session.exchangeBind(qpid::client::arg::exchange="xml", qpid::client::arg::queue="odd_blue", qpid::client::arg::bindingKey="query_name", qpid::client::arg::arguments=binding); - - Message message; - message.getDeliveryProperties().setRoutingKey("query_name"); - - message.getHeaders().setString("color", "blue"); - string m = "<message><id>1</id></message>"; - message.setData(m); - - f.session.messageTransfer(qpid::client::arg::content=message, qpid::client::arg::destination="xml"); - - Message m2 = localQueue.get(1*qpid::sys::TIME_SEC); - BOOST_CHECK_EQUAL(m, m2.getData()); -} - -/** - * Ensure that multiple queues can be bound using the same routing key - */ -QPID_AUTO_TEST_CASE(testXMLBindMultipleQueues) { - ClientSessionFixture f; - - - f.session.exchangeDeclare(arg::exchange="xml", arg::type="xml"); - f.session.queueDeclare(arg::queue="blue", arg::exclusive=true, arg::autoDelete=true); - f.session.queueDeclare(arg::queue="red", arg::exclusive=true, arg::autoDelete=true); - - FieldTable blue; - blue.setString("xquery", "./colour = 'blue'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="blue", arg::bindingKey="by-colour", arg::arguments=blue); - FieldTable red; - red.setString("xquery", "./colour = 'red'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="red", arg::bindingKey="by-colour", arg::arguments=red); - - Message sent1("<colour>blue</colour>", "by-colour"); - f.session.messageTransfer(arg::content=sent1, arg::destination="xml"); - - Message sent2("<colour>red</colour>", "by-colour"); - f.session.messageTransfer(arg::content=sent2, arg::destination="xml"); - - Message received; - BOOST_CHECK(f.subs.get(received, "blue")); - BOOST_CHECK_EQUAL(sent1.getData(), received.getData()); - BOOST_CHECK(f.subs.get(received, "red")); - BOOST_CHECK_EQUAL(sent2.getData(), received.getData()); -} - -//### Test: Bad XML does not kill the server - and does not even -// raise an exception, the content is not required to be XML. - -QPID_AUTO_TEST_CASE(testXMLSendBadXML) { - ClientSessionFixture f; - - f.session.exchangeDeclare(arg::exchange="xml", arg::type="xml"); - f.session.queueDeclare(arg::queue="blue", arg::exclusive=true, arg::autoDelete=true)\ - ; - f.session.queueDeclare(arg::queue="red", arg::exclusive=true, arg::autoDelete=true); - - FieldTable blue; - blue.setString("xquery", "./colour = 'blue'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="blue", arg::bindingKey="by-c\ -olour", arg::arguments=blue); - FieldTable red; - red.setString("xquery", "./colour = 'red'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="red", arg::bindingKey="by-co\ -lour", arg::arguments=red); - - Message sent1("<>colour>blue</colour>", "by-colour"); - f.session.messageTransfer(arg::content=sent1, arg::destination="xml"); - - BOOST_CHECK_EQUAL(1, 1); -} - - -//### Test: Bad XQuery does not kill the server, but does raise an exception - -QPID_AUTO_TEST_CASE(testXMLBadXQuery) { - ClientSessionFixture f; - - f.session.exchangeDeclare(arg::exchange="xml", arg::type="xml"); - f.session.queueDeclare(arg::queue="blue", arg::exclusive=true, arg::autoDelete=true)\ - ; - - try { - ScopedSuppressLogging sl; // Supress logging of error messages for expected error. - FieldTable blue; - blue.setString("xquery", "./colour $=! 'blue'"); - f.session.exchangeBind(arg::exchange="xml", arg::queue="blue", arg::bindingKey="by-c\ -olour", arg::arguments=blue); - } - catch (const InternalErrorException& e) { - return; - } - BOOST_ERROR("A bad XQuery must raise an exception when used in an XML Binding."); - -} - - -//### Test: double, string, and integer field values can all be bound to queries - -QPID_AUTO_TEST_CASE(testXmlBindingUntyped) { - ClientSessionFixture f; - - SubscriptionManager subscriptions(f.session); - SubscribedLocalQueue localQueue(subscriptions); - - f.session.exchangeDeclare(qpid::client::arg::exchange="xml", qpid::client::arg::type="xml"); - f.session.queueDeclare(qpid::client::arg::queue="odd_blue"); - subscriptions.subscribe(localQueue, "odd_blue"); - - FieldTable binding; - binding.setString("xquery", - "declare variable $s external;" - "declare variable $i external;" - "declare variable $d external;" - "$s = 'string' and $i = 1 and $d < 1"); - f.session.exchangeBind(qpid::client::arg::exchange="xml", qpid::client::arg::queue="odd_blue", qpid::client::arg::bindingKey="query_name", qpid::client::arg::arguments=binding); - - Message message; - message.getDeliveryProperties().setRoutingKey("query_name"); - - message.getHeaders().setString("s", "string"); - message.getHeaders().setInt("i", 1); - message.getHeaders().setDouble("d", 0.5); - string m = "<message>Hi, Mom!</message>"; - message.setData(m); - - f.session.messageTransfer(qpid::client::arg::content=message, qpid::client::arg::destination="xml"); - - Message m2 = localQueue.get(1*qpid::sys::TIME_SEC); - BOOST_CHECK_EQUAL(m, m2.getData()); -} - - -//### Test: double, string, and integer field values can all be bound to queries - -QPID_AUTO_TEST_CASE(testXmlBindingTyped) { - ClientSessionFixture f; - - SubscriptionManager subscriptions(f.session); - SubscribedLocalQueue localQueue(subscriptions); - - f.session.exchangeDeclare(qpid::client::arg::exchange="xml", qpid::client::arg::type="xml"); - f.session.queueDeclare(qpid::client::arg::queue="odd_blue"); - subscriptions.subscribe(localQueue, "odd_blue"); - - FieldTable binding; - binding.setString("xquery", - "declare variable $s as xs:string external;" - "declare variable $i as xs:integer external;" - "declare variable $d external;" // XQilla bug when declaring xs:float, xs:double types? Fine if untyped, acts as float. - "$s = 'string' and $i = 1 and $d < 1"); - f.session.exchangeBind(qpid::client::arg::exchange="xml", qpid::client::arg::queue="odd_blue", qpid::client::arg::bindingKey="query_name", qpid::client::arg::arguments=binding); - - Message message; - message.getDeliveryProperties().setRoutingKey("query_name"); - - message.getHeaders().setString("s", "string"); - message.getHeaders().setInt("i", 1); - message.getHeaders().setDouble("d", 0.5); - string m = "<message>Hi, Mom!</message>"; - message.setData(m); - - f.session.messageTransfer(qpid::client::arg::content=message, qpid::client::arg::destination="xml"); - - Message m2 = localQueue.get(1*qpid::sys::TIME_SEC); - BOOST_CHECK_EQUAL(m, m2.getData()); -} - - -//### Test: Each session can provide its own definition for a query name - - - -//### Test: Bindings persist, surviving broker restart - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/acl.py b/cpp/src/tests/acl.py deleted file mode 100755 index 5e9a150d8f..0000000000 --- a/cpp/src/tests/acl.py +++ /dev/null @@ -1,1077 +0,0 @@ -#!/usr/bin/env python -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import sys -import qpid -from qpid.util import connect -from qpid.connection import Connection -from qpid.datatypes import uuid4 -from qpid.testlib import TestBase010 -from qmf.console import Session -from qpid.datatypes import Message -import qpid.messaging - -class ACLFile: - def __init__(self, policy='data_dir/policy.acl'): - self.f = open(policy,'w') - - def write(self,line): - self.f.write(line) - - def close(self): - self.f.close() - -class ACLTests(TestBase010): - - def get_session(self, user, passwd): - socket = connect(self.broker.host, self.broker.port) - connection = Connection (sock=socket, username=user, password=passwd, - mechanism="PLAIN") - connection.start() - return connection.session(str(uuid4())) - - def reload_acl(self): - acl = self.qmf.getObjects(_class="acl")[0] - return acl.reloadACLFile() - - def get_acl_file(self): - return ACLFile(self.config.defines.get("policy-file", "data_dir/policy.acl")) - - def setUp(self): - aclf = self.get_acl_file() - aclf.write('acl allow all all\n') - aclf.close() - TestBase010.setUp(self) - self.startQmf() - self.reload_acl() - - def tearDown(self): - aclf = self.get_acl_file() - aclf.write('acl allow all all\n') - aclf.close() - self.reload_acl() - TestBase010.tearDown(self) - - #===================================== - # ACL general tests - #===================================== - - def test_deny_mode(self): - """ - Test the deny all mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow anonymous all all\n') - aclf.write('acl allow bob@QPID create queue\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - try: - session.queue_declare(queue="deny_queue") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request"); - self.fail("Error during queue create request"); - - try: - session.exchange_bind(exchange="amq.direct", queue="deny_queue", binding_key="routing_key") - self.fail("ACL should deny queue bind request"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - - def test_allow_mode(self): - """ - Test the allow all mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID bind exchange\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - try: - session.queue_declare(queue="allow_queue") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request"); - self.fail("Error during queue create request"); - - try: - session.exchange_bind(exchange="amq.direct", queue="allow_queue", binding_key="routing_key") - self.fail("ACL should deny queue bind request"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - - - #===================================== - # ACL file format tests - #===================================== - - def test_empty_groups(self): - """ - Test empty groups - """ - aclf = self.get_acl_file() - aclf.write('acl group\n') - aclf.write('acl group admins bob@QPID joe@QPID\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("Insufficient tokens for acl definition",0,len(result.text)) == -1): - self.fail("ACL Reader should reject the acl file due to empty group name") - - def test_illegal_acl_formats(self): - """ - Test illegal acl formats - """ - aclf = self.get_acl_file() - aclf.write('acl group admins bob@QPID joe@QPID\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("Unknown ACL permission",0,len(result.text)) == -1): - self.fail(result) - - def test_illegal_extension_lines(self): - """ - Test illegal extension lines - """ - - aclf = self.get_acl_file() - aclf.write('group admins bob@QPID \n') - aclf.write(' \ \n') - aclf.write('joe@QPID \n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("contains an illegal extension",0,len(result.text)) == -1): - self.fail(result) - - if (result.text.find("Non-continuation line must start with \"group\" or \"acl\"",0,len(result.text)) == -1): - self.fail(result) - - def test_llegal_extension_lines(self): - """ - Test proper extention lines - """ - aclf = self.get_acl_file() - aclf.write('group test1 joe@EXAMPLE.com \\ \n') # should be allowed - aclf.write(' jack@EXAMPLE.com \\ \n') # should be allowed - aclf.write('jill@TEST.COM \\ \n') # should be allowed - aclf.write('host/123.example.com@TEST.COM\n') # should be allowed - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("ACL format error",0,len(result.text)) != -1): - self.fail(result) - - def test_user_realm(self): - """ - Test a user defined without a realm - Ex. group admin rajith - """ - aclf = self.get_acl_file() - aclf.write('group admin bob\n') # shouldn't be allowed - aclf.write('acl deny admin bind exchange\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("Username 'bob' must contain a realm",0,len(result.text)) == -1): - self.fail(result) - - def test_allowed_chars_for_username(self): - """ - Test a user defined without a realm - Ex. group admin rajith - """ - aclf = self.get_acl_file() - aclf.write('group test1 joe@EXAMPLE.com\n') # should be allowed - aclf.write('group test2 jack_123-jill@EXAMPLE.com\n') # should be allowed - aclf.write('group test4 host/somemachine.example.com@EXAMPLE.COM\n') # should be allowed - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("ACL format error",0,len(result.text)) != -1): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('group test1 joe$H@EXAMPLE.com\n') # shouldn't be allowed - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("Username \"joe$H@EXAMPLE.com\" contains illegal characters",0,len(result.text)) == -1): - self.fail(result) - - #===================================== - # ACL validation tests - #===================================== - - def test_illegal_queue_policy(self): - """ - Test illegal queue policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ding\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "ding is not a valid value for 'policytype', possible values are one of" \ - " { 'ring' 'ring_strict' 'flow_to_disk' 'reject' }"; - if (result.text != expected): - self.fail(result) - - def test_illegal_queue_size(self): - """ - Test illegal queue policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'maxqueuesize', " \ - "values should be between 0 and 9223372036854775807"; - if (result.text != expected): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'maxqueuesize', " \ - "values should be between 0 and 9223372036854775807"; - if (result.text != expected): - self.fail(result) - - - def test_illegal_queue_count(self): - """ - Test illegal queue policy - """ - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=-1\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "-1 is not a valid value for 'maxqueuecount', " \ - "values should be between 0 and 9223372036854775807"; - if (result.text != expected): - self.fail(result) - - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=9223372036854775808\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - expected = "9223372036854775808 is not a valid value for 'maxqueuecount', " \ - "values should be between 0 and 9223372036854775807"; - if (result.text != expected): - self.fail(result) - - - #===================================== - # ACL queue tests - #===================================== - - def test_queue_allow_mode(self): - """ - Test cases for queue acl in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create queue name=q1 durable=true passive=true\n') - aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ring\n') - aclf.write('acl deny bob@QPID access queue name=q3\n') - aclf.write('acl deny bob@QPID purge queue name=q3\n') - aclf.write('acl deny bob@QPID delete queue name=q4\n') - aclf.write('acl deny bob@QPID create queue name=q5 maxqueuesize=1000 maxqueuecount=100\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="q1", durable=True, passive=True) - self.fail("ACL should deny queue create request with name=q1 durable=true passive=true"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.policy_type"] = "ring" - session.queue_declare(queue="q2", exclusive=True, arguments=queue_options) - self.fail("ACL should deny queue create request with name=q2 exclusive=true qpid.policy_type=ring"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.policy_type"] = "ring_strict" - session.queue_declare(queue="q2", exclusive=True, arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=q2 exclusive=true qpid.policy_type=ring_strict"); - - try: - queue_options = {} - queue_options["qpid.max_count"] = 200 - queue_options["qpid.max_size"] = 500 - session.queue_declare(queue="q5", exclusive=True, arguments=queue_options) - self.fail("ACL should deny queue create request with name=q2, qpid.max_size=500 and qpid.max_count=200"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 200 - queue_options["qpid.max_size"] = 100 - session.queue_declare(queue="q2", exclusive=True, arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=q2, qpid.max_size=100 and qpid.max_count=200 "); - try: - session.queue_declare(queue="q3", exclusive=True) - session.queue_declare(queue="q4", durable=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request for q3 and q4 with any parameter"); - - try: - session.queue_query(queue="q3") - self.fail("ACL should deny queue query request for q3"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_purge(queue="q3") - self.fail("ACL should deny queue purge request for q3"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_purge(queue="q4") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue purge request for q4"); - - try: - session.queue_delete(queue="q4") - self.fail("ACL should deny queue delete request for q4"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_delete(queue="q3") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue delete request for q3"); - - - def test_queue_deny_mode(self): - """ - Test cases for queue acl in deny mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID create queue name=q1 durable=true passive=true\n') - aclf.write('acl allow bob@QPID create queue name=q2 exclusive=true policytype=ring\n') - aclf.write('acl allow bob@QPID access queue name=q3\n') - aclf.write('acl allow bob@QPID purge queue name=q3\n') - aclf.write('acl allow bob@QPID create queue name=q3\n') - aclf.write('acl allow bob@QPID create queue name=q4\n') - aclf.write('acl allow bob@QPID delete queue name=q4\n') - aclf.write('acl allow bob@QPID create queue name=q5 maxqueuesize=1000 maxqueuecount=100\n') - aclf.write('acl allow anonymous all all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="q1", durable=True, passive=True) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=q1 durable=true passive=true"); - - try: - session.queue_declare(queue="q1", durable=False, passive=False) - self.fail("ACL should deny queue create request with name=q1 durable=true passive=false"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_declare(queue="q2", exclusive=False) - self.fail("ACL should deny queue create request with name=q2 exclusive=false"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 200 - queue_options["qpid.max_size"] = 500 - session.queue_declare(queue="q5", arguments=queue_options) - self.fail("ACL should deny queue create request with name=q2 maxqueuesize=500 maxqueuecount=200"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - queue_options = {} - queue_options["qpid.max_count"] = 100 - queue_options["qpid.max_size"] = 500 - session.queue_declare(queue="q5", arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request with name=q2 maxqueuesize=500 maxqueuecount=200"); - - try: - queue_options = {} - queue_options["qpid.policy_type"] = "ring" - session.queue_declare(queue="q2", exclusive=True, arguments=queue_options) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request for q2 with exclusive=true policytype=ring"); - - try: - session.queue_declare(queue="q3") - session.queue_declare(queue="q4") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue create request for q3 and q4"); - - try: - session.queue_query(queue="q4") - self.fail("ACL should deny queue query request for q4"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_purge(queue="q4") - self.fail("ACL should deny queue purge request for q4"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_purge(queue="q3") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue purge request for q3"); - - try: - session.queue_query(queue="q3") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue query request for q3"); - - try: - session.queue_delete(queue="q3") - self.fail("ACL should deny queue delete request for q3"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.queue_delete(queue="q4") - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow queue delete request for q4"); - - #===================================== - # ACL exchange tests - #===================================== - - def test_exchange_acl_allow_mode(self): - session = self.get_session('bob','bob') - session.queue_declare(queue="baz") - - """ - Test cases for exchange acl in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID create exchange name=testEx durable=true passive=true\n') - aclf.write('acl deny bob@QPID create exchange name=ex1 type=direct\n') - aclf.write('acl deny bob@QPID access exchange name=myEx queuename=q1 routingkey=rk1.*\n') - aclf.write('acl deny bob@QPID bind exchange name=myEx queuename=q1 routingkey=rk1\n') - aclf.write('acl deny bob@QPID unbind exchange name=myEx queuename=q1 routingkey=rk1\n') - aclf.write('acl deny bob@QPID delete exchange name=myEx\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - session.queue_declare(queue='q1') - session.queue_declare(queue='q2') - session.exchange_declare(exchange='myEx', type='direct') - - try: - session.exchange_declare(exchange='testEx', durable=True, passive=True) - self.fail("ACL should deny exchange create request with name=testEx durable=true passive=true"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='testEx', type='direct', durable=True, passive=False) - except qpid.session.SessionException, e: - print e - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange create request for testEx with any parameter other than durable=true and passive=true"); - - try: - session.exchange_declare(exchange='ex1', type='direct') - self.fail("ACL should deny exchange create request with name=ex1 type=direct"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='myXml', type='direct') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange create request for myXml with any parameter"); - - try: - session.exchange_query(name='myEx') - self.fail("ACL should deny exchange query request for myEx"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bound(exchange='myEx', queue='q1', binding_key='rk1.*') - self.fail("ACL should deny exchange bound request for myEx with queuename=q1 and routing_key='rk1.*' "); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_query(name='amq.topic') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange query request for exchange='amq.topic'"); - - try: - session.exchange_bound(exchange='myEx', queue='q1', binding_key='rk2.*') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bound request for myEx with queuename=q1 and binding_key='rk2.*'"); - - try: - session.exchange_bind(exchange='myEx', queue='q1', binding_key='rk1') - self.fail("ACL should deny exchange bind request with exchange='myEx' queuename='q1' bindingkey='rk1'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bind(exchange='myEx', queue='q1', binding_key='x') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bind request for exchange='myEx', queue='q1', binding_key='x'"); - - try: - session.exchange_bind(exchange='myEx', queue='q2', binding_key='rk1') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bind request for exchange='myEx', queue='q2', binding_key='rk1'"); - - try: - session.exchange_unbind(exchange='myEx', queue='q1', binding_key='rk1') - self.fail("ACL should deny exchange unbind request with exchange='myEx' queuename='q1' bindingkey='rk1'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_unbind(exchange='myEx', queue='q1', binding_key='x') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange unbind request for exchange='myEx', queue='q1', binding_key='x'"); - - try: - session.exchange_unbind(exchange='myEx', queue='q2', binding_key='rk1') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange unbind request for exchange='myEx', queue='q2', binding_key='rk1'"); - - try: - session.exchange_delete(exchange='myEx') - self.fail("ACL should deny exchange delete request for myEx"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_delete(exchange='myXml') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange delete request for myXml"); - - - def test_exchange_acl_deny_mode(self): - session = self.get_session('bob','bob') - session.queue_declare(queue='bar') - - """ - Test cases for exchange acl in deny mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID create exchange name=myEx durable=true passive=false\n') - aclf.write('acl allow bob@QPID bind exchange name=amq.topic queuename=bar routingkey=foo.*\n') - aclf.write('acl allow bob@QPID unbind exchange name=amq.topic queuename=bar routingkey=foo.*\n') - aclf.write('acl allow bob@QPID access exchange name=myEx queuename=q1 routingkey=rk1.*\n') - aclf.write('acl allow bob@QPID delete exchange name=myEx\n') - aclf.write('acl allow anonymous all all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='myEx', type='direct', durable=True, passive=False) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange create request for myEx with durable=true and passive=false"); - - try: - session.exchange_declare(exchange='myEx', type='direct', durable=False) - self.fail("ACL should deny exchange create request with name=myEx durable=false"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bind(exchange='amq.topic', queue='bar', binding_key='foo.bar') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bind request for exchange='amq.topic', queue='bar', binding_key='foor.bar'"); - - try: - session.exchange_bind(exchange='amq.topic', queue='baz', binding_key='foo.bar') - self.fail("ACL should deny exchange bind request for exchange='amq.topic', queue='baz', binding_key='foo.bar'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bind(exchange='amq.topic', queue='bar', binding_key='fooz.bar') - self.fail("ACL should deny exchange bind request for exchange='amq.topic', queue='bar', binding_key='fooz.bar'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_unbind(exchange='amq.topic', queue='bar', binding_key='foo.bar') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange unbind request for exchange='amq.topic', queue='bar', binding_key='foor.bar'"); - try: - session.exchange_unbind(exchange='amq.topic', queue='baz', binding_key='foo.bar') - self.fail("ACL should deny exchange unbind request for exchange='amq.topic', queue='baz', binding_key='foo.bar'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_unbind(exchange='amq.topic', queue='bar', binding_key='fooz.bar') - self.fail("ACL should deny exchange unbind request for exchange='amq.topic', queue='bar', binding_key='fooz.bar'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_query(name='amq.topic') - self.fail("ACL should deny exchange query request for amq.topic"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_bound(exchange='myEx', queue='q1', binding_key='rk2.*') - self.fail("ACL should deny exchange bound request for amq.topic with queuename=q1 and routing_key='rk2.*' "); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_query(name='myEx') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange query request for exchange='myEx'"); - - try: - session.exchange_bound(exchange='myEx', queue='q1', binding_key='rk1.*') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange bound request for myEx with queuename=q1 and binding_key='rk1.*'"); - - try: - session.exchange_delete(exchange='myXml') - self.fail("ACL should deny exchange delete request for myXml"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_delete(exchange='myEx') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow exchange delete request for myEx"); - - def test_create_and_delete_exchange_via_qmf(self): - """ - Test acl is enforced when creating/deleting via QMF - methods. Note that in order to be able to send the QMF methods - and receive the responses a significant amount of permissions - need to be enabled (TODO: can the set below be narrowed down - at all?) - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID create exchange\n') - aclf.write('acl allow admin@QPID delete exchange\n') - aclf.write('acl allow all access exchange\n') - aclf.write('acl allow all bind exchange\n') - aclf.write('acl allow all create queue\n') - aclf.write('acl allow all access queue\n') - aclf.write('acl allow all delete queue\n') - aclf.write('acl allow all consume queue\n') - aclf.write('acl allow all access method\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - bob = BrokerAdmin(self.config.broker, "bob", "bob") - bob.create_exchange("my-exchange") #should pass - #cleanup by deleting exchange - try: - bob.delete_exchange("my-exchange") #should fail - self.fail("ACL should deny exchange delete request for my-exchange"); - except Exception, e: - self.assertEqual(7,e.args[0]["error_code"]) - assert e.args[0]["error_text"].find("unauthorized-access") == 0 - admin = BrokerAdmin(self.config.broker, "admin", "admin") - admin.delete_exchange("my-exchange") #should pass - - anonymous = BrokerAdmin(self.config.broker) - try: - anonymous.create_exchange("another-exchange") #should fail - self.fail("ACL should deny exchange create request for another-exchange"); - except Exception, e: - self.assertEqual(7,e.args[0]["error_code"]) - assert e.args[0]["error_text"].find("unauthorized-access") == 0 - - - #===================================== - # ACL consume tests - #===================================== - - def test_consume_allow_mode(self): - """ - Test cases for consume in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID consume queue name=q1\n') - aclf.write('acl deny bob@QPID consume queue name=q2\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - - - try: - session.queue_declare(queue='q1') - session.queue_declare(queue='q2') - session.queue_declare(queue='q3') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow create queue request"); - - try: - session.message_subscribe(queue='q1', destination='myq1') - self.fail("ACL should deny subscription for queue='q1'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_subscribe(queue='q2', destination='myq1') - self.fail("ACL should deny subscription for queue='q2'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_subscribe(queue='q3', destination='myq1') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow subscription for q3"); - - - def test_consume_deny_mode(self): - """ - Test cases for consume in allow mode - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID consume queue name=q1\n') - aclf.write('acl allow bob@QPID consume queue name=q2\n') - aclf.write('acl allow bob@QPID create queue\n') - aclf.write('acl allow anonymous all\n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - - - try: - session.queue_declare(queue='q1') - session.queue_declare(queue='q2') - session.queue_declare(queue='q3') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow create queue request"); - - try: - session.message_subscribe(queue='q1', destination='myq1') - session.message_subscribe(queue='q2', destination='myq2') - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow subscription for q1 and q2"); - - try: - session.message_subscribe(queue='q3', destination='myq3') - self.fail("ACL should deny subscription for queue='q3'"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - - #===================================== - # ACL publish tests - #===================================== - - def test_publish_acl_allow_mode(self): - """ - Test various publish acl - """ - aclf = self.get_acl_file() - aclf.write('acl deny bob@QPID publish exchange name=amq.direct routingkey=rk1\n') - aclf.write('acl deny bob@QPID publish exchange name=amq.topic\n') - aclf.write('acl deny bob@QPID publish exchange name=myEx routingkey=rk2\n') - aclf.write('acl allow all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - - props = session.delivery_properties(routing_key="rk1") - - try: - session.message_transfer(destination="amq.direct", message=Message(props,"Test")) - self.fail("ACL should deny message transfer to name=amq.direct routingkey=rk1"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_transfer(destination="amq.topic", message=Message(props,"Test")) - self.fail("ACL should deny message transfer to name=amq.topic"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.exchange_declare(exchange='myEx', type='direct', durable=False) - session.message_transfer(destination="myEx", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange myEx with routing key rk1"); - - - props = session.delivery_properties(routing_key="rk2") - try: - session.message_transfer(destination="amq.direct", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange amq.direct with routing key rk2"); - - - def test_publish_acl_deny_mode(self): - """ - Test various publish acl - """ - aclf = self.get_acl_file() - aclf.write('acl allow bob@QPID publish exchange name=amq.direct routingkey=rk1\n') - aclf.write('acl allow bob@QPID publish exchange name=amq.topic\n') - aclf.write('acl allow bob@QPID publish exchange name=myEx routingkey=rk2\n') - aclf.write('acl allow bob@QPID create exchange\n') - aclf.write('acl allow anonymous all all \n') - aclf.write('acl deny all all') - aclf.close() - - result = self.reload_acl() - if (result.text.find("format error",0,len(result.text)) != -1): - self.fail(result) - - session = self.get_session('bob','bob') - - props = session.delivery_properties(routing_key="rk2") - - try: - session.message_transfer(destination="amq.direct", message=Message(props,"Test")) - self.fail("ACL should deny message transfer to name=amq.direct routingkey=rk2"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_transfer(destination="amq.topic", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange amq.topic with any routing key"); - - try: - session.exchange_declare(exchange='myEx', type='direct', durable=False) - session.message_transfer(destination="myEx", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange myEx with routing key=rk2"); - - props = session.delivery_properties(routing_key="rk1") - - try: - session.message_transfer(destination="myEx", message=Message(props,"Test")) - self.fail("ACL should deny message transfer to name=myEx routingkey=rk1"); - except qpid.session.SessionException, e: - self.assertEqual(403,e.args[0].error_code) - session = self.get_session('bob','bob') - - try: - session.message_transfer(destination="amq.direct", message=Message(props,"Test")) - except qpid.session.SessionException, e: - if (403 == e.args[0].error_code): - self.fail("ACL should allow message transfer to exchange amq.direct with routing key rk1"); - -class BrokerAdmin: - def __init__(self, broker, username=None, password=None): - self.connection = qpid.messaging.Connection(broker) - if username: - self.connection.username = username - self.connection.password = password - self.connection.sasl_mechanisms = "PLAIN" - self.connection.open() - self.session = self.connection.session() - self.sender = self.session.sender("qmf.default.direct/broker") - self.reply_to = "responses-#; {create:always}" - self.receiver = self.session.receiver(self.reply_to) - - def invoke(self, method, arguments): - content = { - "_object_id": {"_object_name": "org.apache.qpid.broker:broker:amqp-broker"}, - "_method_name": method, - "_arguments": arguments - } - request = qpid.messaging.Message(reply_to=self.reply_to, content=content) - request.properties["x-amqp-0-10.app-id"] = "qmf2" - request.properties["qmf.opcode"] = "_method_request" - self.sender.send(request) - response = self.receiver.fetch() - self.session.acknowledge() - if response.properties['x-amqp-0-10.app-id'] == 'qmf2': - if response.properties['qmf.opcode'] == '_method_response': - return response.content['_arguments'] - elif response.properties['qmf.opcode'] == '_exception': - raise Exception(response.content['_values']) - else: raise Exception("Invalid response received, unexpected opcode: %s" % response.properties['qmf.opcode']) - else: raise Exception("Invalid response received, not a qmfv2 method: %s" % response.properties['x-amqp-0-10.app-id']) - def create_exchange(self, name, exchange_type=None, options={}): - properties = options - if exchange_type: properties["exchange_type"] = exchange_type - self.invoke("create", {"type": "exchange", "name":name, "properties":properties}) - - def create_queue(self, name, properties={}): - self.invoke("create", {"type": "queue", "name":name, "properties":properties}) - - def delete_exchange(self, name): - self.invoke("delete", {"type": "exchange", "name":name}) - - def delete_queue(self, name): - self.invoke("delete", {"type": "queue", "name":name}) diff --git a/cpp/src/tests/ais_check b/cpp/src/tests/ais_check deleted file mode 100755 index 92eaa9dd39..0000000000 --- a/cpp/src/tests/ais_check +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -srcdir=`dirname $0` - -# Check AIS requirements and run tests if found. -ps -u root | grep 'aisexec\|corosync' >/dev/null || { - echo WARNING: Skipping cluster tests, the aisexec or corosync daemon is not running. - exit 0; # A warning, not a failure. -} - -# Execute command with the ais group set if user is a member. -with_ais_group() { - if id -nG | grep '\<ais\>' >/dev/null; then sg ais -c "$*" - else "$@" - fi -} diff --git a/cpp/src/tests/ais_test.cpp b/cpp/src/tests/ais_test.cpp deleted file mode 100644 index 00c61242e4..0000000000 --- a/cpp/src/tests/ais_test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// Defines test_main function to link with actual unit test code. -#define BOOST_AUTO_TEST_MAIN // Boost 1.33 -#define BOOST_TEST_MAIN -#include "unit_test.h" - diff --git a/cpp/src/tests/allhosts b/cpp/src/tests/allhosts deleted file mode 100755 index e43571aed4..0000000000 --- a/cpp/src/tests/allhosts +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -usage() { - echo "Usage: $0 [options] command. -Run a command on each host in \$HOSTS. -Options: - -l USER passed to ssh - run as USER. - -t passed to ssh - create a terminal. - -b run in background, wait for commands to complete. - -d run in background, don't wait for commands to complete. - -s SECONDS sleep between starting commands. - -q don't print banner lines for each host. - -o SUFFIX log output of each command to <host>.SUFFIX -" - exit 1 -} - -while getopts "tl:bs:dqo:" opt; do - case $opt in - l) SSHOPTS="-l$OPTARG $SSHOPTS" ;; - t) SSHOPTS="-t $SSHOPTS" ;; - b) BACKGROUND=1 ;; - d) BACKGROUND=1; DISOWN=1 ;; - s) SLEEP="sleep $OPTARG" ;; - q) NOBANNER=1 ;; - o) SUFFIX=$OPTARG ;; - *) usage;; - esac -done -shift `expr $OPTIND - 1` -test "$*" || usage; - -OK_FILE=`mktemp` # Will be deleted if anything goes wrong. -trap "rm -f $OK_FILE" EXIT - -do_ssh() { - h=$1; shift - if test $SUFFIX ; then ssh $SSHOPTS $h "$@" &> $h.$SUFFIX - else ssh $SSHOPTS $h "$@"; fi || rm -rf $OK_FILE; -} - -for h in $HOSTS ; do - test "$NOBANNER" || echo "== ssh $SSHOPTS $h $@ ==" - if [ "$BACKGROUND" = 1 ]; then - do_ssh $h "$@" & - CHILDREN="$! $CHILDREN" - else - do_ssh $h "$@" - fi - $SLEEP -done - -if [ "$DISOWN" = 1 ]; then - for c in $CHILDREN; do disown $c; done -else - wait -fi - -test -f $OK_FILE diff --git a/cpp/src/tests/amqp_0_10/Map.cpp b/cpp/src/tests/amqp_0_10/Map.cpp deleted file mode 100644 index ffb235829e..0000000000 --- a/cpp/src/tests/amqp_0_10/Map.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "amqp_0_10/unit_test.h" -#include "qpid/amqp_0_10/Map.h" -#include "qpid/amqp_0_10/Array.h" -#include "qpid/amqp_0_10/Struct32.h" -#include "qpid/amqp_0_10/UnknownType.h" -#include "qpid/amqp_0_10/Codec.h" -#include <iostream> - -using namespace qpid::amqp_0_10; -using namespace std; - -QPID_AUTO_TEST_SUITE(MapTestSuite) - - QPID_AUTO_TEST_CASE(testGetSet) { - MapValue v; - v = Str8("foo"); - BOOST_CHECK(v.get<Str8>()); - BOOST_CHECK(!v.get<uint8_t>()); - BOOST_CHECK_EQUAL(*v.get<Str8>(), "foo"); - - v = uint8_t(42); - BOOST_CHECK(!v.get<Str8>()); - BOOST_CHECK(v.get<uint8_t>()); - BOOST_CHECK_EQUAL(*v.get<uint8_t>(), 42); - - v = uint16_t(12); - BOOST_CHECK(v.get<uint16_t>()); - BOOST_CHECK_EQUAL(*v.get<uint16_t>(), 12); -} - -template <class R> struct TestVisitor : public MapValue::Visitor<R> { - template <class T> R operator()(const T&) const { throw MapValue::BadTypeException(); } - R operator()(const R& r) const { return r; } -}; - -QPID_AUTO_TEST_CASE(testVisit) { - MapValue v; - v = Str8("foo"); - BOOST_CHECK_EQUAL(v.apply_visitor(TestVisitor<Str8>()), "foo"); - v = Uint16(42); - BOOST_CHECK_EQUAL(v.apply_visitor(TestVisitor<Uint16>()), 42); - try { - v.apply_visitor(TestVisitor<bool>()); - BOOST_FAIL("Expecting exception"); - } - catch(const MapValue::BadTypeException&) {} -} - - -QPID_AUTO_TEST_CASE(testEncodeMapValue) { - MapValue mv; - std::string data; - mv = Str8("hello"); - Codec::encode(back_inserter(data))(mv); - BOOST_CHECK_EQUAL(data.size(), Codec::size(mv)); - MapValue mv2; - Codec::decode(data.begin())(mv2); - BOOST_CHECK_EQUAL(mv2.getCode(), 0x85); - BOOST_REQUIRE(mv2.get<Str8>()); - BOOST_CHECK_EQUAL(*mv2.get<Str8>(), "hello"); -} - -QPID_AUTO_TEST_CASE(testEncode) { - Map map; - std::string data; - map["A"] = true; - map["b"] = Str8("hello"); - Codec::encode(back_inserter(data))(map); - BOOST_CHECK_EQUAL(Codec::size(map), data.size()); - Map map2; - Codec::decode(data.begin())(map2); - BOOST_CHECK_EQUAL(map.size(), 2u); - BOOST_CHECK(map["A"].get<bool>()); - BOOST_CHECK_EQUAL(*map["b"].get<Str8>(), "hello"); -} - - -QPID_AUTO_TEST_SUITE_END() diff --git a/cpp/src/tests/amqp_0_10/ProxyTemplate.cpp b/cpp/src/tests/amqp_0_10/ProxyTemplate.cpp deleted file mode 100644 index f54ee0da22..0000000000 --- a/cpp/src/tests/amqp_0_10/ProxyTemplate.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "amqp_0_10/unit_test.h" -#include "qpid/amqp_0_10/ProxyTemplate.h" -#include <boost/any.hpp> - -QPID_AUTO_TEST_SUITE(ProxyTemplateTestSuite) - -using namespace qpid::amqp_0_10; - -struct ToAny { - template <class T> - boost::any operator()(const T& t) { return boost::any(t); } -}; - -struct AnyProxy : public ProxyTemplate<ToAny, boost::any> {}; - -QPID_AUTO_TEST_CASE(testAnyProxy) { - AnyProxy p; - boost::any a=p.connectionTune(1,2,3,4); - BOOST_CHECK_EQUAL(a.type().name(), typeid(connection::Tune).name()); - connection::Tune* tune=boost::any_cast<connection::Tune>(&a); - BOOST_REQUIRE(tune); - BOOST_CHECK_EQUAL(tune->channelMax, 1u); - BOOST_CHECK_EQUAL(tune->maxFrameSize, 2u); - BOOST_CHECK_EQUAL(tune->heartbeatMin, 3u); - BOOST_CHECK_EQUAL(tune->heartbeatMax, 4u); -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/cpp/src/tests/amqp_0_10/apply.cpp b/cpp/src/tests/amqp_0_10/apply.cpp deleted file mode 100644 index 0aa4421791..0000000000 --- a/cpp/src/tests/amqp_0_10/apply.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "amqp_0_10/unit_test.h" -#include "qpid/amqp_0_10/specification.h" -#include "qpid/amqp_0_10/ApplyControl.h" - -QPID_AUTO_TEST_SUITE(VisitorTestSuite) - -using namespace qpid::amqp_0_10; - -struct GetCode : public ApplyFunctor<uint8_t> { - template <class T> uint8_t operator()(const T&) const { return T::CODE; } -}; - -struct SetChannelMax : ApplyFunctor<void> { - template <class T> void operator()(T&) const { BOOST_FAIL(""); } - void operator()(connection::Tune& t) const { t.channelMax=42; } -}; - -struct TestFunctor { - typedef bool result_type; - bool operator()(const connection::Tune& tune) { - BOOST_CHECK_EQUAL(tune.channelMax, 1u); - BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u); - BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u); - BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u); - return true; - } - template <class T> - bool operator()(const T&) { return false; } -}; - -QPID_AUTO_TEST_CASE(testApply) { - connection::Tune tune(1,2,3,4); - Control* p = &tune; - - // boost oddity - without the cast we get undefined symbol errors. - BOOST_CHECK_EQUAL(apply(GetCode(), *p), (uint8_t)connection::Tune::CODE); - - TestFunctor tf; - BOOST_CHECK(apply(tf, *p)); - - connection::Start start; - p = &start; - BOOST_CHECK(!apply(tf, *p)); - - apply(SetChannelMax(), tune); - BOOST_CHECK_EQUAL(tune.channelMax, 42); -} - -struct VoidTestFunctor { - typedef void result_type; - - int code; - VoidTestFunctor() : code() {} - - void operator()(const connection::Tune& tune) { - BOOST_CHECK_EQUAL(tune.channelMax, 1u); - BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u); - BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u); - BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u); - code=connection::Tune::CODE; - } - template <class T> - void operator()(const T&) { code=0xFF; } -}; - -QPID_AUTO_TEST_CASE(testApplyVoid) { - connection::Tune tune(1,2,3,4); - Control* p = &tune; - VoidTestFunctor tf; - apply(tf, *p); - BOOST_CHECK_EQUAL(uint8_t(connection::Tune::CODE), tf.code); - - connection::Start start; - p = &start; - apply(tf, *p); - BOOST_CHECK_EQUAL(0xFF, tf.code); -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/cpp/src/tests/amqp_0_10/handlers.cpp b/cpp/src/tests/amqp_0_10/handlers.cpp deleted file mode 100644 index 91bb304a17..0000000000 --- a/cpp/src/tests/amqp_0_10/handlers.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "amqp_0_10/unit_test.h" -#include "qpid/Exception.h" -#include "qpid/amqp_0_10/Unit.h" -#include "qpid/amqp_0_10/ControlHolder.h" -#include "qpid/amqp_0_10/CommandHolder.h" -#include "qpid/amqp_0_10/handlers.h" -#include "qpid/amqp_0_10/specification.h" - -QPID_AUTO_TEST_SUITE(handler_tests) - -using namespace qpid::amqp_0_10; -using namespace std; - -string called; // Set by called handler function - -// Note on handlers: -// -// Control and Command handlers are separate, both behave the same way, -// so substitute "control or command" for command in the following. -// -// Command handlers derive from CommandHandler and implement functions -// for all the commands they handle. Handling an unimplemented command -// will raise NotImplementedException. -// -// Using virtual inheritance from CommandHandler allows multiple -// handlers to be aggregated into one with multiple inheritance, -// See test code for example. -// -// E.g. the existing broker model would have two control handlers: -// - ConnectionHandler: ControlHandler for connection controls. -// - SessionHandler: ControlHandler for session controls. -// It would have class-command handlers for each AMQP class: -// - QueueHandler, MessageHandler etc.. handle each class. -// And an aggregate handler in place of BrokerAdapter -// - BrokerCommandHandler: public QueueHandler, MessageHandler ... -// -// In other applications (e.g. cluster) any combination of commands -// can be handled by a given handler. It _might_ simplify the code -// to collaps ConnectionHandler and SessionHandler into a single -// ControlHandler (or it might not.) - -struct TestExecutionHandler : public virtual CommandHandler { - void executionSync() { called = "executionSync"; } - // ... etc. for all execution commands -}; - -struct TestMessageHandler : public virtual CommandHandler { - void messageCancel(const Str8&) { called="messageCancel"; } - // ... etc. -}; - -// Aggregate handler for all recognised commands. -struct TestCommandHandler : - public TestExecutionHandler, - public TestMessageHandler - // ... etc. handlers for all command classes. -{}; // Nothing to do. - - -// Sample unit handler, written as a static_visitor. -// Note it could equally be written with if/else statements -// in handle. -// -struct TestUnitHandler : public boost::static_visitor<void> { - TestCommandHandler handler; - void handle(const Unit& u) { u.applyVisitor(*this); } - - void operator()(const Body&) { called="Body"; } - void operator()(const Header&) { called="Header"; } - void operator()(const ControlHolder&) { throw qpid::Exception("I don't do controls."); } - void operator()(const CommandHolder& c) { c.invoke(handler); } -}; - -QPID_AUTO_TEST_CASE(testHandlers) { - TestUnitHandler handler; - Unit u; - - u = Body(); - handler.handle(u); - BOOST_CHECK_EQUAL("Body", called); - - u = Header(); - handler.handle(u); - BOOST_CHECK_EQUAL("Header", called); - - // in_place<Foo>(...) is equivalent to Foo(...) but - // constructs Foo directly in the holder, avoiding - // a copy. - - u = CommandHolder(in_place<execution::Sync>()); - handler.handle(u); - BOOST_CHECK_EQUAL("executionSync", called); - - u = ControlHolder(in_place<connection::Start>(Map(), Str16Array(), Str16Array())); - try { - handler.handle(u); - } catch (const qpid::Exception&) {} - - u = CommandHolder(in_place<message::Cancel>(Str8())); - handler.handle(u); - BOOST_CHECK_EQUAL("messageCancel", called); -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/cpp/src/tests/amqp_0_10/serialize.cpp b/cpp/src/tests/amqp_0_10/serialize.cpp deleted file mode 100644 index 975d6206ec..0000000000 --- a/cpp/src/tests/amqp_0_10/serialize.cpp +++ /dev/null @@ -1,429 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "amqp_0_10/unit_test.h" -#include "amqp_0_10/allSegmentTypes.h" - -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/Buffer.h" - -#include "qpid/amqp_0_10/Packer.h" -#include "qpid/amqp_0_10/built_in_types.h" -#include "qpid/amqp_0_10/Codec.h" -#include "qpid/amqp_0_10/specification.h" -#include "qpid/amqp_0_10/ControlHolder.h" -#include "qpid/amqp_0_10/Struct32.h" -#include "qpid/amqp_0_10/FrameHeader.h" -#include "qpid/amqp_0_10/Map.h" -#include "qpid/amqp_0_10/Unit.h" -#include "allSegmentTypes.h" - -#include <boost/test/test_case_template.hpp> -#include <boost/type_traits/is_arithmetic.hpp> -#include <boost/utility/enable_if.hpp> -#include <boost/optional.hpp> -#include <boost/mpl/vector.hpp> -#include <boost/mpl/back_inserter.hpp> -#include <boost/mpl/copy.hpp> -#include <boost/mpl/empty_sequence.hpp> -#include <boost/current_function.hpp> -#include <iterator> -#include <string> -#include <sstream> -#include <iostream> -#include <netinet/in.h> - -// Missing operators needed for tests. -namespace boost { -template <class T, size_t N> -std::ostream& operator<<(std::ostream& out, const array<T,N>& a) { - std::ostream_iterator<T> o(out, " "); - std::copy(a.begin(), a.end(), o); - return out; -} -} // boost - -QPID_AUTO_TEST_SUITE(SerializeTestSuite) - -using namespace std; -namespace mpl=boost::mpl; -using namespace qpid::amqp_0_10; -using qpid::framing::in_place; - -template <class A, class B> struct concat2 { typedef typename mpl::copy<B, typename mpl::back_inserter<A> >::type type; }; -template <class A, class B, class C> struct concat3 { typedef typename concat2<A, typename concat2<B, C>::type>::type type; }; -template <class A, class B, class C, class D> struct concat4 { typedef typename concat2<A, typename concat3<B, C, D>::type>::type type; }; - -typedef mpl::vector<Boolean, Char, Int32, Int64, Int8, Uint16, CharUtf32, Uint32, Uint64, Bin8, Uint8>::type IntegralTypes; -typedef mpl::vector<Bin1024, Bin128, Bin16, Bin256, Bin32, Bin40, Bin512, Bin64, Bin72>::type BinTypes; -typedef mpl::vector<Double, Float>::type FloatTypes; -typedef mpl::vector<SequenceNo, Uuid, Datetime, Dec32, Dec64> FixedSizeClassTypes; -typedef mpl::vector<Map, Vbin8, Str8Latin, Str8, Str8Utf16, Vbin16, Str16Latin, Str16, Str16Utf16, Vbin32> VariableSizeTypes; - -typedef concat4<IntegralTypes, BinTypes, FloatTypes, FixedSizeClassTypes>::type FixedSizeTypes; -typedef concat2<FixedSizeTypes, VariableSizeTypes>::type AllTypes; - -// TODO aconway 2008-02-20: should test 64 bit integrals for order also. -QPID_AUTO_TEST_CASE(testNetworkByteOrder) { - string data; - - uint32_t l = 0x11223344; - Codec::encode(std::back_inserter(data))(l); - uint32_t enc=reinterpret_cast<const uint32_t&>(*data.data()); - uint32_t l2 = ntohl(enc); - BOOST_CHECK_EQUAL(l, l2); - - data.clear(); - uint16_t s = 0x1122; - Codec::encode(std::back_inserter(data))(s); - uint32_t s2 = ntohs(*reinterpret_cast<const uint32_t*>(data.data())); - BOOST_CHECK_EQUAL(s, s2); -} - -QPID_AUTO_TEST_CASE(testSetLimit) { - typedef Codec::Encoder<back_insert_iterator<string> > Encoder; - string data; - Encoder encode(back_inserter(data), 3); - encode('1')('2')('3'); - try { - encode('4'); - BOOST_FAIL("Expected exception"); - } catch (...) {} // FIXME aconway 2008-04-03: catch proper exception - BOOST_CHECK_EQUAL(data, "123"); -} - -QPID_AUTO_TEST_CASE(testScopedLimit) { - typedef Codec::Encoder<back_insert_iterator<string> > Encoder; - string data; - Encoder encode(back_inserter(data), 10); - encode(Str8("123")); // 4 bytes - { - Encoder::ScopedLimit l(encode, 3); - encode('a')('b')('c'); - try { - encode('d'); - BOOST_FAIL("Expected exception"); - } catch(...) {} // FIXME aconway 2008-04-03: catch proper exception - } - BOOST_CHECK_EQUAL(data, "\003123abc"); - encode('x')('y')('z'); - try { - encode('!'); - BOOST_FAIL("Expected exception"); - } catch(...) {} // FIXME aconway 2008-04-03: catch proper exception - BOOST_CHECK_EQUAL(data.size(), 10u); -} - -// Assign test values to the various types. -void testValue(bool& b) { b = true; } -void testValue(Bit&) { } -template <class T> typename boost::enable_if<boost::is_arithmetic<T> >::type testValue(T& n) { n=42; } -void testValue(CharUtf32& c) { c = 43; } -void testValue(long long& l) { l = 0x012345; } -void testValue(Datetime& dt) { dt = qpid::sys::now(); } -void testValue(Uuid& uuid) { uuid=Uuid(true); } -template <class E, class M> void testValue(Decimal<E,M>& d) { d.exponent=2; d.mantissa=0x1122; } -void testValue(SequenceNo& s) { s = 42; } -template <size_t N> void testValue(Bin<N>& a) { a.assign(42); } -template <class T, class S, int Unique> void testValue(SerializableString<T, S, Unique>& s) { - char msg[]="foobar"; - s.assign(msg, msg+sizeof(msg)); -} -void testValue(Str16& s) { s = "the quick brown fox jumped over the lazy dog"; } -void testValue(Str8& s) { s = "foobar"; } -void testValue(Map& m) { m["s"] = Str8("foobar"); m["b"] = true; m["c"] = uint16_t(42); } - -//typedef mpl::vector<Str8, Str16>::type TestTypes; -/*BOOST_AUTO_TEST_CASE_TEMPLATE(testEncodeDecode, T, AllTypes) -{ - string data; - T t; - testValue(t); - Codec::encode(std::back_inserter(data))(t); - - BOOST_CHECK_EQUAL(Codec::size(t), data.size()); - - T t2; - Codec::decode(data.begin())(t2); - BOOST_CHECK_EQUAL(t,t2); -} -*/ - -struct TestMe { - bool encoded, decoded; - char value; - TestMe(char v) : encoded(), decoded(), value(v) {} - template <class S> void encode(S& s) const { - const_cast<TestMe*>(this)->encoded=true; s(value); - } - template <class S> void decode(S& s) { decoded=true; s(value); } - template <class S> void serialize(S& s) { s.split(*this); } -}; - -QPID_AUTO_TEST_CASE(testSplit) { - string data; - TestMe t1('x'); - Codec::encode(std::back_inserter(data))(t1); - BOOST_CHECK(t1.encoded); - BOOST_CHECK(!t1.decoded); - BOOST_CHECK_EQUAL(data, "x"); - - TestMe t2('y'); - Codec::decode(data.begin())(t2); - BOOST_CHECK(!t2.encoded); - BOOST_CHECK(t2.decoded); - BOOST_CHECK_EQUAL(t2.value, 'x'); -} - -QPID_AUTO_TEST_CASE(testControlEncodeDecode) { - string data; - Control::Holder h(in_place<connection::Tune>(1,2,3,4)); - Codec::encode(std::back_inserter(data))(h); - - BOOST_CHECK_EQUAL(data.size(), Codec::size(h)); - - Codec::Decoder<string::iterator> decode(data.begin()); - Control::Holder h2; - decode(h2); - - BOOST_REQUIRE(h2.get()); - BOOST_CHECK_EQUAL(h2.get()->getClassCode(), connection::CODE); - BOOST_CHECK_EQUAL(h2.get()->getCode(), uint8_t(connection::Tune::CODE)); - connection::Tune& tune=static_cast<connection::Tune&>(*h2.get()); - BOOST_CHECK_EQUAL(tune.channelMax, 1u); - BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u); - BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u); - BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u); -} - -QPID_AUTO_TEST_CASE(testStruct32) { - message::DeliveryProperties dp; - dp.priority=message::MEDIUM; - dp.routingKey="foo"; - Struct32 s(dp); - string data; - Codec::encode(back_inserter(data))(s); - - uint32_t structSize; // Starts with size - Codec::decode(data.begin())(structSize); - BOOST_CHECK_EQUAL(structSize, Codec::size(dp) + 2); // +2 for code - BOOST_CHECK_EQUAL(structSize, data.size()-4); // encoded body - - BOOST_CHECK_EQUAL(data.size(), Codec::size(s)); - Struct32 s2; - Codec::decode(data.begin())(s2); - message::DeliveryProperties* dp2 = s2.getIf<message::DeliveryProperties>(); - BOOST_REQUIRE(dp2); - BOOST_CHECK_EQUAL(dp2->priority, message::MEDIUM); - BOOST_CHECK_EQUAL(dp2->routingKey, "foo"); -} - -QPID_AUTO_TEST_CASE(testStruct32Unknown) { - // Verify we can recode an unknown struct unchanged. - Struct32 s; - string data; - Codec::encode(back_inserter(data))(uint32_t(10)); - data.append(10, 'X'); - Codec::decode(data.begin())(s); - string data2; - Codec::encode(back_inserter(data2))(s); - BOOST_CHECK_EQUAL(data.size(), data2.size()); - BOOST_CHECK_EQUAL(data, data2); -} - -struct DummyPacked { - static const uint8_t PACK=1; - boost::optional<char> i, j; - char k; - Bit l,m; - DummyPacked(char a=0, char b=0, char c=0) : i(a), j(b), k(c), l(), m() {} - template <class S> void serialize(S& s) { s(i)(j)(k)(l)(m); } -}; - -Packer<DummyPacked> serializable(DummyPacked& d) { return Packer<DummyPacked>(d); } - -QPID_AUTO_TEST_CASE(testPackBits) { - DummyPacked d('a','b','c'); - BOOST_CHECK_EQUAL(packBits(d), 7u); - d.j = boost::none; - BOOST_CHECK_EQUAL(packBits(d), 5u); - d.m = true; - BOOST_CHECK_EQUAL(packBits(d), 0x15u); -} - - -QPID_AUTO_TEST_CASE(testPacked) { - string data; - - Codec::encode(back_inserter(data))('a')(boost::optional<char>('b'))(boost::optional<char>())('c'); - BOOST_CHECK_EQUAL(data, "abc"); - data.clear(); - - DummyPacked dummy('a','b','c'); - - Codec::encode(back_inserter(data))(dummy); - BOOST_CHECK_EQUAL(data.size(), 4u); - BOOST_CHECK_EQUAL(data, string("\007abc")); - data.clear(); - - dummy.i = boost::none; - Codec::encode(back_inserter(data))(dummy); - BOOST_CHECK_EQUAL(data, string("\6bc")); - data.clear(); - - const char* missing = "\5xy"; - Codec::decode(missing)(dummy); - BOOST_CHECK(dummy.i); - BOOST_CHECK_EQUAL(*dummy.i, 'x'); - BOOST_CHECK(!dummy.j); - BOOST_CHECK_EQUAL(dummy.k, 'y'); -} - -QPID_AUTO_TEST_CASE(testUnitControl) { - string data; - Control::Holder h(in_place<connection::Tune>(1,2,3,4)); - Codec::encode(std::back_inserter(data))(h); - - Unit unit(FrameHeader(FIRST_FRAME|LAST_FRAME, CONTROL)); - Codec::decode(data.begin())(unit); - - BOOST_REQUIRE(unit.get<ControlHolder>()); - - string data2; - Codec::encode(back_inserter(data2))(unit); - - BOOST_CHECK_EQUAL(data, data2); -} - -QPID_AUTO_TEST_CASE(testArray) { - ArrayDomain<char> a; - a.resize(3, 'x'); - string data; - Codec::encode(back_inserter(data))(a); - - ArrayDomain<char> b; - Codec::decode(data.begin())(b); - BOOST_CHECK_EQUAL(b.size(), 3u); - string data3; - Codec::encode(back_inserter(data3))(a); - BOOST_CHECK_EQUAL(data, data3); - - Array x; - Codec::decode(data.begin())(x); - BOOST_CHECK_EQUAL(x.size(), 3u); - BOOST_CHECK_EQUAL(x[0].size(), 1u); - BOOST_CHECK_EQUAL(*x[0].begin(), 'x'); - BOOST_CHECK_EQUAL(*x[2].begin(), 'x'); - - string data2; - Codec::encode(back_inserter(data2))(x); - BOOST_CHECK_EQUAL(data,data2); -} - -QPID_AUTO_TEST_CASE(testStruct) { - string data; - - message::DeliveryProperties dp; - BOOST_CHECK(!dp.discardUnroutable); - dp.immediate = true; - dp.redelivered = false; - dp.priority = message::MEDIUM; - dp.exchange = "foo"; - - Codec::encode(back_inserter(data))(dp); - // Skip 4 bytes size, little-endian decode for pack bits. - uint16_t encodedBits=uint8_t(data[5]); - encodedBits <<= 8; - encodedBits += uint8_t(data[4]); - BOOST_CHECK_EQUAL(encodedBits, packBits(dp)); - - data.clear(); - Struct32 h(dp); - Codec::encode(back_inserter(data))(h); - - Struct32 h2; - Codec::decode(data.begin())(h2); - BOOST_CHECK_EQUAL(h2.getClassCode(), Uint8(message::DeliveryProperties::CLASS_CODE)); - BOOST_CHECK_EQUAL(h2.getCode(), Uint8(message::DeliveryProperties::CODE)); - message::DeliveryProperties* dp2 = - dynamic_cast<message::DeliveryProperties*>(h2.get()); - BOOST_CHECK(dp2); - BOOST_CHECK(!dp2->discardUnroutable); - BOOST_CHECK(dp2->immediate); - BOOST_CHECK(!dp2->redelivered); - BOOST_CHECK_EQUAL(dp2->priority, message::MEDIUM); - BOOST_CHECK_EQUAL(dp2->exchange, "foo"); -} - -struct RecodeUnit { - template <class T> - void operator() (const T& t) { - BOOST_MESSAGE(BOOST_CURRENT_FUNCTION << " called with: " << t); - using qpid::framing::Buffer; - using qpid::framing::AMQFrame; - - session::Header sh; - BOOST_CHECK_EQUAL(Codec::size(sh), 2u); - - // Encode unit. - Unit u(t); - string data; - Codec::encode(back_inserter(data))(u.getHeader())(u); - data.push_back(char(0xCE)); // Preview end-of-frame - - // Decode AMQFrame - Buffer buf(&data[0], data.size()); - AMQFrame f; - f.decode(buf); - BOOST_MESSAGE("AMQFrame decoded: " << f); - // Encode AMQFrame - string data2(f.size(), ' '); - Buffer buf2(&data2[0], data.size()); - f.encode(buf2); - - // Verify encoded by unit == encoded by AMQFrame - BOOST_CHECK_MESSAGE(data == data2, BOOST_CURRENT_FUNCTION); - - // Decode unit - // FIXME aconway 2008-04-15: must set limit to decode a header. - Codec::Decoder<string::iterator> decode(data2.begin(), data2.size()-1); - - FrameHeader h; - decode(h); - BOOST_CHECK_EQUAL(u.getHeader(), h); - Unit u2(h); - decode(u2); - - // Re-encode unit - string data3; - Codec::encode(back_inserter(data3))(u2.getHeader())(u2); - data3.push_back(char(0xCE)); // Preview end-of-frame - - BOOST_CHECK_MESSAGE(data3 == data2, BOOST_CURRENT_FUNCTION); - } -}; - -QPID_AUTO_TEST_CASE(testSerializeAllSegmentTypes) { - RecodeUnit recode; - allSegmentTypes(recode); -} - -QPID_AUTO_TEST_SUITE_END() diff --git a/cpp/src/tests/background.ps1 b/cpp/src/tests/background.ps1 deleted file mode 100644 index 36e9e4e6e9..0000000000 --- a/cpp/src/tests/background.ps1 +++ /dev/null @@ -1,55 +0,0 @@ -#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Run a PowerShell scriptblock in a background process.
-param(
- [scriptblock] $script # scriptblock to run
-)
-
-# break out of the script on any errors
-trap { break }
-
-# In order to pass a scriptblock to another powershell instance, it must
-# be encoded to pass through the command line.
-$encodedScript = [convert]::ToBase64String(
- [Text.Encoding]::Unicode.GetBytes([string] $script))
-
-#$p = new-object System.Diagnostics.Process
-$si = new-object System.Diagnostics.ProcessStartInfo
-$si.WorkingDirectory = $pwd
-$si.FileName = (get-command powershell.exe).Definition
-$si.Arguments = "-encodedCommand $encodedScript"
-
-###### debugging setup
-#$si.CreateNoWindow = $true
-# UseShellExecute false required for RedirectStandard(Error, Output)
-#$si.UseShellExecute = $false
-#$si.RedirectStandardError = $true
-#$si.RedirectStandardOutput = $true
-######
-$si.UseShellExecute = $true
-
-##### Debugging, instead of the plain Start() above.
-#$output = [io.File]::AppendText("start.out")
-#$error = [io.File]::AppendText("start.err")
-$p = [System.Diagnostics.Process]::Start($si)
-#$output.WriteLine($p.StandardOutput.ReadToEnd())
-#$error.WriteLine($p.StandardError.ReadToEnd())
-#$p.WaitForExit()
-#$output.Close()
diff --git a/cpp/src/tests/benchmark b/cpp/src/tests/benchmark deleted file mode 100755 index c075837847..0000000000 --- a/cpp/src/tests/benchmark +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# A basic "benchmark" to generate performacne samples of throughput -# and latency against a single cluster member while they are replicating. -# -# Must be run in the qpid src/tests build directory. -# - -usage() { -cat <<EOF -Usage: $0 [options] -- client hosts --- broker hosts -Read the script for options. -EOF -} -# Defaults -TESTDIR=${TESTDIR:-$PWD} # Absolute path to test exes on all hosts. -SCRIPTDIR=${SCRIPTDIR:-`dirname $0`} # Path to local test scripts directory. -SAMPLES=10 # Runs of each test. -COUNT=${COUNT:-10000} # Count for pub/sub tests. -SIZE=${SIZE:-600} # Size of messages -ECHO=${ECHO:-1000} # Count for echo test. -NSUBS=${NSUBS:-4} -NPUBS=${NPUBS:-4} - -collect() { eval $COLLECT=\""\$$COLLECT $*"\"; } -COLLECT=ARGS -while test $# -gt 0; do - case $1 in - --testdir) TESTDIR=$2 ; shift 2 ;; - --samples) SAMPLES=$2 ; shift 2 ;; - --count) COUNT=$2 ; shift 2 ;; - --echos) ECHO=$2 ; shift 2 ;; - --size) SIZE=$2 ; shift 2 ;; - --nsubs) NSUBS=$2 ; shift 2 ;; - --npubs) NPUBS=$2 ; shift 2 ;; - --) COLLECT=CLIENTARG; shift ;; - ---) COLLECT=BROKERARG; shift;; - *) collect $1; shift ;; - esac -done - -CLIENTS=${CLIENTARG:-$CLIENTS} -BROKERS=${BROKERARG:-$BROKERS} -test -z "$CLIENTS" && { echo "Must specify at least one client host."; exit 1; } -test -z "$BROKERS" && { echo "Must specify at least one broker host."; exit 1; } - -export TESTDIR # For perfdist -CLIENTS=($CLIENTS) # Convert to array -BROKERS=($BROKERS) -trap "rm -f $FILES" EXIT - -dosamples() { - FILE=`mktemp` - FILES="$FILES $FILE" - TABS=`echo "$HEADING" | sed s'/[^ ]//g'` - { - echo "\"$*\"$TABS" - echo "$HEADING" - for (( i=0; i<$SAMPLES; ++i)) ; do echo "`$*`" ; done - echo - } | tee $FILE -} - -HEADING="pub sub total Mb" -dosamples $SCRIPTDIR/perfdist --size $SIZE --count $COUNT --nsubs $NSUBS --npubs $NPUBS -s -- ${CLIENTS[*]} --- ${BROKERS[*]} -HEADING="pub" -dosamples ssh -A ${CLIENTS[0]} $TESTDIR/publish --routing-key perftest0 --size $SIZE --count $COUNT -s -b ${BROKERS[0]} -HEADING="sub" -dosamples ssh -A ${CLIENTS[0]} $TESTDIR/consume --queue perftest0 -s --count $COUNT -b ${BROKERS[0]} -HEADING="min max avg" -dosamples ssh -A ${CLIENTS[0]} $TESTDIR/echotest --count $ECHO -s -b ${BROKERS[0]} - -echo -echo "Tab separated spreadsheet (also saved as benchmark.tab):" -echo - -echo "benchmark -- ${CLIENTS[*]} --- ${BROKERS[*]} " | tee benchmark.tab -paste $FILES | tee -a benchmark.tab diff --git a/cpp/src/tests/brokermgmt.mk b/cpp/src/tests/brokermgmt.mk deleted file mode 100644 index cf9a47200c..0000000000 --- a/cpp/src/tests/brokermgmt.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Build a unit test for the broker's internal management agent. - -BROKERMGMT_GEN_SRC= \ - brokermgmt_gen/qmf/org/apache/qpid/broker/mgmt/test/Package.cpp \ - brokermgmt_gen/qmf/org/apache/qpid/broker/mgmt/test/Package.h \ - brokermgmt_gen/qmf/org/apache/qpid/broker/mgmt/test/TestObject.h \ - brokermgmt_gen/qmf/org/apache/qpid/broker/mgmt/test/TestObject.cpp - -$(BROKERMGMT_GEN_SRC): brokermgmt_gen.timestamp - -if GENERATE -BROKERMGMT_DEPS=../mgen.timestamp -endif # GENERATE -brokermgmt_gen.timestamp: BrokerMgmtAgent.xml ${BROKERMGMT_DEPS} - $(QMF_GEN) -b -o brokermgmt_gen/qmf $(srcdir)/BrokerMgmtAgent.xml - touch $@ - -BrokerMgmtAgent.$(OBJEXT): $(BROKERMGMT_GEN_SRC) - -CLEANFILES+=$(BROKERMGMT_GEN_SRC) brokermgmt_gen.timestamp - -unit_test_SOURCES+=BrokerMgmtAgent.cpp ${BROKERMGMT_GEN_SRC} -INCLUDES+= -Ibrokermgmt_gen - -EXTRA_DIST+=BrokerMgmtAgent.xml diff --git a/cpp/src/tests/brokertest.py b/cpp/src/tests/brokertest.py deleted file mode 100644 index a19dd305e5..0000000000 --- a/cpp/src/tests/brokertest.py +++ /dev/null @@ -1,671 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Support library for tests that start multiple brokers, e.g. cluster -# or federation - -import os, signal, string, tempfile, subprocess, socket, threading, time, imp, re -import qpid, traceback, signal -from qpid import connection, messaging, util -from qpid.compat import format_exc -from qpid.harness import Skipped -from unittest import TestCase -from copy import copy -from threading import Thread, Lock, Condition -from logging import getLogger -import qmf.console - -log = getLogger("qpid.brokertest") - -# Values for expected outcome of process at end of test -EXPECT_EXIT_OK=1 # Expect to exit with 0 status before end of test. -EXPECT_EXIT_FAIL=2 # Expect to exit with non-0 status before end of test. -EXPECT_RUNNING=3 # Expect to still be running at end of test -EXPECT_UNKNOWN=4 # No expectation, don't check exit status. - -def find_exe(program): - """Find an executable in the system PATH""" - def is_exe(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - mydir, name = os.path.split(program) - if mydir: - if is_exe(program): return program - else: - for path in os.environ["PATH"].split(os.pathsep): - exe_file = os.path.join(path, program) - if is_exe(exe_file): return exe_file - return None - -def is_running(pid): - try: - os.kill(pid, 0) - return True - except: - return False - -class BadProcessStatus(Exception): - pass - -def error_line(filename, n=1): - """Get the last n line(s) of filename for error messages""" - result = [] - try: - f = open(filename) - try: - for l in f: - if len(result) == n: result.pop(0) - result.append(" "+l) - finally: - f.close() - except: return "" - return ":\n" + "".join(result) - -def retry(function, timeout=10, delay=.01): - """Call function until it returns True or timeout expires. - Double the delay for each retry. Return True if function - returns true, False if timeout expires.""" - deadline = time.time() + timeout - while not function(): - remaining = deadline - time.time() - if remaining <= 0: return False - delay = min(delay, remaining) - time.sleep(delay) - delay *= 2 - return True - -class AtomicCounter: - def __init__(self): - self.count = 0 - self.lock = Lock() - - def next(self): - self.lock.acquire(); - ret = self.count - self.count += 1 - self.lock.release(); - return ret - -_popen_id = AtomicCounter() # Popen identifier for use in output file names. - -# Constants for file descriptor arguments to Popen -FILE = "FILE" # Write to file named after process -PIPE = subprocess.PIPE - -class Popen(subprocess.Popen): - """ - Can set and verify expectation of process status at end of test. - Dumps command line, stdout, stderr to data dir for debugging. - """ - - def __init__(self, cmd, expect=EXPECT_EXIT_OK, stdin=None, stdout=FILE, stderr=FILE): - """Run cmd (should be a list of program and arguments) - expect - if set verify expectation at end of test. - stdout, stderr - can have the same values as for subprocess.Popen as well as - FILE (the default) which means write to a file named after the process. - stdin - like subprocess.Popen but defauts to PIPE - """ - self._clean = False - self._clean_lock = Lock() - assert find_exe(cmd[0]), "executable not found: "+cmd[0] - if type(cmd) is type(""): cmd = [cmd] # Make it a list. - self.cmd = [ str(x) for x in cmd ] - self.expect = expect - self.id = _popen_id.next() - self.pname = "%s-%d" % (os.path.split(self.cmd[0])[1], self.id) - if stdout == FILE: stdout = open(self.outfile("out"), "w") - if stderr == FILE: stderr = open(self.outfile("err"), "w") - try: - subprocess.Popen.__init__(self, self.cmd, bufsize=0, executable=None, - stdin=stdin, stdout=stdout, stderr=stderr, - close_fds=True) - except ValueError: # Windows can't do close_fds - subprocess.Popen.__init__(self, self.cmd, bufsize=0, executable=None, - stdin=stdin, stdout=stdout, stderr=stderr) - - f = open(self.outfile("cmd"), "w") - try: f.write("%s\n%d"%(self.cmd_str(), self.pid)) - finally: f.close() - log.debug("Started process %s: %s" % (self.pname, " ".join(self.cmd))) - - def __str__(self): return "Popen<%s>"%(self.pname) - - def outfile(self, ext): return "%s.%s" % (self.pname, ext) - - def unexpected(self,msg): - err = error_line(self.outfile("err")) or error_line(self.outfile("out")) - raise BadProcessStatus("%s %s%s" % (self.pname, msg, err)) - - def stop(self): # Clean up at end of test. - try: - if self.expect == EXPECT_UNKNOWN: - try: self.kill() # Just make sure its dead - except: pass - elif self.expect == EXPECT_RUNNING: - try: self.kill() - except: self.unexpected("expected running, exit code %d" % self.wait()) - else: - retry(lambda: self.poll() is not None) - if self.returncode is None: # Still haven't stopped - self.kill() - self.unexpected("still running") - elif self.expect == EXPECT_EXIT_OK and self.returncode != 0: - self.unexpected("exit code %d" % self.returncode) - elif self.expect == EXPECT_EXIT_FAIL and self.returncode == 0: - self.unexpected("expected error") - finally: - self.wait() # Clean up the process. - - def communicate(self, input=None): - ret = subprocess.Popen.communicate(self, input) - self.cleanup() - return ret - - def is_running(self): return self.poll() is None - - def assert_running(self): - if not self.is_running(): self.unexpected("Exit code %d" % self.returncode) - - def wait(self): - ret = subprocess.Popen.wait(self) - self._cleanup() - return ret - - def terminate(self): - try: subprocess.Popen.terminate(self) - except AttributeError: # No terminate method - try: - os.kill( self.pid , signal.SIGTERM) - except AttributeError: # no os.kill, using taskkill.. (Windows only) - os.popen('TASKKILL /PID ' +str(self.pid) + ' /F') - self._cleanup() - - def kill(self): - try: subprocess.Popen.kill(self) - except AttributeError: # No terminate method - try: - os.kill( self.pid , signal.SIGKILL) - except AttributeError: # no os.kill, using taskkill.. (Windows only) - os.popen('TASKKILL /PID ' +str(self.pid) + ' /F') - self._cleanup() - - def _cleanup(self): - """Clean up after a dead process""" - self._clean_lock.acquire() - if not self._clean: - self._clean = True - try: self.stdin.close() - except: pass - try: self.stdout.close() - except: pass - try: self.stderr.close() - except: pass - self._clean_lock.release() - - def cmd_str(self): return " ".join([str(s) for s in self.cmd]) - -def checkenv(name): - value = os.getenv(name) - if not value: raise Exception("Environment variable %s is not set" % name) - return value - -def find_in_file(str, filename): - if not os.path.exists(filename): return False - f = open(filename) - try: return str in f.read() - finally: f.close() - -class Broker(Popen): - "A broker process. Takes care of start, stop and logging." - _broker_count = 0 - - def __str__(self): return "Broker<%s %s>"%(self.name, self.pname) - - def find_log(self): - self.log = "%s.log" % self.name - i = 1 - while (os.path.exists(self.log)): - self.log = "%s-%d.log" % (self.name, i) - i += 1 - - def get_log(self): - return os.path.abspath(self.log) - - def __init__(self, test, args=[], name=None, expect=EXPECT_RUNNING, port=0, log_level=None, wait=None): - """Start a broker daemon. name determines the data-dir and log - file names.""" - - self.test = test - self._port=port - if BrokerTest.store_lib: - args = args + ['--load-module', BrokerTest.store_lib] - if BrokerTest.sql_store_lib: - args = args + ['--load-module', BrokerTest.sql_store_lib] - args = args + ['--catalog', BrokerTest.sql_catalog] - if BrokerTest.sql_clfs_store_lib: - args = args + ['--load-module', BrokerTest.sql_clfs_store_lib] - args = args + ['--catalog', BrokerTest.sql_catalog] - cmd = [BrokerTest.qpidd_exec, "--port", port, "--no-module-dir"] + args - if not "--auth" in args: cmd.append("--auth=no") - if wait != None: - cmd += ["--wait", str(wait)] - if name: self.name = name - else: - self.name = "broker%d" % Broker._broker_count - Broker._broker_count += 1 - self.find_log() - cmd += ["--log-to-file", self.log] - cmd += ["--log-to-stderr=no"] - if log_level != None: - cmd += ["--log-enable=%s" % log_level] - self.datadir = self.name - cmd += ["--data-dir", self.datadir] - Popen.__init__(self, cmd, expect, stdout=PIPE) - test.cleanup_stop(self) - self._host = "127.0.0.1" - log.debug("Started broker %s (%s, %s)" % (self.name, self.pname, self.log)) - self._log_ready = False - - def startQmf(self, handler=None): - self.qmf_session = qmf.console.Session(handler) - self.qmf_broker = self.qmf_session.addBroker("%s:%s" % (self.host(), self.port())) - - def host(self): return self._host - - def port(self): - # Read port from broker process stdout if not already read. - if (self._port == 0): - try: self._port = int(self.stdout.readline()) - except ValueError: - raise Exception("Can't get port for broker %s (%s)%s" % - (self.name, self.pname, error_line(self.log,5))) - return self._port - - def unexpected(self,msg): - raise BadProcessStatus("%s: %s (%s)" % (msg, self.name, self.pname)) - - def connect(self, **kwargs): - """New API connection to the broker.""" - return messaging.Connection.establish(self.host_port(), **kwargs) - - def connect_old(self): - """Old API connection to the broker.""" - socket = qpid.util.connect(self.host(),self.port()) - connection = qpid.connection.Connection (sock=socket) - connection.start() - return connection; - - def declare_queue(self, queue): - c = self.connect_old() - s = c.session(str(qpid.datatypes.uuid4())) - s.queue_declare(queue=queue) - c.close() - - def _prep_sender(self, queue, durable, xprops): - s = queue + "; {create:always, node:{durable:" + str(durable) - if xprops != None: s += ", x-declare:{" + xprops + "}" - return s + "}}" - - def send_message(self, queue, message, durable=True, xprops=None, session=None): - if session == None: - s = self.connect().session() - else: - s = session - s.sender(self._prep_sender(queue, durable, xprops)).send(message) - if session == None: - s.connection.close() - - def send_messages(self, queue, messages, durable=True, xprops=None, session=None): - if session == None: - s = self.connect().session() - else: - s = session - sender = s.sender(self._prep_sender(queue, durable, xprops)) - for m in messages: sender.send(m) - if session == None: - s.connection.close() - - def get_message(self, queue): - s = self.connect().session() - m = s.receiver(queue+"; {create:always}", capacity=1).fetch(timeout=1) - s.acknowledge() - s.connection.close() - return m - - def get_messages(self, queue, n): - s = self.connect().session() - receiver = s.receiver(queue+"; {create:always}", capacity=n) - m = [receiver.fetch(timeout=1) for i in range(n)] - s.acknowledge() - s.connection.close() - return m - - def host_port(self): return "%s:%s" % (self.host(), self.port()) - - def log_ready(self): - """Return true if the log file exists and contains a broker ready message""" - if not self._log_ready: - self._log_ready = find_in_file("notice Broker running", self.log) - return self._log_ready - - def ready(self, **kwargs): - """Wait till broker is ready to serve clients""" - # First make sure the broker is listening by checking the log. - if not retry(self.log_ready, timeout=60): - raise Exception( - "Timed out waiting for broker %s%s"%(self.name, error_line(self.log,5))) - # Create a connection and a session. For a cluster broker this will - # return after cluster init has finished. - try: - c = self.connect(**kwargs) - try: c.session() - finally: c.close() - except Exception,e: raise RethrownException( - "Broker %s not responding: (%s)%s"%(self.name,e,error_line(self.log, 5))) - - def store_state(self): - f = open(os.path.join(self.datadir, "cluster", "store.status")) - try: uuids = f.readlines() - finally: f.close() - null_uuid="00000000-0000-0000-0000-000000000000\n" - if len(uuids) < 2: return "unknown" # we looked while the file was being updated. - if uuids[0] == null_uuid: return "empty" - if uuids[1] == null_uuid: return "dirty" - return "clean" - -class Cluster: - """A cluster of brokers in a test.""" - - _cluster_count = 0 - - def __init__(self, test, count=0, args=[], expect=EXPECT_RUNNING, wait=True): - self.test = test - self._brokers=[] - self.name = "cluster%d" % Cluster._cluster_count - Cluster._cluster_count += 1 - # Use unique cluster name - self.args = copy(args) - self.args += [ "--cluster-name", "%s-%s:%d" % (self.name, socket.gethostname(), os.getpid()) ] - self.args += [ "--log-enable=info+", "--log-enable=debug+:cluster"] - assert BrokerTest.cluster_lib, "Cannot locate cluster plug-in" - self.args += [ "--load-module", BrokerTest.cluster_lib ] - self.start_n(count, expect=expect, wait=wait) - - def start(self, name=None, expect=EXPECT_RUNNING, wait=True, args=[], port=0): - """Add a broker to the cluster. Returns the index of the new broker.""" - if not name: name="%s-%d" % (self.name, len(self._brokers)) - self._brokers.append(self.test.broker(self.args+args, name, expect, wait, port=port)) - return self._brokers[-1] - - def start_n(self, count, expect=EXPECT_RUNNING, wait=True, args=[]): - for i in range(count): self.start(expect=expect, wait=wait, args=args) - - # Behave like a list of brokers. - def __len__(self): return len(self._brokers) - def __getitem__(self,index): return self._brokers[index] - def __iter__(self): return self._brokers.__iter__() - -class BrokerTest(TestCase): - """ - Tracks processes started by test and kills at end of test. - Provides a well-known working directory for each test. - """ - - # Environment settings. - qpidd_exec = os.path.abspath(checkenv("QPIDD_EXEC")) - cluster_lib = os.getenv("CLUSTER_LIB") - xml_lib = os.getenv("XML_LIB") - qpid_config_exec = os.getenv("QPID_CONFIG_EXEC") - qpid_route_exec = os.getenv("QPID_ROUTE_EXEC") - receiver_exec = os.getenv("RECEIVER_EXEC") - sender_exec = os.getenv("SENDER_EXEC") - sql_store_lib = os.getenv("STORE_SQL_LIB") - sql_clfs_store_lib = os.getenv("STORE_SQL_CLFS_LIB") - sql_catalog = os.getenv("STORE_CATALOG") - store_lib = os.getenv("STORE_LIB") - test_store_lib = os.getenv("TEST_STORE_LIB") - rootdir = os.getcwd() - - def configure(self, config): self.config=config - - def setUp(self): - outdir = self.config.defines.get("OUTDIR") or "brokertest.tmp" - self.dir = os.path.join(self.rootdir, outdir, self.id()) - os.makedirs(self.dir) - os.chdir(self.dir) - self.stopem = [] # things to stop at end of test - - def tearDown(self): - err = [] - for p in self.stopem: - try: p.stop() - except Exception, e: err.append(str(e)) - self.stopem = [] # reset in case more processes start - os.chdir(self.rootdir) - if err: raise Exception("Unexpected process status:\n "+"\n ".join(err)) - - def cleanup_stop(self, stopable): - """Call thing.stop at end of test""" - self.stopem.append(stopable) - - def popen(self, cmd, expect=EXPECT_EXIT_OK, stdin=None, stdout=FILE, stderr=FILE): - """Start a process that will be killed at end of test, in the test dir.""" - os.chdir(self.dir) - p = Popen(cmd, expect, stdin=stdin, stdout=stdout, stderr=stderr) - self.cleanup_stop(p) - return p - - def broker(self, args=[], name=None, expect=EXPECT_RUNNING, wait=True, port=0, log_level=None): - """Create and return a broker ready for use""" - b = Broker(self, args=args, name=name, expect=expect, port=port, log_level=log_level) - if (wait): - try: b.ready() - except Exception, e: - raise RethrownException("Failed to start broker %s(%s): %s" % (b.name, b.log, e)) - return b - - def cluster(self, count=0, args=[], expect=EXPECT_RUNNING, wait=True): - """Create and return a cluster ready for use""" - cluster = Cluster(self, count, args, expect=expect, wait=wait) - return cluster - - def browse(self, session, queue, timeout=0): - """Assert that the contents of messages on queue (as retrieved - using session and timeout) exactly match the strings in - expect_contents""" - r = session.receiver("%s;{mode:browse}"%(queue)) - try: - contents = [] - try: - while True: contents.append(r.fetch(timeout=timeout).content) - except messaging.Empty: pass - finally: pass #FIXME aconway 2011-04-14: r.close() - return contents - - def assert_browse(self, session, queue, expect_contents, timeout=0): - """Assert that the contents of messages on queue (as retrieved - using session and timeout) exactly match the strings in - expect_contents""" - actual_contents = self.browse(session, queue, timeout) - self.assertEqual(expect_contents, actual_contents) - -def join(thread, timeout=10): - thread.join(timeout) - if thread.isAlive(): raise Exception("Timed out joining thread %s"%thread) - -class RethrownException(Exception): - """Captures the stack trace of the current exception to be thrown later""" - def __init__(self, msg=""): - Exception.__init__(self, msg+"\n"+format_exc()) - -class StoppableThread(Thread): - """ - Base class for threads that do something in a loop and periodically check - to see if they have been stopped. - """ - def __init__(self): - self.stopped = False - self.error = None - Thread.__init__(self) - - def stop(self): - self.stopped = True - join(self) - if self.error: raise self.error - -class NumberedSender(Thread): - """ - Thread to run a sender client and send numbered messages until stopped. - """ - - def __init__(self, broker, max_depth=None, queue="test-queue"): - """ - max_depth: enable flow control, ensure sent - received <= max_depth. - Requires self.notify_received(n) to be called each time messages are received. - """ - Thread.__init__(self) - self.sender = broker.test.popen( - ["qpid-send", - "--broker", "localhost:%s"%broker.port(), - "--address", "%s;{create:always}"%queue, - "--failover-updates", - "--content-stdin" - ], - expect=EXPECT_RUNNING, - stdin=PIPE) - self.condition = Condition() - self.max = max_depth - self.received = 0 - self.stopped = False - self.error = None - - def write_message(self, n): - self.sender.stdin.write(str(n)+"\n") - self.sender.stdin.flush() - - def run(self): - try: - self.sent = 0 - while not self.stopped: - if self.max: - self.condition.acquire() - while not self.stopped and self.sent - self.received > self.max: - self.condition.wait() - self.condition.release() - self.write_message(self.sent) - self.sent += 1 - except Exception: self.error = RethrownException(self.sender.pname) - - def notify_received(self, count): - """Called by receiver to enable flow control. count = messages received so far.""" - self.condition.acquire() - self.received = count - self.condition.notify() - self.condition.release() - - def stop(self): - self.condition.acquire() - try: - self.stopped = True - self.condition.notify() - finally: self.condition.release() - join(self) - self.write_message(-1) # end-of-messages marker. - if self.error: raise self.error - -class NumberedReceiver(Thread): - """ - Thread to run a receiver client and verify it receives - sequentially numbered messages. - """ - def __init__(self, broker, sender = None, queue="test-queue"): - """ - sender: enable flow control. Call sender.received(n) for each message received. - """ - Thread.__init__(self) - self.test = broker.test - self.receiver = self.test.popen( - ["qpid-receive", - "--broker", "localhost:%s"%broker.port(), - "--address", "%s;{create:always}"%queue, - "--failover-updates", - "--forever" - ], - expect=EXPECT_RUNNING, - stdout=PIPE) - self.lock = Lock() - self.error = None - self.sender = sender - - def read_message(self): - return int(self.receiver.stdout.readline()) - - def run(self): - try: - self.received = 0 - m = self.read_message() - while m != -1: - assert(m <= self.received) # Check for missing messages - if (m == self.received): # Ignore duplicates - self.received += 1 - if self.sender: - self.sender.notify_received(self.received) - m = self.read_message() - except Exception: - self.error = RethrownException(self.receiver.pname) - - def stop(self): - """Returns when termination message is received""" - join(self) - if self.error: raise self.error - -class ErrorGenerator(StoppableThread): - """ - Thread that continuously generates errors by trying to consume from - a non-existent queue. For cluster regression tests, error handling - caused issues in the past. - """ - - def __init__(self, broker): - StoppableThread.__init__(self) - self.broker=broker - broker.test.cleanup_stop(self) - self.start() - - def run(self): - c = self.broker.connect_old() - try: - while not self.stopped: - try: - c.session(str(qpid.datatypes.uuid4())).message_subscribe( - queue="non-existent-queue") - assert(False) - except qpid.session.SessionException: pass - time.sleep(0.01) - except: pass # Normal if broker is killed. - -def import_script(path): - """ - Import executable script at path as a module. - Requires some trickery as scripts are not in standard module format - """ - f = open(path) - try: - name=os.path.split(path)[1].replace("-","_") - return imp.load_module(name, f, path, ("", "r", imp.PY_SOURCE)) - finally: f.close() diff --git a/cpp/src/tests/cli_tests.py b/cpp/src/tests/cli_tests.py deleted file mode 100755 index 6c75927461..0000000000 --- a/cpp/src/tests/cli_tests.py +++ /dev/null @@ -1,475 +0,0 @@ -#!/usr/bin/env python -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import sys -import os -import imp -from qpid.testlib import TestBase010 -# from brokertest import import_script, checkenv -from qpid.datatypes import Message -from qpid.queue import Empty -from time import sleep - -def import_script(path): - """ - Import executable script at path as a module. - Requires some trickery as scripts are not in standard module format - """ - f = open(path) - try: - name=os.path.split(path)[1].replace("-","_") - return imp.load_module(name, f, path, ("", "r", imp.PY_SOURCE)) - finally: f.close() - -def checkenv(name): - value = os.getenv(name) - if not value: raise Exception("Environment variable %s is not set" % name) - return value - -class CliTests(TestBase010): - - def remote_host(self): - return self.defines.get("remote-host", "localhost") - - def remote_port(self): - return int(self.defines["remote-port"]) - - def cli_dir(self): - return self.defines["cli-dir"] - - def makeQueue(self, qname, arguments, api=False): - if api: - ret = self.qpid_config_api(" add queue " + qname + " " + arguments) - else: - ret = os.system(self.qpid_config_command(" add queue " + qname + " " + arguments)) - - self.assertEqual(ret, 0) - queues = self.qmf.getObjects(_class="queue") - for queue in queues: - if queue.name == qname: - return queue - assert False - - def test_queue_params(self): - self.startQmf() - queue1 = self.makeQueue("test_queue_params1", "--limit-policy none") - queue2 = self.makeQueue("test_queue_params2", "--limit-policy reject") - queue3 = self.makeQueue("test_queue_params3", "--limit-policy flow-to-disk") - queue4 = self.makeQueue("test_queue_params4", "--limit-policy ring") - queue5 = self.makeQueue("test_queue_params5", "--limit-policy ring-strict") - - LIMIT = "qpid.policy_type" - assert LIMIT not in queue1.arguments - self.assertEqual(queue2.arguments[LIMIT], "reject") - self.assertEqual(queue3.arguments[LIMIT], "flow_to_disk") - self.assertEqual(queue4.arguments[LIMIT], "ring") - self.assertEqual(queue5.arguments[LIMIT], "ring_strict") - - queue6 = self.makeQueue("test_queue_params6", "--order fifo") - queue7 = self.makeQueue("test_queue_params7", "--order lvq") - queue8 = self.makeQueue("test_queue_params8", "--order lvq-no-browse") - - LVQ = "qpid.last_value_queue" - LVQNB = "qpid.last_value_queue_no_browse" - - assert LVQ not in queue6.arguments - assert LVQ in queue7.arguments - assert LVQ not in queue8.arguments - - assert LVQNB not in queue6.arguments - assert LVQNB not in queue7.arguments - assert LVQNB in queue8.arguments - - - def test_queue_params_api(self): - self.startQmf() - queue1 = self.makeQueue("test_queue_params1", "--limit-policy none", True) - queue2 = self.makeQueue("test_queue_params2", "--limit-policy reject", True) - queue3 = self.makeQueue("test_queue_params3", "--limit-policy flow-to-disk", True) - queue4 = self.makeQueue("test_queue_params4", "--limit-policy ring", True) - queue5 = self.makeQueue("test_queue_params5", "--limit-policy ring-strict", True) - - LIMIT = "qpid.policy_type" - assert LIMIT not in queue1.arguments - self.assertEqual(queue2.arguments[LIMIT], "reject") - self.assertEqual(queue3.arguments[LIMIT], "flow_to_disk") - self.assertEqual(queue4.arguments[LIMIT], "ring") - self.assertEqual(queue5.arguments[LIMIT], "ring_strict") - - queue6 = self.makeQueue("test_queue_params6", "--order fifo", True) - queue7 = self.makeQueue("test_queue_params7", "--order lvq", True) - queue8 = self.makeQueue("test_queue_params8", "--order lvq-no-browse", True) - - LVQ = "qpid.last_value_queue" - LVQNB = "qpid.last_value_queue_no_browse" - - assert LVQ not in queue6.arguments - assert LVQ in queue7.arguments - assert LVQ not in queue8.arguments - - assert LVQNB not in queue6.arguments - assert LVQNB not in queue7.arguments - assert LVQNB in queue8.arguments - - - def test_qpid_config(self): - self.startQmf(); - qmf = self.qmf - qname = "test_qpid_config" - - ret = os.system(self.qpid_config_command(" add queue " + qname)) - self.assertEqual(ret, 0) - queues = qmf.getObjects(_class="queue") - found = False - for queue in queues: - if queue.name == qname: - self.assertEqual(queue.durable, False) - found = True - self.assertEqual(found, True) - - ret = os.system(self.qpid_config_command(" del queue " + qname)) - self.assertEqual(ret, 0) - queues = qmf.getObjects(_class="queue") - found = False - for queue in queues: - if queue.name == qname: - found = True - self.assertEqual(found, False) - - def test_qpid_config_api(self): - self.startQmf(); - qmf = self.qmf - qname = "test_qpid_config_api" - - ret = self.qpid_config_api(" add queue " + qname) - self.assertEqual(ret, 0) - queues = qmf.getObjects(_class="queue") - found = False - for queue in queues: - if queue.name == qname: - self.assertEqual(queue.durable, False) - found = True - self.assertEqual(found, True) - - ret = self.qpid_config_api(" del queue " + qname) - self.assertEqual(ret, 0) - queues = qmf.getObjects(_class="queue") - found = False - for queue in queues: - if queue.name == qname: - found = True - self.assertEqual(found, False) - - - def test_qpid_config_sasl_plain_expect_succeed(self): - self.startQmf(); - qmf = self.qmf - qname = "test_qpid_config_sasl_plain_expect_succeed" - cmd = " --sasl-mechanism PLAIN -a guest/guest@localhost:"+str(self.broker.port) + " add queue " + qname - ret = self.qpid_config_api(cmd) - self.assertEqual(ret, 0) - - def test_qpid_config_sasl_plain_expect_fail(self): - """Fails because no user name and password is supplied""" - self.startQmf(); - qmf = self.qmf - qname = "test_qpid_config_sasl_plain_expect_succeed" - cmd = " --sasl-mechanism PLAIN -a localhost:"+str(self.broker.port) + " add queue " + qname - ret = self.qpid_config_api(cmd) - assert ret != 0 - - # helpers for some of the test methods - def helper_find_exchange(self, xchgname, typ, expected=True): - xchgs = self.qmf.getObjects(_class = "exchange") - found = False - for xchg in xchgs: - if xchg.name == xchgname: - if typ: - self.assertEqual(xchg.type, typ) - found = True - self.assertEqual(found, expected) - - def helper_create_exchange(self, xchgname, typ="direct", opts=""): - foo = self.qpid_config_command(opts + " add exchange " + typ + " " + xchgname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - self.helper_find_exchange(xchgname, typ, True) - - def helper_destroy_exchange(self, xchgname): - foo = self.qpid_config_command(" del exchange " + xchgname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - self.helper_find_exchange(xchgname, False, expected=False) - - def helper_find_queue(self, qname, expected=True): - queues = self.qmf.getObjects(_class="queue") - found = False - for queue in queues: - if queue.name == qname: - self.assertEqual(queue.durable, False) - found = True - self.assertEqual(found, expected) - - def helper_create_queue(self, qname): - foo = self.qpid_config_command(" add queue " + qname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - self.helper_find_queue(qname, True) - - def helper_destroy_queue(self, qname): - foo = self.qpid_config_command(" del queue " + qname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - self.helper_find_queue(qname, False) - - - # test the bind-queue-to-header-exchange functionality - def test_qpid_config_headers(self): - self.startQmf(); - qmf = self.qmf - qname = "test_qpid_config" - xchgname = "test_xchg" - - # first create a header xchg - self.helper_create_exchange(xchgname, typ="headers") - - # create the queue - self.helper_create_queue(qname) - - # now bind the queue to the xchg - foo = self.qpid_config_command(" bind " + xchgname + " " + qname + - " key all foo=bar baz=quux") - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - - # he likes it, mikey. Ok, now tear it all down. first the binding - ret = os.system(self.qpid_config_command(" unbind " + xchgname + " " + qname + - " key")) - self.assertEqual(ret, 0) - - # then the queue - self.helper_destroy_queue(qname) - - # then the exchange - self.helper_destroy_exchange(xchgname) - - - def test_qpid_config_xml(self): - self.startQmf(); - qmf = self.qmf - qname = "test_qpid_config" - xchgname = "test_xchg" - - # first create a header xchg - self.helper_create_exchange(xchgname, typ="xml") - - # create the queue - self.helper_create_queue(qname) - - # now bind the queue to the xchg - foo = self.qpid_config_command("-f test.xquery bind " + xchgname + " " + qname) - # print foo - ret = os.system(foo) - self.assertEqual(ret, 0) - - # he likes it, mikey. Ok, now tear it all down. first the binding - ret = os.system(self.qpid_config_command(" unbind " + xchgname + " " + qname + - " key")) - self.assertEqual(ret, 0) - - # then the queue - self.helper_destroy_queue(qname) - - # then the exchange - self.helper_destroy_exchange(xchgname) - - def test_qpid_config_durable(self): - self.startQmf(); - qmf = self.qmf - qname = "test_qpid_config" - - ret = os.system(self.qpid_config_command(" add queue --durable " + qname)) - self.assertEqual(ret, 0) - queues = qmf.getObjects(_class="queue") - found = False - for queue in queues: - if queue.name == qname: - self.assertEqual(queue.durable, True) - found = True - self.assertEqual(found, True) - - ret = os.system(self.qpid_config_command(" del queue " + qname)) - self.assertEqual(ret, 0) - queues = qmf.getObjects(_class="queue") - found = False - for queue in queues: - if queue.name == qname: - found = True - self.assertEqual(found, False) - - def test_qpid_config_altex(self): - self.startQmf(); - qmf = self.qmf - exName = "testalt" - qName = "testqalt" - altName = "amq.direct" - - ret = os.system(self.qpid_config_command(" add exchange topic %s --alternate-exchange=%s" % (exName, altName))) - self.assertEqual(ret, 0) - - exchanges = qmf.getObjects(_class="exchange") - found = False - for exchange in exchanges: - if exchange.name == altName: - self.assertEqual(exchange.altExchange, None) - - if exchange.name == exName: - found = True - if not exchange.altExchange: - self.fail("Alternate exchange not set") - self.assertEqual(exchange._altExchange_.name, altName) - self.assertEqual(found, True) - - ret = os.system(self.qpid_config_command(" add queue %s --alternate-exchange=%s" % (qName, altName))) - self.assertEqual(ret, 0) - - queues = qmf.getObjects(_class="queue") - found = False - for queue in queues: - if queue.name == qName: - found = True - if not queue.altExchange: - self.fail("Alternate exchange not set") - self.assertEqual(queue._altExchange_.name, altName) - self.assertEqual(found, True) - - def test_qpid_config_list_queues_arguments(self): - """ - Test to verify that when the type of a policy limit is - actually a string (though still a valid value), it does not - upset qpid-config - """ - self.startQmf(); - qmf = self.qmf - - names = ["queue_capacity%s" % (i) for i in range(1, 6)] - for name in names: - self.session.queue_declare(queue=name, exclusive=True, - arguments={'qpid.max_count' : str(i), 'qpid.max_size': '100'}) - - output = os.popen(self.qpid_config_command(" queues")).readlines() - queues = [line.split()[0] for line in output[2:len(output)]] #ignore first two lines (header) - - for name in names: - assert name in queues, "%s not in %s" % (name, queues) - - def test_qpid_route(self): - self.startQmf(); - qmf = self.qmf - - command = self.cli_dir() + "/qpid-route dynamic add guest/guest@localhost:%d %s:%d amq.topic" %\ - (self.broker.port, self.remote_host(), self.remote_port()) - ret = os.system(command) - self.assertEqual(ret, 0) - - links = qmf.getObjects(_class="link") - found = False - for link in links: - if link.port == self.remote_port(): - found = True - self.assertEqual(found, True) - - def test_qpid_route_api(self): - self.startQmf(); - qmf = self.qmf - - ret = self.qpid_route_api("dynamic add " - + "guest/guest@localhost:"+str(self.broker.port) + " " - + str(self.remote_host())+":"+str(self.remote_port()) + " " - +"amq.direct") - - self.assertEqual(ret, 0) - - links = qmf.getObjects(_class="link") - found = False - for link in links: - if link.port == self.remote_port(): - found = True - self.assertEqual(found, True) - - - def test_qpid_route_api(self): - self.startQmf(); - qmf = self.qmf - - ret = self.qpid_route_api("dynamic add " - + " --client-sasl-mechanism PLAIN " - + "guest/guest@localhost:"+str(self.broker.port) + " " - + str(self.remote_host())+":"+str(self.remote_port()) + " " - +"amq.direct") - - self.assertEqual(ret, 0) - - links = qmf.getObjects(_class="link") - found = False - for link in links: - if link.port == self.remote_port(): - found = True - self.assertEqual(found, True) - - def test_qpid_route_api_expect_fail(self): - self.startQmf(); - qmf = self.qmf - - ret = self.qpid_route_api("dynamic add " - + " --client-sasl-mechanism PLAIN " - + "localhost:"+str(self.broker.port) + " " - + str(self.remote_host())+":"+str(self.remote_port()) + " " - +"amq.direct") - assert ret != 0 - - - def getProperty(self, msg, name): - for h in msg.headers: - if hasattr(h, name): return getattr(h, name) - return None - - def getAppHeader(self, msg, name): - headers = self.getProperty(msg, "application_headers") - if headers: - return headers[name] - return None - - def qpid_config_command(self, arg = ""): - return self.cli_dir() + "/qpid-config -a localhost:%d" % self.broker.port + " " + arg - - def qpid_config_api(self, arg = ""): - script = import_script(checkenv("QPID_CONFIG_EXEC")) - broker = ["-a", "localhost:"+str(self.broker.port)] - return script.main(broker + arg.split()) - - def qpid_route_api(self, arg = ""): - script = import_script(checkenv("QPID_ROUTE_EXEC")) - return script.main(arg.split()) diff --git a/cpp/src/tests/cluster.cmake b/cpp/src/tests/cluster.cmake deleted file mode 100644 index 3471173e97..0000000000 --- a/cpp/src/tests/cluster.cmake +++ /dev/null @@ -1,90 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# -# Cluster tests cmake fragment, to be included in CMakeLists.txt -# - -add_executable (failover_soak failover_soak.cpp ForkedBroker.cpp ${platform_test_additions}) -target_link_libraries (failover_soak qpidclient) -remember_location(failover_soak) - -add_executable (cluster_authentication_soak cluster_authentication_soak.cpp ForkedBroker.cpp ${platform_test_additions}) -target_link_libraries (cluster_authentication_soak qpidclient) -remember_location(cluster_authentication_soak) - -set (cluster_test_SOURCES - cluster_test - unit_test - ClusterFixture - ForkedBroker - PartialFailure - ClusterFailover - InitialStatusMap - StoreStatus - ) -add_executable (cluster_test ${cluster_test_SOURCES} ${platform_test_additions}) -target_link_libraries (cluster_test ${qpid_test_boost_libs} qpidclient qpidbroker cluster_shared) -remember_location(cluster_test) - -add_test (cluster_test ${CMAKE_CURRENT_SOURCE_DIR}/run_cluster_test${test_script_suffix}) -add_test (cluster_tests ${CMAKE_CURRENT_SOURCE_DIR}/run_cluster_tests${test_script_suffix}) -add_test (cluster_read_credit ${CMAKE_CURRENT_SOURCE_DIR}/cluster_read_credit${test_script_suffix}) -add_test (cluster_test_watchdog ${CMAKE_CURRENT_SOURCE_DIR}/test_watchdog${test_script_suffix}) -add_test (federated_cluster_test ${CMAKE_CURRENT_SOURCE_DIR}/federated_cluster_test${test_script_suffix}) -add_test (clustered_replication_test ${CMAKE_CURRENT_SOURCE_DIR}/clustered_replication_test${test_script_suffix}) - -# FIXME aconway 2009-12-01: translate to cmake -# # Clean up after cluster_test and start_cluster -# CLEANFILES += cluster_test.acl cluster.ports - -# EXTRA_DIST += \ -# ais_check \ -# run_cluster_test \ -# cluster_read_credit \ -# test_watchdog \ -# start_cluster \ -# stop_cluster \ -# restart_cluster \ -# cluster_python_tests \ -# cluster_python_tests_failing.txt \ -# federated_cluster_test \ -# clustered_replication_test \ -# run_cluster_tests \ -# run_long_cluster_tests \ -# testlib.py \ -# cluster_tests.py \ -# long_cluster_tests.py \ -# cluster_tests.fail - -# LONG_TESTS += \ -# run_long_cluster_tests \ -# start_cluster \ -# cluster_python_tests \ -# stop_cluster - -# qpidtest_PROGRAMS += cluster_test - -# cluster_test_SOURCES = \ - -# cluster_test_LDADD=$(lib_client) $(lib_broker) ../cluster.la -lboost_unit_test_framework - -# qpidtest_SCRIPTS += run_cluster_tests cluster_tests.py run_long_cluster_tests long_cluster_tests.py testlib.py cluster_tests.fail - -# endif diff --git a/cpp/src/tests/cluster.mk b/cpp/src/tests/cluster.mk deleted file mode 100644 index 7d17dd7bde..0000000000 --- a/cpp/src/tests/cluster.mk +++ /dev/null @@ -1,100 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -# Include cluster scripts and extra files in distribution even if -# we're not configured for cluster. - -# Useful scripts for doing cluster testing. -CLUSTER_TEST_SCRIPTS_LIST= \ - allhosts rsynchosts \ - qpid-build-rinstall qpid-src-rinstall \ - qpid-test-cluster \ - qpid-cluster-benchmark - -EXTRA_DIST += \ - $(CLUSTER_TEST_SCRIPTS_LIST) \ - ais_check \ - run_cluster_test \ - cluster_read_credit \ - test_watchdog \ - start_cluster \ - stop_cluster \ - restart_cluster \ - cluster_python_tests \ - cluster_python_tests_failing.txt \ - federated_cluster_test \ - clustered_replication_test \ - run_cluster_tests \ - run_long_cluster_tests \ - testlib.py \ - brokertest.py \ - cluster_tests.py \ - cluster_test_logs.py \ - long_cluster_tests.py \ - cluster_tests.fail - - -if HAVE_LIBCPG - -# -# Cluster tests makefile fragment, to be included in Makefile.am -# - -# NOTE: Programs using the openais library must be run with gid=ais -# You should do "newgrp ais" before running the tests to run these. -# - - -# ais_check checks pre-requisites for cluster tests and runs them if ok. -TESTS += \ - run_cluster_test \ - cluster_read_credit \ - test_watchdog \ - run_cluster_tests \ - federated_cluster_test \ - clustered_replication_test - -# Clean up after cluster_test and start_cluster -CLEANFILES += cluster_test.acl cluster.ports - -LONG_TESTS += \ - run_long_cluster_tests \ - start_cluster \ - cluster_python_tests \ - stop_cluster - -qpidtest_PROGRAMS += cluster_test - -cluster_test_SOURCES = \ - cluster_test.cpp \ - unit_test.cpp \ - ClusterFixture.cpp \ - ClusterFixture.h \ - ForkedBroker.h \ - ForkedBroker.cpp \ - PartialFailure.cpp \ - ClusterFailover.cpp - -cluster_test_LDADD=$(lib_client) $(lib_broker) ../cluster.la -lboost_unit_test_framework - -qpidtest_SCRIPTS += run_cluster_tests brokertest.py cluster_tests.py cluster_test_logs.py run_long_cluster_tests long_cluster_tests.py testlib.py cluster_tests.fail -qpidtest_SCRIPTS += $(CLUSTER_TEST_SCRIPTS_LIST) - -endif diff --git a/cpp/src/tests/cluster_authentication_soak.cpp b/cpp/src/tests/cluster_authentication_soak.cpp deleted file mode 100644 index b8e8a22693..0000000000 --- a/cpp/src/tests/cluster_authentication_soak.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <signal.h> -#include <fcntl.h> - -#include <sys/wait.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> - -#include <string> -#include <iostream> -#include <sstream> -#include <vector> - -#include <boost/assign.hpp> - -#include "qpid/framing/Uuid.h" - -#include <ForkedBroker.h> -#include <qpid/client/Connection.h> - -#include <sasl/sasl.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - - - -using namespace std; -using boost::assign::list_of; -using namespace qpid::framing; -using namespace qpid::client; - - -namespace qpid { -namespace tests { - -vector<pid_t> brokerPids; - -typedef vector<ForkedBroker *> brokerVector; - - - - - -int runSilent = 1; -int newbiePort = 0; - - -void -makeClusterName ( string & s ) { - stringstream ss; - ss << "authenticationSoakCluster_" << Uuid(true).str(); - s = ss.str(); -} - - - -void -startBroker ( brokerVector & brokers , int brokerNumber, string const & clusterName ) { - stringstream prefix, clusterArg; - prefix << "soak-" << brokerNumber; - clusterArg << "--cluster-name=" << clusterName; - - std::vector<std::string> argv; - - argv.push_back ("../qpidd"); - argv.push_back ("--no-module-dir"); - argv.push_back ("--load-module=../.libs/cluster.so"); - argv.push_back (clusterArg.str()); - argv.push_back ("--cluster-username=zig"); - argv.push_back ("--cluster-password=zig"); - argv.push_back ("--cluster-mechanism=ANONYMOUS"); - argv.push_back ("--sasl-config=./sasl_config"); - argv.push_back ("--auth=yes"); - argv.push_back ("--mgmt-enable=yes"); - argv.push_back ("--log-prefix"); - argv.push_back (prefix.str()); - argv.push_back ("--log-to-file"); - argv.push_back (prefix.str()+".log"); - argv.push_back ("TMP_DATA_DIR"); - - ForkedBroker * newbie = new ForkedBroker (argv); - newbiePort = newbie->getPort(); - brokers.push_back ( newbie ); -} - - - - -bool -runPerftest ( bool hangTest ) { - stringstream portSs; - portSs << newbiePort; - string portStr = portSs.str(); - char const * path = "./qpid-perftest"; - - vector<char const *> argv; - argv.push_back ( "./qpid-perftest" ); - argv.push_back ( "-p" ); - argv.push_back ( portStr.c_str() ); - argv.push_back ( "--username" ); - argv.push_back ( "zig" ); - argv.push_back ( "--password" ); - argv.push_back ( "zig" ); - argv.push_back ( "--mechanism" ); - argv.push_back ( "DIGEST-MD5" ); - argv.push_back ( "--count" ); - argv.push_back ( "20000" ); - argv.push_back ( 0 ); - - pid_t pid = fork(); - - if ( ! pid ) { - int i=open("/dev/null",O_RDWR); - dup2 ( i, fileno(stdout) ); - dup2 ( i, fileno(stderr) ); - - execv ( path, const_cast<char * const *>(&argv[0]) ); - // The exec failed: we are still in parent process. - perror ( "error running qpid-perftest: " ); - return false; - } - else { - if ( hangTest ) { - if ( ! runSilent ) - cerr << "Pausing perftest " << pid << endl; - kill ( pid, 19 ); - } - - struct timeval startTime, - currentTime, - duration; - - gettimeofday ( & startTime, 0 ); - - while ( 1 ) { - sleep ( 2 ); - int status; - int returned_pid = waitpid ( pid, &status, WNOHANG ); - if ( returned_pid == pid ) { - int exit_status = WEXITSTATUS(status); - if ( exit_status ) { - cerr << "qpid-perftest failed. exit_status was: " << exit_status << endl; - return false; - } - else { - return true; // qpid-perftest succeeded. - } - } - else { // qpid-perftest has not yet completed. - gettimeofday ( & currentTime, 0 ); - timersub ( & currentTime, & startTime, & duration ); - if ( duration.tv_sec > 60 ) { - kill ( pid, 9 ); - cerr << "qpid-perftest pid " << pid << " hanging: killed.\n"; - return false; - } - } - } - - } -} - - - -bool -allBrokersAreAlive ( brokerVector & brokers ) { - for ( unsigned int i = 0; i < brokers.size(); ++ i ) - if ( ! brokers[i]->isRunning() ) - return false; - - return true; -} - - - - - -void -killAllBrokers ( brokerVector & brokers ) { - for ( unsigned int i = 0; i < brokers.size(); ++ i ) { - brokers[i]->kill ( 9 ); - } -} - - - - -void -killOneBroker ( brokerVector & brokers ) { - int doomedBroker = getpid() % brokers.size(); - cout << "Killing broker " << brokers[doomedBroker]->getPID() << endl; - brokers[doomedBroker]->kill ( 9 ); - sleep ( 2 ); -} - - - - -}} // namespace qpid::tests - -using namespace qpid::tests; - - - -/* - * Please note that this test has self-test capability. - * It is intended to detect - * 1. perftest hangs. - * 2. broker deaths - * Both of these condtions can be forced when running manually - * to ensure that the test really does detect them. - * See command-line arguments 3 and 4. - */ -int -main ( int argc, char ** argv ) -{ - // I need the SASL_PATH_TYPE_CONFIG feature, which did not appear until SASL 2.1.22 -#if (SASL_VERSION_FULL < ((2<<16)|(1<<8)|22)) - cout << "Skipping SASL test, SASL version too low." << endl; - return 0; -#endif - - int n_iterations = argc > 1 ? atoi(argv[1]) : 1; - runSilent = argc > 2 ? atoi(argv[2]) : 1; // default to silent - int killBroker = argc > 3 ? atoi(argv[3]) : 0; // Force the kill of one broker. - int hangTest = argc > 4 ? atoi(argv[4]) : 0; // Force the first perftest to hang. - int n_brokers = 3; - brokerVector brokers; - - srand ( getpid() ); - string clusterName; - makeClusterName ( clusterName ); - for ( int i = 0; i < n_brokers; ++ i ) { - startBroker ( brokers, i, clusterName ); - } - - sleep ( 3 ); - - /* Run all qpid-perftest iterations, and only then check for brokers - * still being up. If you just want a quick check for the failure - * mode in which a single iteration would kill all brokers except - * the client-connected one, just run it with the iterations arg - * set to 1. - */ - for ( int iteration = 0; iteration < n_iterations; ++ iteration ) { - if ( ! runPerftest ( hangTest ) ) { - if ( ! runSilent ) - cerr << "qpid-perftest " << iteration << " failed.\n"; - return 1; - } - if ( ! ( iteration % 10 ) ) { - if ( ! runSilent ) - cerr << "qpid-perftest " << iteration << " complete. -------------- \n"; - } - } - if ( ! runSilent ) - cerr << "\nqpid-perftest " << n_iterations << " iterations complete. -------------- \n\n"; - - /* If the command-line tells us to kill a broker, do - * it now. Use this option to prove that this test - * really can detect broker-deaths. - */ - if ( killBroker ) { - killOneBroker ( brokers ); - } - - if ( ! allBrokersAreAlive ( brokers ) ) { - if ( ! runSilent ) - cerr << "not all brokers are alive.\n"; - killAllBrokers ( brokers ); - return 2; - } - - killAllBrokers ( brokers ); - if ( ! runSilent ) - cout << "success.\n"; - - return 0; -} - - - diff --git a/cpp/src/tests/cluster_python_tests b/cpp/src/tests/cluster_python_tests deleted file mode 100755 index 9d9137ed57..0000000000 --- a/cpp/src/tests/cluster_python_tests +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Skip if cluster services not running. -. `dirname $0`/ais_check - -FAILING=`dirname $0`/cluster_python_tests_failing.txt -source `dirname $0`/python_tests - diff --git a/cpp/src/tests/cluster_python_tests_failing.txt b/cpp/src/tests/cluster_python_tests_failing.txt deleted file mode 100644 index 7ba8089946..0000000000 --- a/cpp/src/tests/cluster_python_tests_failing.txt +++ /dev/null @@ -1,32 +0,0 @@ -qpid_tests.broker_0_10.management.ManagementTest.test_purge_queue -qpid_tests.broker_0_10.management.ManagementTest.test_connection_close -qpid_tests.broker_0_10.dtx.DtxTests.test_bad_resume -qpid_tests.broker_0_10.dtx.DtxTests.test_commit_unknown -qpid_tests.broker_0_10.dtx.DtxTests.test_end -qpid_tests.broker_0_10.dtx.DtxTests.test_end_suspend_and_fail -qpid_tests.broker_0_10.dtx.DtxTests.test_end_unknown_xid -qpid_tests.broker_0_10.dtx.DtxTests.test_forget_xid_on_completion -qpid_tests.broker_0_10.dtx.DtxTests.test_get_timeout -qpid_tests.broker_0_10.dtx.DtxTests.test_get_timeout_unknown -qpid_tests.broker_0_10.dtx.DtxTests.test_implicit_end -qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_commit_not_ended -qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_commit_one_phase_false -qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_commit_one_phase_true -qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_prepare_not_ended -qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_rollback_not_ended -qpid_tests.broker_0_10.dtx.DtxTests.test_prepare_unknown -qpid_tests.broker_0_10.dtx.DtxTests.test_recover -qpid_tests.broker_0_10.dtx.DtxTests.test_rollback_unknown -qpid_tests.broker_0_10.dtx.DtxTests.test_select_required -qpid_tests.broker_0_10.dtx.DtxTests.test_set_timeout -qpid_tests.broker_0_10.dtx.DtxTests.test_simple_commit -qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_commit -qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_rollback -qpid_tests.broker_0_10.dtx.DtxTests.test_simple_rollback -qpid_tests.broker_0_10.dtx.DtxTests.test_start_already_known -qpid_tests.broker_0_10.dtx.DtxTests.test_start_join -qpid_tests.broker_0_10.dtx.DtxTests.test_start_join_and_resume -qpid_tests.broker_0_10.dtx.DtxTests.test_suspend_resume -qpid_tests.broker_0_10.dtx.DtxTests.test_suspend_start_end_resume -qpid_tests.broker_0_10.message.MessageTests.test_ttl -qpid_tests.broker_0_10.management.ManagementTest.test_broker_connectivity_oldAPI diff --git a/cpp/src/tests/cluster_read_credit b/cpp/src/tests/cluster_read_credit deleted file mode 100755 index 370d4098c5..0000000000 --- a/cpp/src/tests/cluster_read_credit +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Regression test for http://issues.apache.org/jira/browse/QPID-2086 - -srcdir=`dirname $0` -. $srcdir/ais_check -$srcdir/start_cluster 1 --cluster-read-max=2 || exit 1 -trap $srcdir/stop_cluster EXIT -seq 1 10000 | ./sender --port `cat cluster.ports` --routing-key no-such-queue diff --git a/cpp/src/tests/cluster_test.cpp b/cpp/src/tests/cluster_test.cpp deleted file mode 100644 index f2ccd0ba84..0000000000 --- a/cpp/src/tests/cluster_test.cpp +++ /dev/null @@ -1,1231 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test_tools.h" -#include "unit_test.h" -#include "ForkedBroker.h" -#include "BrokerFixture.h" -#include "ClusterFixture.h" - -#include "qpid/client/Connection.h" -#include "qpid/client/ConnectionSettings.h" -#include "qpid/client/ConnectionAccess.h" -#include "qpid/client/Session.h" -#include "qpid/client/FailoverListener.h" -#include "qpid/client/FailoverManager.h" -#include "qpid/client/QueueOptions.h" -#include "qpid/cluster/Cluster.h" -#include "qpid/cluster/Cpg.h" -#include "qpid/cluster/UpdateClient.h" -#include "qpid/framing/AMQBody.h" -#include "qpid/framing/Uuid.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/log/Logger.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Thread.h" - -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/assign.hpp> - -#include <string> -#include <iostream> -#include <fstream> -#include <iterator> -#include <vector> -#include <set> -#include <algorithm> -#include <iterator> - - -using namespace std; -using namespace qpid; -using namespace qpid::cluster; -using namespace qpid::framing; -using namespace qpid::client; -using namespace boost::assign; -using broker::Broker; -using boost::shared_ptr; - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(cluster_test) - -bool durableFlag = std::getenv("STORE_LIB") != 0; - -void prepareArgs(ClusterFixture::Args& args, const bool durableFlag = false) { - ostringstream clusterLib; - clusterLib << getLibPath("CLUSTER_LIB"); - args += "--auth", "no", "--no-module-dir", "--load-module", clusterLib.str(); - if (durableFlag) - args += "--load-module", getLibPath("STORE_LIB"), "TMP_DATA_DIR"; - else - args += "--no-data-dir"; -} - -ClusterFixture::Args prepareArgs(const bool durableFlag = false) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - return args; -} - -// Timeout for tests that wait for messages -const sys::Duration TIMEOUT=2*sys::TIME_SEC; - - -ostream& operator<<(ostream& o, const cpg_name* n) { - return o << Cpg::str(*n); -} - -ostream& operator<<(ostream& o, const cpg_address& a) { - return o << "(" << a.nodeid <<","<<a.pid<<","<<a.reason<<")"; -} - -template <class T> -ostream& operator<<(ostream& o, const pair<T*, int>& array) { - o << "{ "; - ostream_iterator<cpg_address> i(o, " "); - copy(array.first, array.first+array.second, i); - o << "}"; - return o; -} - -template <class C> set<int> makeSet(const C& c) { - set<int> s; - copy(c.begin(), c.end(), inserter(s, s.begin())); - return s; -} - -class Sender { - public: - Sender(boost::shared_ptr<ConnectionImpl> ci, uint16_t ch) : connection(ci), channel(ch) {} - void send(const AMQBody& body, bool firstSeg, bool lastSeg, bool firstFrame, bool lastFrame) { - AMQFrame f(body); - f.setChannel(channel); - f.setFirstSegment(firstSeg); - f.setLastSegment(lastSeg); - f.setFirstFrame(firstFrame); - f.setLastFrame(lastFrame); - connection->expand(f.encodedSize(), false); - connection->handle(f); - } - - private: - boost::shared_ptr<ConnectionImpl> connection; - uint16_t channel; -}; - -int64_t getMsgSequence(const Message& m) { - return m.getMessageProperties().getApplicationHeaders().getAsInt64("qpid.msg_sequence"); -} - -Message ttlMessage(const string& data, const string& key, uint64_t ttl, bool durable = false) { - Message m(data, key); - m.getDeliveryProperties().setTtl(ttl); - if (durable) m.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - return m; -} - -Message makeMessage(const string& data, const string& key, bool durable = false) { - Message m(data, key); - if (durable) m.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - return m; -} - -vector<string> browse(Client& c, const string& q, int n) { - SubscriptionSettings browseSettings( - FlowControl::messageCredit(n), - ACCEPT_MODE_NONE, - ACQUIRE_MODE_NOT_ACQUIRED, - 0 // No auto-ack. - ); - LocalQueue lq; - c.subs.subscribe(lq, q, browseSettings); - c.session.messageFlush(q); - vector<string> result; - for (int i = 0; i < n; ++i) { - Message m; - if (!lq.get(m, TIMEOUT)) - break; - result.push_back(m.getData()); - } - c.subs.getSubscription(q).cancel(); - return result; -} - -ConnectionSettings aclSettings(int port, const std::string& id) { - ConnectionSettings settings; - settings.port = port; - settings.mechanism = "PLAIN"; - settings.username = id; - settings.password = id; - return settings; -} - -// An illegal frame body -struct PoisonPill : public AMQBody { - virtual uint8_t type() const { return 0xFF; } - virtual void encode(Buffer& ) const {} - virtual void decode(Buffer& , uint32_t=0) {} - virtual uint32_t encodedSize() const { return 0; } - - virtual void print(std::ostream&) const {}; - virtual void accept(AMQBodyConstVisitor&) const {}; - - virtual AMQMethodBody* getMethod() { return 0; } - virtual const AMQMethodBody* getMethod() const { return 0; } - - /** Match if same type and same class/method ID for methods */ - static bool match(const AMQBody& , const AMQBody& ) { return false; } - virtual boost::intrusive_ptr<AMQBody> clone() const { return new PoisonPill; } -}; - -QPID_AUTO_TEST_CASE(testBadClientData) { - // Ensure that bad data on a client connection closes the - // connection but does not stop the broker. - ClusterFixture::Args args; - prepareArgs(args, false); - args += "--log-enable=critical"; // Supress expected errors - ClusterFixture cluster(2, args, -1); - Client c0(cluster[0]); - Client c1(cluster[1]); - boost::shared_ptr<client::ConnectionImpl> ci = - client::ConnectionAccess::getImpl(c0.connection); - AMQFrame poison(boost::intrusive_ptr<AMQBody>(new PoisonPill)); - ci->expand(poison.encodedSize(), false); - ci->handle(poison); - { - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(c0.session.queueQuery("q0"), Exception); - } - Client c00(cluster[0]); - BOOST_CHECK_EQUAL(c00.session.queueQuery("q00").getQueue(), ""); - BOOST_CHECK_EQUAL(c1.session.queueQuery("q1").getQueue(), ""); -} - -QPID_AUTO_TEST_CASE(testAcl) { - ofstream policyFile("cluster_test.acl"); - policyFile << "acl allow foo@QPID create queue name=foo" << endl - << "acl allow foo@QPID create queue name=foo2" << endl - << "acl deny foo@QPID create queue name=bar" << endl - << "acl allow all all" << endl; - policyFile.close(); - char cwd[1024]; - BOOST_CHECK(::getcwd(cwd, sizeof(cwd))); - ostringstream aclLib; - aclLib << getLibPath("ACL_LIB"); - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - args += "--log-enable=critical"; // Supress expected errors - args += "--acl-file", string(cwd) + "/cluster_test.acl", - "--cluster-mechanism", "PLAIN", - "--cluster-username", "cluster", - "--cluster-password", "cluster", - "--load-module", aclLib.str(); - ClusterFixture cluster(2, args, -1); - - Client c0(aclSettings(cluster[0], "c0"), "c0"); - Client c1(aclSettings(cluster[1], "c1"), "c1"); - Client foo(aclSettings(cluster[1], "foo"), "foo"); - - foo.session.queueDeclare("foo", arg::durable=durableFlag); - BOOST_CHECK_EQUAL(c0.session.queueQuery("foo").getQueue(), "foo"); - - { - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(foo.session.queueDeclare("bar", arg::durable=durableFlag), framing::UnauthorizedAccessException); - } - BOOST_CHECK(c0.session.queueQuery("bar").getQueue().empty()); - BOOST_CHECK(c1.session.queueQuery("bar").getQueue().empty()); - - cluster.add(); - Client c2(aclSettings(cluster[2], "c2"), "c2"); - { - ScopedSuppressLogging sl; - BOOST_CHECK_THROW(foo.session.queueDeclare("bar", arg::durable=durableFlag), framing::UnauthorizedAccessException); - } - BOOST_CHECK(c2.session.queueQuery("bar").getQueue().empty()); -} - -QPID_AUTO_TEST_CASE(testMessageTimeToLive) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(2, args, -1); - Client c0(cluster[0], "c0"); - Client c1(cluster[1], "c1"); - c0.session.queueDeclare("p", arg::durable=durableFlag); - c0.session.queueDeclare("q", arg::durable=durableFlag); - c0.session.messageTransfer(arg::content=ttlMessage("a", "q", 200, durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("b", "q", durableFlag)); - c0.session.messageTransfer(arg::content=ttlMessage("x", "p", 100000, durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("y", "p", durableFlag)); - cluster.add(); - Client c2(cluster[1], "c2"); - - BOOST_CHECK_EQUAL(browse(c0, "p", 1), list_of<string>("x")); - BOOST_CHECK_EQUAL(browse(c1, "p", 1), list_of<string>("x")); - BOOST_CHECK_EQUAL(browse(c2, "p", 1), list_of<string>("x")); - - sys::usleep(200*1000); - BOOST_CHECK_EQUAL(browse(c0, "q", 1), list_of<string>("b")); - BOOST_CHECK_EQUAL(browse(c1, "q", 1), list_of<string>("b")); - BOOST_CHECK_EQUAL(browse(c2, "q", 1), list_of<string>("b")); -} - -QPID_AUTO_TEST_CASE(testSequenceOptions) { - // Make sure the exchange qpid.msg_sequence property is properly replicated. - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0], "c0"); - FieldTable ftargs; - ftargs.setInt("qpid.msg_sequence", 1); - c0.session.queueDeclare(arg::queue="q", arg::durable=durableFlag); - c0.session.exchangeDeclare(arg::exchange="ex", arg::type="direct", arg::arguments=ftargs); - c0.session.exchangeBind(arg::exchange="ex", arg::queue="q", arg::bindingKey="k"); - c0.session.messageTransfer(arg::content=makeMessage("1", "k", durableFlag), arg::destination="ex"); - c0.session.messageTransfer(arg::content=makeMessage("2", "k", durableFlag), arg::destination="ex"); - BOOST_CHECK_EQUAL(1, getMsgSequence(c0.subs.get("q", TIMEOUT))); - BOOST_CHECK_EQUAL(2, getMsgSequence(c0.subs.get("q", TIMEOUT))); - - cluster.add(); - Client c1(cluster[1]); - c1.session.messageTransfer(arg::content=makeMessage("3", "k", durableFlag), arg::destination="ex"); - BOOST_CHECK_EQUAL(3, getMsgSequence(c1.subs.get("q", TIMEOUT))); -} - -QPID_AUTO_TEST_CASE(testTxTransaction) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0], "c0"); - c0.session.queueDeclare(arg::queue="q", arg::durable=durableFlag); - c0.session.messageTransfer(arg::content=makeMessage("A", "q", durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("B", "q", durableFlag)); - - // Start a transaction that will commit. - Session commitSession = c0.connection.newSession("commit"); - SubscriptionManager commitSubs(commitSession); - commitSession.txSelect(); - commitSession.messageTransfer(arg::content=makeMessage("a", "q", durableFlag)); - commitSession.messageTransfer(arg::content=makeMessage("b", "q", durableFlag)); - BOOST_CHECK_EQUAL(commitSubs.get("q", TIMEOUT).getData(), "A"); - - // Start a transaction that will roll back. - Session rollbackSession = c0.connection.newSession("rollback"); - SubscriptionManager rollbackSubs(rollbackSession); - rollbackSession.txSelect(); - rollbackSession.messageTransfer(arg::content=makeMessage("1", "q", durableFlag)); - Message rollbackMessage = rollbackSubs.get("q", TIMEOUT); - BOOST_CHECK_EQUAL(rollbackMessage.getData(), "B"); - - BOOST_CHECK_EQUAL(c0.session.queueQuery("q").getMessageCount(), 0u); - // Add new member mid transaction. - cluster.add(); - Client c1(cluster[1], "c1"); - - // More transactional work - BOOST_CHECK_EQUAL(c1.session.queueQuery("q").getMessageCount(), 0u); - rollbackSession.messageTransfer(arg::content=makeMessage("2", "q", durableFlag)); - commitSession.messageTransfer(arg::content=makeMessage("c", "q", durableFlag)); - rollbackSession.messageTransfer(arg::content=makeMessage("3", "q", durableFlag)); - - BOOST_CHECK_EQUAL(c1.session.queueQuery("q").getMessageCount(), 0u); - - // Commit/roll back. - commitSession.txCommit(); - rollbackSession.txRollback(); - rollbackSession.messageRelease(rollbackMessage.getId()); - - // Verify queue status: just the comitted messages and dequeues should remain. - BOOST_CHECK_EQUAL(c1.session.queueQuery("q").getMessageCount(), 4u); - BOOST_CHECK_EQUAL(c1.subs.get("q", TIMEOUT).getData(), "B"); - BOOST_CHECK_EQUAL(c1.subs.get("q", TIMEOUT).getData(), "a"); - BOOST_CHECK_EQUAL(c1.subs.get("q", TIMEOUT).getData(), "b"); - BOOST_CHECK_EQUAL(c1.subs.get("q", TIMEOUT).getData(), "c"); - - commitSession.close(); - rollbackSession.close(); -} - -QPID_AUTO_TEST_CASE(testUnacked) { - // Verify replication of unacknowledged messages. - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0], "c0"); - - Message m; - - // Create unacked message: acquired but not accepted. - SubscriptionSettings manualAccept(FlowControl::unlimited(), ACCEPT_MODE_EXPLICIT, ACQUIRE_MODE_PRE_ACQUIRED, 0); - c0.session.queueDeclare("q1", arg::durable=durableFlag); - c0.session.messageTransfer(arg::content=makeMessage("11","q1", durableFlag)); - LocalQueue q1; - c0.subs.subscribe(q1, "q1", manualAccept); - BOOST_CHECK_EQUAL(q1.get(TIMEOUT).getData(), "11"); // Acquired but not accepted - BOOST_CHECK_EQUAL(c0.session.queueQuery("q1").getMessageCount(), 0u); // Gone from queue - - // Create unacked message: not acquired, accepted or completeed. - SubscriptionSettings manualAcquire(FlowControl::unlimited(), ACCEPT_MODE_EXPLICIT, ACQUIRE_MODE_NOT_ACQUIRED, 0); - c0.session.queueDeclare("q2", arg::durable=durableFlag); - c0.session.messageTransfer(arg::content=makeMessage("21","q2", durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("22","q2", durableFlag)); - LocalQueue q2; - c0.subs.subscribe(q2, "q2", manualAcquire); - m = q2.get(TIMEOUT); // Not acquired or accepted, still on queue - BOOST_CHECK_EQUAL(m.getData(), "21"); - BOOST_CHECK_EQUAL(c0.session.queueQuery("q2").getMessageCount(), 2u); // Not removed - c0.subs.getSubscription("q2").acquire(m); // Acquire manually - BOOST_CHECK_EQUAL(c0.session.queueQuery("q2").getMessageCount(), 1u); // Removed - BOOST_CHECK_EQUAL(q2.get(TIMEOUT).getData(), "22"); // Not acquired or accepted, still on queue - BOOST_CHECK_EQUAL(c0.session.queueQuery("q2").getMessageCount(), 1u); // 1 not acquired. - - // Create empty credit record: acquire and accept but don't complete. - SubscriptionSettings manualComplete(FlowControl::messageWindow(1), ACCEPT_MODE_EXPLICIT, ACQUIRE_MODE_PRE_ACQUIRED, 1, MANUAL_COMPLETION); - c0.session.queueDeclare("q3", arg::durable=durableFlag); - c0.session.messageTransfer(arg::content=makeMessage("31", "q3", durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("32", "q3", durableFlag)); - LocalQueue q3; - c0.subs.subscribe(q3, "q3", manualComplete); - Message m31=q3.get(TIMEOUT); - BOOST_CHECK_EQUAL(m31.getData(), "31"); // Automatically acquired & accepted but not completed. - BOOST_CHECK_EQUAL(c0.session.queueQuery("q3").getMessageCount(), 1u); - - // Add new member while there are unacked messages. - cluster.add(); - Client c1(cluster[1], "c1"); - - // Check queue counts - BOOST_CHECK_EQUAL(c1.session.queueQuery("q1").getMessageCount(), 0u); - BOOST_CHECK_EQUAL(c1.session.queueQuery("q2").getMessageCount(), 1u); - BOOST_CHECK_EQUAL(c1.session.queueQuery("q3").getMessageCount(), 1u); - - // Complete the empty credit message, should unblock the message behind it. - BOOST_CHECK_THROW(q3.get(0), Exception); - c0.session.markCompleted(SequenceSet(m31.getId()), true); - BOOST_CHECK_EQUAL(q3.get(TIMEOUT).getData(), "32"); - BOOST_CHECK_EQUAL(c0.session.queueQuery("q3").getMessageCount(), 0u); - BOOST_CHECK_EQUAL(c1.session.queueQuery("q3").getMessageCount(), 0u); - - // Close the original session - unacked messages should be requeued. - c0.session.close(); - BOOST_CHECK_EQUAL(c1.session.queueQuery("q1").getMessageCount(), 1u); - BOOST_CHECK_EQUAL(c1.session.queueQuery("q2").getMessageCount(), 2u); - - BOOST_CHECK_EQUAL(c1.subs.get("q1", TIMEOUT).getData(), "11"); - BOOST_CHECK_EQUAL(c1.subs.get("q2", TIMEOUT).getData(), "21"); - BOOST_CHECK_EQUAL(c1.subs.get("q2", TIMEOUT).getData(), "22"); -} - -// FIXME aconway 2009-06-17: test for unimplemented feature, enable when implemented. -void testUpdateTxState() { - // Verify that we update transaction state correctly to new members. - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0], "c0"); - - // Do work in a transaction. - c0.session.txSelect(); - c0.session.queueDeclare("q", arg::durable=durableFlag); - c0.session.messageTransfer(arg::content=makeMessage("1","q", durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("2","q", durableFlag)); - Message m; - BOOST_CHECK(c0.subs.get(m, "q", TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "1"); - - // New member, TX not comitted, c1 should see nothing. - cluster.add(); - Client c1(cluster[1], "c1"); - BOOST_CHECK_EQUAL(c1.session.queueQuery(arg::queue="q").getMessageCount(), 0u); - - // After commit c1 shoudl see results of tx. - c0.session.txCommit(); - BOOST_CHECK_EQUAL(c1.session.queueQuery(arg::queue="q").getMessageCount(), 1u); - BOOST_CHECK(c1.subs.get(m, "q", TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "2"); - - // Another transaction with both members active. - c0.session.messageTransfer(arg::content=makeMessage("3","q", durableFlag)); - BOOST_CHECK_EQUAL(c1.session.queueQuery(arg::queue="q").getMessageCount(), 0u); - c0.session.txCommit(); - BOOST_CHECK_EQUAL(c1.session.queueQuery(arg::queue="q").getMessageCount(), 1u); - BOOST_CHECK(c1.subs.get(m, "q", TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "3"); -} - -QPID_AUTO_TEST_CASE(testUpdateMessageBuilder) { - // Verify that we update a partially recieved message to a new member. - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0], "c0"); - c0.session.queueDeclare("q", arg::durable=durableFlag); - Sender sender(ConnectionAccess::getImpl(c0.connection), c0.session.getChannel()); - - // Send first 2 frames of message. - MessageTransferBody transfer( - ProtocolVersion(), string(), // default exchange. - framing::message::ACCEPT_MODE_NONE, - framing::message::ACQUIRE_MODE_PRE_ACQUIRED); - sender.send(transfer, true, false, true, true); - AMQHeaderBody header; - header.get<DeliveryProperties>(true)->setRoutingKey("q"); - if (durableFlag) - header.get<DeliveryProperties>(true)->setDeliveryMode(DELIVERY_MODE_PERSISTENT); - else - header.get<DeliveryProperties>(true)->setDeliveryMode(DELIVERY_MODE_NON_PERSISTENT); - sender.send(header, false, false, true, true); - - // No reliable way to ensure the partial message has arrived - // before we start the new broker, so we sleep. - sys::usleep(2500); - cluster.add(); - - // Send final 2 frames of message. - sender.send(AMQContentBody("ab"), false, true, true, false); - sender.send(AMQContentBody("cd"), false, true, false, true); - - // Verify message is enqued correctly on second member. - Message m; - Client c1(cluster[1], "c1"); - BOOST_CHECK(c1.subs.get(m, "q", TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "abcd"); - BOOST_CHECK_EQUAL(2u, knownBrokerPorts(c1.connection, 2).size()); -} - -QPID_AUTO_TEST_CASE(testConnectionKnownHosts) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0], "c0"); - set<int> kb0 = knownBrokerPorts(c0.connection, 1); - BOOST_CHECK_EQUAL(kb0.size(), 1u); - BOOST_CHECK_EQUAL(kb0, makeSet(cluster)); - - cluster.add(); - Client c1(cluster[1], "c1"); - set<int> kb1 = knownBrokerPorts(c1.connection, 2); - kb0 = knownBrokerPorts(c0.connection, 2); - BOOST_CHECK_EQUAL(kb1.size(), 2u); - BOOST_CHECK_EQUAL(kb1, makeSet(cluster)); - BOOST_CHECK_EQUAL(kb1,kb0); - - cluster.add(); - Client c2(cluster[2], "c2"); - set<int> kb2 = knownBrokerPorts(c2.connection, 3); - kb1 = knownBrokerPorts(c1.connection, 3); - kb0 = knownBrokerPorts(c0.connection, 3); - BOOST_CHECK_EQUAL(kb2.size(), 3u); - BOOST_CHECK_EQUAL(kb2, makeSet(cluster)); - BOOST_CHECK_EQUAL(kb2,kb0); - BOOST_CHECK_EQUAL(kb2,kb1); - - cluster.killWithSilencer(1,c1.connection,9); - kb0 = knownBrokerPorts(c0.connection, 2); - kb2 = knownBrokerPorts(c2.connection, 2); - BOOST_CHECK_EQUAL(kb0.size(), 2u); - BOOST_CHECK_EQUAL(kb0, kb2); -} - -QPID_AUTO_TEST_CASE(testUpdateConsumers) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - - Client c0(cluster[0], "c0"); - c0.session.queueDeclare("p", arg::durable=durableFlag); - c0.session.queueDeclare("q", arg::durable=durableFlag); - c0.subs.subscribe(c0.lq, "q", FlowControl::zero()); - LocalQueue lp; - c0.subs.subscribe(lp, "p", FlowControl::messageCredit(1)); - c0.session.sync(); - - // Start new members - cluster.add(); // Local - Client c1(cluster[1], "c1"); - cluster.add(); - Client c2(cluster[2], "c2"); - - // Transfer messages - c0.session.messageTransfer(arg::content=makeMessage("aaa", "q", durableFlag)); - - c0.session.messageTransfer(arg::content=makeMessage("bbb", "p", durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("ccc", "p", durableFlag)); - - // Activate the subscription, ensure message removed on all queues. - c0.subs.setFlowControl("q", FlowControl::unlimited()); - Message m; - BOOST_CHECK(c0.lq.get(m, TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "aaa"); - BOOST_CHECK_EQUAL(c0.session.queueQuery("q").getMessageCount(), 0u); - BOOST_CHECK_EQUAL(c1.session.queueQuery("q").getMessageCount(), 0u); - BOOST_CHECK_EQUAL(c2.session.queueQuery("q").getMessageCount(), 0u); - - // Check second subscription's flow control: gets first message, not second. - BOOST_CHECK(lp.get(m, TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "bbb"); - BOOST_CHECK_EQUAL(c0.session.queueQuery("p").getMessageCount(), 1u); - BOOST_CHECK_EQUAL(c1.session.queueQuery("p").getMessageCount(), 1u); - BOOST_CHECK_EQUAL(c2.session.queueQuery("p").getMessageCount(), 1u); - - BOOST_CHECK(c0.subs.get(m, "p", TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "ccc"); - - // Kill the subscribing member, ensure further messages are not removed. - cluster.killWithSilencer(0,c0.connection,9); - BOOST_REQUIRE_EQUAL(knownBrokerPorts(c1.connection, 2).size(), 2u); - for (int i = 0; i < 10; ++i) { - c1.session.messageTransfer(arg::content=makeMessage("xxx", "q", durableFlag)); - BOOST_REQUIRE(c1.subs.get(m, "q", TIMEOUT)); - BOOST_REQUIRE_EQUAL(m.getData(), "xxx"); - } -} - -// Test that message data and delivery properties are updated properly. -QPID_AUTO_TEST_CASE(testUpdateMessages) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0], "c0"); - - // Create messages with different delivery properties - c0.session.queueDeclare("q", arg::durable=durableFlag); - c0.session.exchangeBind(arg::exchange="amq.fanout", arg::queue="q"); - c0.session.messageTransfer(arg::content=makeMessage("foo","q", durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("bar","q", durableFlag), - arg::destination="amq.fanout"); - - while (c0.session.queueQuery("q").getMessageCount() != 2) - sys::usleep(1000); // Wait for message to show up on broker 0. - - // Add a new broker, it will catch up. - cluster.add(); - - // Do some work post-add - c0.session.queueDeclare("p", arg::durable=durableFlag); - c0.session.messageTransfer(arg::content=makeMessage("pfoo","p", durableFlag)); - - // Do some work post-join - BOOST_REQUIRE_EQUAL(knownBrokerPorts(c0.connection, 2).size(), 2u); - c0.session.messageTransfer(arg::content=makeMessage("pbar","p", durableFlag)); - - // Verify new brokers have state. - Message m; - - Client c1(cluster[1], "c1"); - - BOOST_CHECK(c1.subs.get(m, "q", TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "foo"); - BOOST_CHECK(m.getDeliveryProperties().hasExchange()); - BOOST_CHECK_EQUAL(m.getDeliveryProperties().getExchange(), ""); - BOOST_CHECK(c1.subs.get(m, "q", TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "bar"); - BOOST_CHECK(m.getDeliveryProperties().hasExchange()); - BOOST_CHECK_EQUAL(m.getDeliveryProperties().getExchange(), "amq.fanout"); - BOOST_CHECK_EQUAL(c1.session.queueQuery("q").getMessageCount(), 0u); - - // Add another broker, don't wait for join - should be stalled till ready. - cluster.add(); - Client c2(cluster[2], "c2"); - BOOST_CHECK(c2.subs.get(m, "p", TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "pfoo"); - BOOST_CHECK(c2.subs.get(m, "p", TIMEOUT)); - BOOST_CHECK_EQUAL(m.getData(), "pbar"); - BOOST_CHECK_EQUAL(c2.session.queueQuery("p").getMessageCount(), 0u); -} - -QPID_AUTO_TEST_CASE(testWiringReplication) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(3, args, -1); - Client c0(cluster[0]); - BOOST_CHECK(c0.session.queueQuery("q").getQueue().empty()); - BOOST_CHECK(c0.session.exchangeQuery("ex").getType().empty()); - c0.session.queueDeclare("q", arg::durable=durableFlag); - c0.session.exchangeDeclare("ex", arg::type="direct"); - c0.session.close(); - c0.connection.close(); - // Verify all brokers get wiring update. - for (size_t i = 0; i < cluster.size(); ++i) { - BOOST_MESSAGE("i == "<< i); - Client c(cluster[i]); - BOOST_CHECK_EQUAL("q", c.session.queueQuery("q").getQueue()); - BOOST_CHECK_EQUAL("direct", c.session.exchangeQuery("ex").getType()); - } -} - -QPID_AUTO_TEST_CASE(testMessageEnqueue) { - // Enqueue on one broker, dequeue on another. - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(2, args, -1); - Client c0(cluster[0]); - c0.session.queueDeclare("q", arg::durable=durableFlag); - c0.session.messageTransfer(arg::content=makeMessage("foo", "q", durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("bar", "q", durableFlag)); - c0.session.close(); - Client c1(cluster[1]); - Message msg; - BOOST_CHECK(c1.subs.get(msg, "q", TIMEOUT)); - BOOST_CHECK_EQUAL(string("foo"), msg.getData()); - BOOST_CHECK(c1.subs.get(msg, "q", TIMEOUT)); - BOOST_CHECK_EQUAL(string("bar"), msg.getData()); -} - -QPID_AUTO_TEST_CASE(testMessageDequeue) { - // Enqueue on one broker, dequeue on two others. - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(3, args, -1); - Client c0(cluster[0], "c0"); - c0.session.queueDeclare("q", arg::durable=durableFlag); - c0.session.messageTransfer(arg::content=makeMessage("foo", "q", durableFlag)); - c0.session.messageTransfer(arg::content=makeMessage("bar", "q", durableFlag)); - - Message msg; - - // Dequeue on 2 others, ensure correct order. - Client c1(cluster[1], "c1"); - BOOST_CHECK(c1.subs.get(msg, "q")); - BOOST_CHECK_EQUAL("foo", msg.getData()); - - Client c2(cluster[2], "c2"); - BOOST_CHECK(c1.subs.get(msg, "q")); - BOOST_CHECK_EQUAL("bar", msg.getData()); - - // Queue should be empty on all cluster members. - BOOST_CHECK_EQUAL(0u, c0.session.queueQuery("q").getMessageCount()); - BOOST_CHECK_EQUAL(0u, c1.session.queueQuery("q").getMessageCount()); - BOOST_CHECK_EQUAL(0u, c2.session.queueQuery("q").getMessageCount()); -} - -QPID_AUTO_TEST_CASE(testDequeueWaitingSubscription) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(3, args, -1); - Client c0(cluster[0]); - BOOST_REQUIRE_EQUAL(knownBrokerPorts(c0.connection, 3).size(), 3u); // Wait for brokers. - - // First start a subscription. - c0.session.queueDeclare("q", arg::durable=durableFlag); - c0.subs.subscribe(c0.lq, "q", FlowControl::messageCredit(2)); - - // Now send messages - Client c1(cluster[1]); - c1.session.messageTransfer(arg::content=makeMessage("foo", "q", durableFlag)); - c1.session.messageTransfer(arg::content=makeMessage("bar", "q", durableFlag)); - - // Check they arrived - Message m; - BOOST_CHECK(c0.lq.get(m, TIMEOUT)); - BOOST_CHECK_EQUAL("foo", m.getData()); - BOOST_CHECK(c0.lq.get(m, TIMEOUT)); - BOOST_CHECK_EQUAL("bar", m.getData()); - - // Queue should be empty on all cluster members. - Client c2(cluster[2]); - BOOST_CHECK_EQUAL(0u, c0.session.queueQuery("q").getMessageCount()); - BOOST_CHECK_EQUAL(0u, c1.session.queueQuery("q").getMessageCount()); - BOOST_CHECK_EQUAL(0u, c2.session.queueQuery("q").getMessageCount()); -} - -QPID_AUTO_TEST_CASE(queueDurabilityPropagationToNewbie) -{ - /* - Start with a single broker. - Set up two queues: one durable, and one not. - Add a new broker to the cluster. - Make sure it has one durable and one non-durable queue. - */ - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0]); - c0.session.queueDeclare("durable_queue", arg::durable=true); - c0.session.queueDeclare("non_durable_queue", arg::durable=false); - cluster.add(); - Client c1(cluster[1]); - QueueQueryResult durable_query = c1.session.queueQuery ( "durable_queue" ); - QueueQueryResult non_durable_query = c1.session.queueQuery ( "non_durable_queue" ); - BOOST_CHECK_EQUAL(durable_query.getQueue(), std::string("durable_queue")); - BOOST_CHECK_EQUAL(non_durable_query.getQueue(), std::string("non_durable_queue")); - - BOOST_CHECK_EQUAL ( durable_query.getDurable(), true ); - BOOST_CHECK_EQUAL ( non_durable_query.getDurable(), false ); -} - - -QPID_AUTO_TEST_CASE(testHeartbeatCancelledOnFailover) -{ - - struct Sender : FailoverManager::Command - { - std::string queue; - std::string content; - - Sender(const std::string& q, const std::string& c) : queue(q), content(c) {} - - void execute(AsyncSession& session, bool) - { - session.messageTransfer(arg::content=makeMessage(content, queue, durableFlag)); - } - }; - - struct Receiver : FailoverManager::Command, MessageListener, qpid::sys::Runnable - { - FailoverManager& mgr; - std::string queue; - std::string expectedContent; - qpid::client::Subscription subscription; - qpid::sys::Monitor lock; - bool ready, failed; - - Receiver(FailoverManager& m, const std::string& q, const std::string& c) : mgr(m), queue(q), expectedContent(c), ready(false), failed(false) {} - - void received(Message& message) - { - BOOST_CHECK_EQUAL(expectedContent, message.getData()); - subscription.cancel(); - } - - void execute(AsyncSession& session, bool) - { - session.queueDeclare(arg::queue=queue, arg::durable=durableFlag); - SubscriptionManager subs(session); - subscription = subs.subscribe(*this, queue); - session.sync(); - setReady(); - subs.run(); - //cleanup: - session.queueDelete(arg::queue=queue); - } - - void run() - { - try { - mgr.execute(*this); - } - catch (const std::exception& e) { - BOOST_MESSAGE("Exception in mgr.execute: " << e.what()); - failed = true; - } - } - - void waitForReady() - { - qpid::sys::Monitor::ScopedLock l(lock); - while (!ready) { - lock.wait(); - } - } - - void setReady() - { - qpid::sys::Monitor::ScopedLock l(lock); - ready = true; - lock.notify(); - } - }; - - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(2, args, -1); - ConnectionSettings settings; - settings.port = cluster[1]; - settings.heartbeat = 1; - FailoverManager fmgr(settings); - Sender sender("my-queue", "my-data"); - Receiver receiver(fmgr, "my-queue", "my-data"); - qpid::sys::Thread runner(receiver); - receiver.waitForReady(); - { - ScopedSuppressLogging allQuiet; // suppress connection closed messages - cluster.kill(1); - //sleep for 2 secs to allow the heartbeat task to fire on the now dead connection: - ::usleep(2*1000*1000); - } - fmgr.execute(sender); - runner.join(); - BOOST_CHECK(!receiver.failed); - fmgr.close(); -} - -QPID_AUTO_TEST_CASE(testPolicyUpdate) { - //tests that the policys internal state is accurate on newly - //joined nodes - ClusterFixture::Args args; - args += "--log-enable", "critical"; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c1(cluster[0], "c1"); - { - ScopedSuppressLogging allQuiet; - QueueOptions options; - options.setSizePolicy(REJECT, 0, 2); - c1.session.queueDeclare("q", arg::arguments=options, arg::durable=durableFlag); - c1.session.messageTransfer(arg::content=makeMessage("one", "q", durableFlag)); - cluster.add(); - Client c2(cluster[1], "c2"); - c2.session.messageTransfer(arg::content=makeMessage("two", "q", durableFlag)); - - BOOST_CHECK_THROW(c2.session.messageTransfer(arg::content=makeMessage("three", "q", durableFlag)), framing::ResourceLimitExceededException); - - Message received; - BOOST_CHECK(c1.subs.get(received, "q")); - BOOST_CHECK_EQUAL(received.getData(), std::string("one")); - BOOST_CHECK(c1.subs.get(received, "q")); - BOOST_CHECK_EQUAL(received.getData(), std::string("two")); - BOOST_CHECK(!c1.subs.get(received, "q")); - } -} - -QPID_AUTO_TEST_CASE(testExclusiveQueueUpdate) { - //tests that exclusive queues are accurately replicated on newly - //joined nodes - ClusterFixture::Args args; - args += "--log-enable", "critical"; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c1(cluster[0], "c1"); - { - ScopedSuppressLogging allQuiet; - c1.session.queueDeclare("q", arg::exclusive=true, arg::autoDelete=true, arg::alternateExchange="amq.fanout"); - cluster.add(); - Client c2(cluster[1], "c2"); - QueueQueryResult result = c2.session.queueQuery("q"); - BOOST_CHECK_EQUAL(result.getQueue(), std::string("q")); - BOOST_CHECK(result.getExclusive()); - BOOST_CHECK(result.getAutoDelete()); - BOOST_CHECK(!result.getDurable()); - BOOST_CHECK_EQUAL(result.getAlternateExchange(), std::string("amq.fanout")); - BOOST_CHECK_THROW(c2.session.queueDeclare(arg::queue="q", arg::exclusive=true, arg::passive=true), framing::ResourceLockedException); - c1.session.close(); - c1.connection.close(); - c2.session = c2.connection.newSession(); - BOOST_CHECK_THROW(c2.session.queueDeclare(arg::queue="q", arg::passive=true), framing::NotFoundException); - } -} - -/** - * Subscribes to specified queue and acquires up to the specified - * number of message but does not accept or release them. These - * message are therefore 'locked' by the clients session. - */ -Subscription lockMessages(Client& client, const std::string& queue, int count) -{ - LocalQueue q; - SubscriptionSettings settings(FlowControl::messageCredit(count)); - settings.autoAck = 0; - Subscription sub = client.subs.subscribe(q, queue, settings); - client.session.messageFlush(sub.getName()); - return sub; -} - -/** - * check that the specified queue contains the expected set of - * messages (matched on content) for all nodes in the cluster - */ -void checkQueue(ClusterFixture& cluster, const std::string& queue, const std::vector<std::string>& messages) -{ - for (size_t i = 0; i < cluster.size(); i++) { - Client client(cluster[i], (boost::format("%1%_%2%") % "c" % (i+1)).str()); - BOOST_CHECK_EQUAL(browse(client, queue, messages.size()), messages); - client.close(); - } -} - -void send(Client& client, const std::string& queue, int count, int start=1, const std::string& base="m", - const std::string& lvqKey="") -{ - for (int i = 0; i < count; i++) { - Message message = makeMessage((boost::format("%1%_%2%") % base % (i+start)).str(), queue, durableFlag); - if (!lvqKey.empty()) message.getHeaders().setString(QueueOptions::strLVQMatchProperty, lvqKey); - client.session.messageTransfer(arg::content=message); - } -} - -QPID_AUTO_TEST_CASE(testRingQueueUpdate) { - //tests that ring queues are accurately replicated on newly - //joined nodes - ClusterFixture::Args args; - args += "--log-enable", "critical"; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c1(cluster[0], "c1"); - { - ScopedSuppressLogging allQuiet; - QueueOptions options; - options.setSizePolicy(RING, 0, 5); - c1.session.queueDeclare("q", arg::arguments=options, arg::durable=durableFlag); - send(c1, "q", 5); - lockMessages(c1, "q", 1); - //add new node - cluster.add(); - BOOST_CHECK_EQUAL(2u, knownBrokerPorts(c1.connection, 2).size());//wait till joined - //send one more message - send(c1, "q", 1, 6); - //release locked message - c1.close(); - //check state of queue on both nodes - checkQueue(cluster, "q", list_of<string>("m_2")("m_3")("m_4")("m_5")("m_6")); - } -} - -QPID_AUTO_TEST_CASE(testRingQueueUpdate2) { - //tests that ring queues are accurately replicated on newly joined - //nodes; just like testRingQueueUpdate, but new node joins after - //the sixth message has been sent. - ClusterFixture::Args args; - args += "--log-enable", "critical"; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c1(cluster[0], "c1"); - { - ScopedSuppressLogging allQuiet; - QueueOptions options; - options.setSizePolicy(RING, 0, 5); - c1.session.queueDeclare("q", arg::arguments=options, arg::durable=durableFlag); - send(c1, "q", 5); - lockMessages(c1, "q", 1); - //send sixth message - send(c1, "q", 1, 6); - //add new node - cluster.add(); - BOOST_CHECK_EQUAL(2u, knownBrokerPorts(c1.connection, 2).size());//wait till joined - //release locked message - c1.close(); - //check state of queue on both nodes - checkQueue(cluster, "q", list_of<string>("m_2")("m_3")("m_4")("m_5")("m_6")); - } -} - -QPID_AUTO_TEST_CASE(testLvqUpdate) { - //tests that lvqs are accurately replicated on newly joined nodes - ClusterFixture::Args args; - args += "--log-enable", "critical"; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c1(cluster[0], "c1"); - { - ScopedSuppressLogging allQuiet; - QueueOptions options; - options.setOrdering(LVQ); - c1.session.queueDeclare("q", arg::arguments=options, arg::durable=durableFlag); - - send(c1, "q", 5, 1, "a", "a"); - send(c1, "q", 2, 1, "b", "b"); - send(c1, "q", 1, 1, "c", "c"); - send(c1, "q", 1, 3, "b", "b"); - - //add new node - cluster.add(); - BOOST_CHECK_EQUAL(2u, knownBrokerPorts(c1.connection, 2).size());//wait till joined - - //check state of queue on both nodes - checkQueue(cluster, "q", list_of<string>("a_5")("b_3")("c_1")); - } -} - - -QPID_AUTO_TEST_CASE(testBrowsedLvqUpdate) { - //tests that lvqs are accurately replicated on newly joined nodes - //if the lvq state has been affected by browsers - ClusterFixture::Args args; - args += "--log-enable", "critical"; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c1(cluster[0], "c1"); - { - ScopedSuppressLogging allQuiet; - QueueOptions options; - options.setOrdering(LVQ); - c1.session.queueDeclare("q", arg::arguments=options, arg::durable=durableFlag); - - send(c1, "q", 1, 1, "a", "a"); - send(c1, "q", 2, 1, "b", "b"); - send(c1, "q", 1, 1, "c", "c"); - checkQueue(cluster, "q", list_of<string>("a_1")("b_2")("c_1")); - send(c1, "q", 4, 2, "a", "a"); - send(c1, "q", 1, 3, "b", "b"); - - //add new node - cluster.add(); - BOOST_CHECK_EQUAL(2u, knownBrokerPorts(c1.connection, 2).size());//wait till joined - - //check state of queue on both nodes - checkQueue(cluster, "q", list_of<string>("a_1")("b_2")("c_1")("a_5")("b_3")); - } -} - -QPID_AUTO_TEST_CASE(testRelease) { - //tests that releasing a messages that was unacked when one node - //joined works correctly - ClusterFixture::Args args; - args += "--log-enable", "critical"; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c1(cluster[0], "c1"); - { - ScopedSuppressLogging allQuiet; - c1.session.queueDeclare("q", arg::durable=durableFlag); - for (int i = 0; i < 5; i++) { - c1.session.messageTransfer(arg::content=makeMessage((boost::format("%1%_%2%") % "m" % (i+1)).str(), "q", durableFlag)); - } - //receive but don't ack a message - LocalQueue lq; - SubscriptionSettings lqSettings(FlowControl::messageCredit(1)); - lqSettings.autoAck = 0; - Subscription lqSub = c1.subs.subscribe(lq, "q", lqSettings); - c1.session.messageFlush("q"); - Message received; - BOOST_CHECK(lq.get(received)); - BOOST_CHECK_EQUAL(received.getData(), std::string("m_1")); - - //add new node - cluster.add(); - - lqSub.release(lqSub.getUnaccepted()); - - //check state of queue on both nodes - vector<string> expected = list_of<string>("m_1")("m_2")("m_3")("m_4")("m_5"); - Client c3(cluster[0], "c3"); - BOOST_CHECK_EQUAL(browse(c3, "q", 5), expected); - Client c2(cluster[1], "c2"); - BOOST_CHECK_EQUAL(browse(c2, "q", 5), expected); - } -} - - -// Browse for 1 message with byte credit, return true if a message was -// received false if not. -bool browseByteCredit(Client& c, const string& q, int n, Message& m) { - SubscriptionSettings browseSettings( - FlowControl(1, n, false), // 1 message, n bytes credit, no window - ACCEPT_MODE_NONE, - ACQUIRE_MODE_NOT_ACQUIRED, - 0 // No auto-ack. - ); - LocalQueue lq; - Subscription s = c.subs.subscribe(lq, q, browseSettings); - c.session.messageFlush(arg::destination=q, arg::sync=true); - c.session.sync(); - c.subs.getSubscription(q).cancel(); - return lq.get(m, 0); // No timeout, flush should push message thru. -} - -// Ensure cluster update preserves exact message size, use byte credt as test. -QPID_AUTO_TEST_CASE(testExactByteCredit) { - ClusterFixture cluster(1, prepareArgs(), -1); - Client c0(cluster[0], "c0"); - c0.session.queueDeclare("q"); - c0.session.messageTransfer(arg::content=Message("MyMessage", "q")); - cluster.add(); - - int size=36; // Size of message on broker: headers+body - Client c1(cluster[1], "c1"); - Message m; - - // Ensure we get the message with exact credit. - BOOST_CHECK(browseByteCredit(c0, "q", size, m)); - BOOST_CHECK(browseByteCredit(c1, "q", size, m)); - // and not with one byte less. - BOOST_CHECK(!browseByteCredit(c0, "q", size-1, m)); - BOOST_CHECK(!browseByteCredit(c1, "q", size-1, m)); -} - -// Test that consumer positions are updated correctly. -// Regression test for https://bugzilla.redhat.com/show_bug.cgi?id=541927 -// -QPID_AUTO_TEST_CASE(testUpdateConsumerPosition) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0], "c0"); - - c0.session.queueDeclare("q", arg::durable=durableFlag); - SubscriptionSettings settings; - settings.autoAck = 0; - // Set the acquire mode to 'not-acquired' the consumer moves along the queue - // but does not acquire (remove) messages. - settings.acquireMode = ACQUIRE_MODE_NOT_ACQUIRED; - Subscription s = c0.subs.subscribe(c0.lq, "q", settings); - c0.session.messageTransfer(arg::content=makeMessage("1", "q", durableFlag)); - BOOST_CHECK_EQUAL("1", c0.lq.get(TIMEOUT).getData()); - - // Add another member, send/receive another message and acquire - // the messages. With the bug, this creates an inconsistency - // because the browse position was not updated to the new member. - cluster.add(); - c0.session.messageTransfer(arg::content=makeMessage("2", "q", durableFlag)); - BOOST_CHECK_EQUAL("2", c0.lq.get(TIMEOUT).getData()); - s.acquire(s.getUnacquired()); - s.accept(s.getUnaccepted()); - - // In the bug we now have 0 messages on cluster[0] and 1 message on cluster[1] - // Subscribing on cluster[1] provokes an error that shuts down cluster[0] - Client c1(cluster[1], "c1"); - Subscription s1 = c1.subs.subscribe(c1.lq, "q"); // Default auto-ack=1 - Message m; - BOOST_CHECK(!c1.lq.get(m, TIMEOUT/10)); - BOOST_CHECK_EQUAL(c1.session.queueQuery("q").getMessageCount(), 0u); - BOOST_CHECK_EQUAL(c0.session.queueQuery("q").getMessageCount(), 0u); -} - -QPID_AUTO_TEST_CASE(testFairsharePriorityDelivery) { - ClusterFixture::Args args; - prepareArgs(args, durableFlag); - ClusterFixture cluster(1, args, -1); - Client c0(cluster[0], "c0"); - - FieldTable arguments; - arguments.setInt("x-qpid-priorities", 10); - arguments.setInt("x-qpid-fairshare", 5); - c0.session.queueDeclare("q", arg::durable=durableFlag, arg::arguments=arguments); - - //send messages of different priorities - for (int i = 0; i < 20; i++) { - Message msg = makeMessage((boost::format("msg-%1%") % i).str(), "q", durableFlag); - msg.getDeliveryProperties().setPriority(i % 2 ? 9 : 5); - c0.session.messageTransfer(arg::content=msg); - } - - //pull off a couple of the messages (first four should be the top priority messages - for (int i = 0; i < 4; i++) { - BOOST_CHECK_EQUAL((boost::format("msg-%1%") % ((i*2)+1)).str(), c0.subs.get("q", TIMEOUT).getData()); - } - - // Add another member - cluster.add(); - Client c1(cluster[1], "c1"); - - //pull off some more messages - BOOST_CHECK_EQUAL((boost::format("msg-%1%") % 9).str(), c0.subs.get("q", TIMEOUT).getData()); - BOOST_CHECK_EQUAL((boost::format("msg-%1%") % 0).str(), c1.subs.get("q", TIMEOUT).getData()); - BOOST_CHECK_EQUAL((boost::format("msg-%1%") % 2).str(), c0.subs.get("q", TIMEOUT).getData()); - - //check queue has same content on both nodes - BOOST_CHECK_EQUAL(browse(c0, "q", 12), browse(c1, "q", 12)); -} - -QPID_AUTO_TEST_SUITE_END() -}} // namespace qpid::tests diff --git a/cpp/src/tests/cluster_test_logs.py b/cpp/src/tests/cluster_test_logs.py deleted file mode 100755 index 9f7d1e2f6c..0000000000 --- a/cpp/src/tests/cluster_test_logs.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Functions for comparing broker log files, used by cluster_tests.py. - -import os, os.path, re, glob -from itertools import izip - -def split_log(log): - """Split a broker log at checkpoints where a member joins. - Return the set of checkpoints discovered.""" - checkpoint_re = re.compile("Member joined, frameSeq=([0-9]+), queue snapshot:") - outfile = None - checkpoints = [] - for l in open(log): - match = checkpoint_re.search(l) - if match: - checkpoint = match.groups()[0] - checkpoints.append(checkpoint) - if outfile: outfile.close() - outfile = open("%s.%s"%(log, checkpoint), 'w') - - if outfile: outfile.write(l) - if outfile: outfile.close() - return checkpoints - -def filter_log(log): - """Filter the contents of a log file to remove data that is expected - to differ between brokers in a cluster. Filtered log contents between - the same checkpoints should match across the cluster.""" - out = open("%s.filter"%(log), 'w') - # Lines to skip entirely, expected differences - skip = "|".join([ - 'local connection', # Only on local broker - 'UPDATER|UPDATEE', # Ignore update process - 'stall for update|unstall, ignore update|cancelled offer .* unstall', - 'caught up', - 'active for links|Passivating links|Activating links', - 'info Connection.* connected to', # UpdateClient connection - 'warning Connection [\d+ [0-9.:]+] closed', # UpdateClient connection - 'warning Broker closed connection: 200, OK', - 'task late', - 'task overran', - 'warning CLOSING .* unsent data', - 'Inter-broker link ', - 'Running in a cluster, marking store', - 'debug Sending keepalive signal to watchdog', # Watchdog timer thread - 'last broker standing joined by 1 replicas, updating queue policies.', - 'Connection .* timed out: closing' # heartbeat connection close - ]) - # Regex to match a UUID - uuid='\w\w\w\w\w\w\w\w-\w\w\w\w-\w\w\w\w-\w\w\w\w-\w\w\w\w\w\w\w\w\w\w\w\w' - # Substitutions to remove expected differences - subs = [ - (r'\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d ', ''), # Remove timestamp - (r'cluster\([0-9.: ]*', 'cluster('), # Remove cluster node id - (r' local\)| shadow\)', ')'), # Remove local/shadow indication - (r'CATCHUP', 'READY'), # Treat catchup as equivalent to ready. - (r'OFFER', 'READY'), # Treat offer as equivalent to ready. - # System UUID expected to be different - (r'(org.apache.qpid.broker:system[:(])%s(\)?)'%(uuid), r'\1UUID\2'), - - # TODO aconway 2010-12-20: review if these should be expected: - (r' len=\d+', ' len=NN'), # buffer lengths - (r' map={.*_object_name:([^,}]*)[,}].*', r' \1'), # V2 map - just keep name - (r'\d+-\d+-\d+--\d+', 'X-X-X--X'), # V1 Object IDs - ] - # Substitutions to mask known issue: durable test shows inconsistent "changed stats for com.redhat.rhm.store:journal" messages. - skip += '|Changed V[12] statistics com.redhat.rhm.store:journal' - subs += [(r'to=console.obj.1.0.com.redhat.rhm.store.journal props=\d+ stats=\d+', - 'to=console.obj.1.0.com.redhat.rhm.store.journal props=NN stats=NN')] - - skip_re = re.compile(skip) - subs = [(re.compile(pattern), subst) for pattern, subst in subs] - for l in open(log): - if skip_re.search(l): continue - for pattern,subst in subs: l = re.sub(pattern,subst,l) - out.write(l) - out.close() - -def verify_logs(): - """Compare log files from cluster brokers, verify that they correspond correctly.""" - for l in glob.glob("*.log"): filter_log(l) - checkpoints = set() - for l in glob.glob("*.filter"): checkpoints = checkpoints.union(set(split_log(l))) - errors=[] - for c in checkpoints: - fragments = glob.glob("*.filter.%s"%(c)) - fragments.sort(reverse=True, key=os.path.getsize) - while len(fragments) >= 2: - a = fragments.pop(0) - b = fragments[0] - for ab in izip(open(a), open(b)): - if ab[0] != ab[1]: - errors.append("\n %s %s"%(a, b)) - break - if errors: - raise Exception("Files differ in %s"%(os.getcwd())+"".join(errors)) - -# Can be run as a script. -if __name__ == "__main__": - verify_logs() diff --git a/cpp/src/tests/cluster_test_scripts/README.txt b/cpp/src/tests/cluster_test_scripts/README.txt deleted file mode 100644 index e861a2f397..0000000000 --- a/cpp/src/tests/cluster_test_scripts/README.txt +++ /dev/null @@ -1,20 +0,0 @@ -Cluster test scripts. - -A set of scripts to start and stop cluster and test clients on -multiple hosts using ssh. - -Pre-requisites: You must be - - set up for password-free ssh access to the test hosts. - - a member of the ais group on all the test hosts. - -Configuration: - -Copy defaults.sh to config.sh and edit the values as necessary. - -Test scripts: - -Test scripts use the functions in functions.sh to start & monitor -cluster and clients. -A test script can collect other scripts. - - diff --git a/cpp/src/tests/cluster_test_scripts/cluster_check b/cpp/src/tests/cluster_test_scripts/cluster_check deleted file mode 100755 index 05fcc1bcd2..0000000000 --- a/cpp/src/tests/cluster_test_scripts/cluster_check +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Check that all members of a cluster are running - -source config.sh - -HOSTS=(`cat $CLUSTER_HOME/hosts`) -PORTS=(`cat $CLUSTER_HOME/ports`) - -for ((i=0; i<${#HOSTS[*]}; ++i)); do - host=${HOSTS[$i]} - port=${PORTS[$i]} - ssh $host "$QPIDD -cp $port" > /dev/null || { - ret=1 - echo "ERROR: broker not running $host:$port" - } -done -exit $ret diff --git a/cpp/src/tests/cluster_test_scripts/cluster_start b/cpp/src/tests/cluster_test_scripts/cluster_start deleted file mode 100755 index 8911358f7e..0000000000 --- a/cpp/src/tests/cluster_test_scripts/cluster_start +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Start a cluster -# -# Arguments: NAME HOST [host...] -# Start a cluster called NAME with N nodes running on the given HOSTs -# repeat the host name to run multiple brokers on one host. Use dynamic -# ports. -# -# Log files, data directories and hosts/ports files are all stored under -# $HOME/cluster_test/$NAME -# - -source config.sh - -CLUSTER_NAME=`date +"${USER}_%F_%T"` -HOSTS=($BROKER_HOSTS) -for ((i = 0; i < ${#HOSTS[*]}; ++i)) ; do - host=${HOSTS[$i]} - datadir=$CLUSTER_HOME/broker$i - log=$datadir/qpidd.log - ssh $host "rm -rf $datadir; mkdir -p $datadir" || { - echo "ERROR: can't make data dir $datadir"; exit 1 - } - port=`ssh $host "echo $QPIDD -dp0 --cluster-name=$CLUSTER_NAME \ - --data-dir=$datadir \ - --log-to-file=$log --log-prefix=broker$i \ - $QPIDD_OPTS | newgrp ais"` || { - error "ERROR: can't start broker $i on $host"; exit 1; - } - PORTS="$PORTS $port" -done - -echo "$BROKER_HOSTS" > $CLUSTER_HOME/hosts -echo "$PORTS" > $CLUSTER_HOME/ports - -`dirname $0`/cluster_check $NAME diff --git a/cpp/src/tests/cluster_test_scripts/cluster_stop b/cpp/src/tests/cluster_test_scripts/cluster_stop deleted file mode 100755 index 09aa8f3b21..0000000000 --- a/cpp/src/tests/cluster_test_scripts/cluster_stop +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Stop the cluster. - -source config.sh - -HOSTS=(`cat $CLUSTER_HOME/hosts`) -PORTS=(`cat $CLUSTER_HOME/ports`) - -for ((i=0; i<${#HOSTS[*]}; ++i)); do - host=${HOSTS[$i]} - port=${PORTS[$i]} - ssh $host "$QPIDD -qp $port" > /dev/null || { - ret=1 - echo "ERROR: stopping broker at $host:$port" - } -done - -exit $ret diff --git a/cpp/src/tests/cluster_test_scripts/config_example.sh b/cpp/src/tests/cluster_test_scripts/config_example.sh deleted file mode 100755 index d47c9a9c77..0000000000 --- a/cpp/src/tests/cluster_test_scripts/config_example.sh +++ /dev/null @@ -1,44 +0,0 @@ -# Cluster configuration. - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# All output stored under $HOME/$CLUSTER_HOME. -CLUSTER_HOME=$HOME/cluster_test - -# Hosts where brokers will be run. Repeat hostname to run multiple brokers on 1 host. -BROKER_HOSTS="mrg22 mrg23 mrg24 mrg25 mrg26" - -# Hosts where clients will be run. -CLIENT_HOSTS="$BROKER_HOSTS" - -# Paths to executables -QPIDD=qpidd -PERFTEST=perftest - -# Directory containing tests -TESTDIR=/usr/bin - -# Options for qpidd, must be sufficient to load the cluster plugin. -# Scripts will add --cluster-name, --daemon, --port and --log-to-file options here. -QPIDD_OPTS=" \ ---auth=no \ ---log-enable=notice+ \ ---log-enable=debug+:cluster \ -" diff --git a/cpp/src/tests/cluster_test_scripts/perftest b/cpp/src/tests/cluster_test_scripts/perftest deleted file mode 100755 index 984761eb5f..0000000000 --- a/cpp/src/tests/cluster_test_scripts/perftest +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run a distributed perftest against a cluster. -# Args: npubs nsubs [perftest-options] - -source config.sh - -NPUBS=${1:-4} ; shift -NSUBS=${1:-4} ; shift -OPTS="--npubs $NPUBS --nsubs $NSUBS $*" - -CLIENTS=($CLIENT_HOSTS) -BROKERS=(`cat $CLUSTER_HOME/hosts`) -PORTS=(`cat $CLUSTER_HOME/ports`) - -start() { - client=${CLIENTS[i % ${#CLIENTS[*]}]} - broker=${BROKERS[i % ${#BROKERS[*]}]} - port=${PORTS[i % ${#PORTS[*]}]} - ssh -n $client $PERFTEST $OPTS $* -b $broker -p $port & - PIDS="$PIDS $!" -} - -ssh ${CLIENTS[0]} $PERFTEST $OPTS --setup -b ${BROKERS[0]} -p${PORTS[0]} -for (( i=0 ; i < $NPUBS ; ++i)); do start --publish; done -for (( ; i < $NPUBS+$NSUBS ; ++i)); do start --subscribe; done -ssh ${CLIENTS[0]} $PERFTEST $OPTS --control -b ${BROKERS[0]} -p${PORTS[0]} - -for pid in $PIDS; do - wait $pid || echo "ERROR: client process $pid failed" -done - -`dirname $0`/cluster_check - - diff --git a/cpp/src/tests/cluster_tests.fail b/cpp/src/tests/cluster_tests.fail deleted file mode 100644 index b28b04f643..0000000000 --- a/cpp/src/tests/cluster_tests.fail +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/cpp/src/tests/cluster_tests.py b/cpp/src/tests/cluster_tests.py deleted file mode 100755 index 593791297a..0000000000 --- a/cpp/src/tests/cluster_tests.py +++ /dev/null @@ -1,1057 +0,0 @@ -#!/usr/bin/env python - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import os, signal, sys, time, imp, re, subprocess, glob, cluster_test_logs -from qpid import datatypes, messaging -from brokertest import * -from qpid.harness import Skipped -from qpid.messaging import Message, Empty, Disposition, REJECTED -from threading import Thread, Lock, Condition -from logging import getLogger -from itertools import chain -from tempfile import NamedTemporaryFile - -log = getLogger("qpid.cluster_tests") - -# Note: brokers that shut themselves down due to critical error during -# normal operation will still have an exit code of 0. Brokers that -# shut down because of an error found during initialize will exit with -# a non-0 code. Hence the apparently inconsistent use of EXPECT_EXIT_OK -# and EXPECT_EXIT_FAIL in some of the tests below. - -# TODO aconway 2010-03-11: resolve this - ideally any exit due to an error -# should give non-0 exit status. - -# Import scripts as modules -qpid_cluster=import_script(checkenv("QPID_CLUSTER_EXEC")) - -def readfile(filename): - """Returns te content of file named filename as a string""" - f = file(filename) - try: return f.read() - finally: f.close() - -class ShortTests(BrokerTest): - """Short cluster functionality tests.""" - - def test_message_replication(self): - """Test basic cluster message replication.""" - # Start a cluster, send some messages to member 0. - cluster = self.cluster(2) - s0 = cluster[0].connect().session() - s0.sender("q; {create:always}").send(Message("x")) - s0.sender("q; {create:always}").send(Message("y")) - s0.connection.close() - - # Verify messages available on member 1. - s1 = cluster[1].connect().session() - m = s1.receiver("q", capacity=1).fetch(timeout=1) - s1.acknowledge() - self.assertEqual("x", m.content) - s1.connection.close() - - # Start member 2 and verify messages available. - s2 = cluster.start().connect().session() - m = s2.receiver("q", capacity=1).fetch(timeout=1) - s2.acknowledge() - self.assertEqual("y", m.content) - s2.connection.close() - - def test_store_direct_update_match(self): - """Verify that brokers stores an identical message whether they receive it - direct from clients or during an update, no header or other differences""" - cluster = self.cluster(0, args=["--load-module", self.test_store_lib]) - cluster.start(args=["--test-store-dump", "direct.dump"]) - # Try messages with various headers - cluster[0].send_message("q", Message(durable=True, content="foobar", - subject="subject", - reply_to="reply_to", - properties={"n":10})) - # Try messages of different sizes - for size in range(0,10000,100): - cluster[0].send_message("q", Message(content="x"*size, durable=True)) - # Try sending via named exchange - c = cluster[0].connect_old() - s = c.session(str(qpid.datatypes.uuid4())) - s.exchange_bind(exchange="amq.direct", binding_key="foo", queue="q") - props = s.delivery_properties(routing_key="foo", delivery_mode=2) - s.message_transfer( - destination="amq.direct", - message=qpid.datatypes.Message(props, "content")) - - # Now update a new member and compare their dumps. - cluster.start(args=["--test-store-dump", "updatee.dump"]) - assert readfile("direct.dump") == readfile("updatee.dump") - os.remove("direct.dump") - os.remove("updatee.dump") - - def test_sasl(self): - """Test SASL authentication and encryption in a cluster""" - sasl_config=os.path.join(self.rootdir, "sasl_config") - acl=os.path.join(os.getcwd(), "policy.acl") - aclf=file(acl,"w") - aclf.write(""" -acl deny zag@QPID create queue -acl allow all all -""") - aclf.close() - cluster = self.cluster(2, args=["--auth", "yes", - "--sasl-config", sasl_config, - "--load-module", os.getenv("ACL_LIB"), - "--acl-file", acl]) - - # Valid user/password, ensure queue is created. - c = cluster[0].connect(username="zig", password="zig") - c.session().sender("ziggy;{create:always}") - c.close() - c = cluster[1].connect(username="zig", password="zig") - c.session().receiver("ziggy;{assert:always}") - c.close() - for b in cluster: b.ready() # Make sure all brokers still running. - - # Valid user, bad password - try: - cluster[0].connect(username="zig", password="foo").close() - self.fail("Expected exception") - except messaging.exceptions.ConnectionError: pass - for b in cluster: b.ready() # Make sure all brokers still running. - - # Bad user ID - try: - cluster[0].connect(username="foo", password="bar").close() - self.fail("Expected exception") - except messaging.exceptions.ConnectionError: pass - for b in cluster: b.ready() # Make sure all brokers still running. - - # Action disallowed by ACL - c = cluster[0].connect(username="zag", password="zag") - try: - s = c.session() - s.sender("zaggy;{create:always}") - s.close() - self.fail("Expected exception") - except messaging.exceptions.UnauthorizedAccess: pass - # make sure the queue was not created at the other node. - c = cluster[0].connect(username="zag", password="zag") - try: - s = c.session() - s.sender("zaggy;{assert:always}") - s.close() - self.fail("Expected exception") - except messaging.exceptions.NotFound: pass - - def test_user_id_update(self): - """Ensure that user-id of an open session is updated to new cluster members""" - sasl_config=os.path.join(self.rootdir, "sasl_config") - cluster = self.cluster(1, args=["--auth", "yes", "--sasl-config", sasl_config,]) - c = cluster[0].connect(username="zig", password="zig") - s = c.session().sender("q;{create:always}") - s.send(Message("x", user_id="zig")) # Message sent before start new broker - cluster.start() - s.send(Message("y", user_id="zig")) # Messsage sent after start of new broker - # Verify brokers are healthy and messages are on the queue. - self.assertEqual("x", cluster[0].get_message("q").content) - self.assertEqual("y", cluster[1].get_message("q").content) - - def test_link_events(self): - """Regression test for https://bugzilla.redhat.com/show_bug.cgi?id=611543""" - args = ["--mgmt-pub-interval", 1] # Publish management information every second. - broker1 = self.cluster(1, args)[0] - broker2 = self.cluster(1, args)[0] - qp = self.popen(["qpid-printevents", broker1.host_port()], EXPECT_RUNNING) - qr = self.popen(["qpid-route", "route", "add", - broker1.host_port(), broker2.host_port(), - "amq.fanout", "key" - ], EXPECT_EXIT_OK) - # Look for link event in printevents output. - retry(lambda: find_in_file("brokerLinkUp", qp.outfile("out"))) - broker1.ready() - broker2.ready() - - def test_queue_cleaner(self): - """ Regression test to ensure that cleanup of expired messages works correctly """ - cluster = self.cluster(2, args=["--queue-purge-interval", 3]) - - s0 = cluster[0].connect().session() - sender = s0.sender("my-lvq; {create: always, node:{x-declare:{arguments:{'qpid.last_value_queue':1}}}}") - #send 10 messages that will all expire and be cleaned up - for i in range(1, 10): - msg = Message("message-%s" % i) - msg.properties["qpid.LVQ_key"] = "a" - msg.ttl = 0.1 - sender.send(msg) - #wait for queue cleaner to run - time.sleep(3) - - #test all is ok by sending and receiving a message - msg = Message("non-expiring") - msg.properties["qpid.LVQ_key"] = "b" - sender.send(msg) - s0.connection.close() - s1 = cluster[1].connect().session() - m = s1.receiver("my-lvq", capacity=1).fetch(timeout=1) - s1.acknowledge() - self.assertEqual("non-expiring", m.content) - s1.connection.close() - - for b in cluster: b.ready() # Make sure all brokers still running. - - - def test_amqfailover_visible(self): - """Verify that the amq.failover exchange can be seen by - QMF-based tools - regression test for BZ615300.""" - broker1 = self.cluster(1)[0] - broker2 = self.cluster(1)[0] - qs = subprocess.Popen(["qpid-stat", "-e", broker1.host_port()], stdout=subprocess.PIPE) - out = qs.communicate()[0] - assert out.find("amq.failover") > 0 - - def evaluate_address(self, session, address): - """Create a receiver just to evaluate an address for its side effects""" - r = session.receiver(address) - r.close() - - def test_expire_fanout(self): - """Regression test for QPID-2874: Clustered broker crashes in assertion in - cluster/ExpiryPolicy.cpp. - Caused by a fan-out message being updated as separate messages""" - cluster = self.cluster(1) - session0 = cluster[0].connect().session() - # Create 2 queues bound to fanout exchange. - self.evaluate_address(session0, "q1;{create:always,node:{x-bindings:[{exchange:'amq.fanout',queue:q1}]}}") - self.evaluate_address(session0, "q2;{create:always,node:{x-bindings:[{exchange:'amq.fanout',queue:q2}]}}") - queues = ["q1", "q2"] - # Send a fanout message with a long timeout - s = session0.sender("amq.fanout") - s.send(Message("foo", ttl=100), sync=False) - # Start a new member, check the messages - cluster.start() - session1 = cluster[1].connect().session() - for q in queues: self.assert_browse(session1, "q1", ["foo"]) - - def test_route_update(self): - """Regression test for https://issues.apache.org/jira/browse/QPID-2982 - Links and bridges associated with routes were not replicated on update. - This meant extra management objects and caused an exit if a management - client was attached. - """ - args=["--mgmt-pub-interval=1","--log-enable=trace+:management"] - cluster0 = self.cluster(1, args=args) - cluster1 = self.cluster(1, args=args) - assert 0 == subprocess.call( - ["qpid-route", "route", "add", cluster0[0].host_port(), - cluster1[0].host_port(), "dummy-exchange", "dummy-key", "-d"]) - cluster0.start() - - # Wait for qpid-tool:list on cluster0[0] to generate expected output. - pattern = re.compile("org.apache.qpid.broker.*link") - qpid_tool = subprocess.Popen(["qpid-tool", cluster0[0].host_port()], - stdin=subprocess.PIPE, stdout=subprocess.PIPE) - class Scanner(Thread): - def __init__(self): self.found = False; Thread.__init__(self) - def run(self): - for l in qpid_tool.stdout: - if pattern.search(l): self.found = True; return - scanner = Scanner() - scanner.start() - start = time.time() - try: - # Wait up to 5 second timeout for scanner to find expected output - while not scanner.found and time.time() < start + 5: - qpid_tool.stdin.write("list\n") # Ask qpid-tool to list - for b in cluster0: b.ready() # Raise if any brokers are down - finally: - qpid_tool.stdin.write("quit\n") - qpid_tool.wait() - scanner.join() - assert scanner.found - # Regression test for https://issues.apache.org/jira/browse/QPID-3235 - # Inconsistent stats when changing elder. - - # Force a change of elder - cluster0.start() - cluster0[0].kill() - time.sleep(2) # Allow a management interval to pass. - # Verify logs are consistent - cluster_test_logs.verify_logs() - - def test_redelivered(self): - """Verify that redelivered flag is set correctly on replayed messages""" - cluster = self.cluster(2, expect=EXPECT_EXIT_FAIL) - url = "amqp:tcp:%s,tcp:%s" % (cluster[0].host_port(), cluster[1].host_port()) - queue = "my-queue" - cluster[0].declare_queue(queue) - self.sender = self.popen( - ["qpid-send", - "--broker", url, - "--address", queue, - "--sequence=true", - "--send-eos=1", - "--messages=100000", - "--connection-options={reconnect:true}" - ]) - self.receiver = self.popen( - ["qpid-receive", - "--broker", url, - "--address", queue, - "--ignore-duplicates", - "--check-redelivered", - "--connection-options={reconnect:true}", - "--forever" - ]) - time.sleep(1)#give sender enough time to have some messages to replay - cluster[0].kill() - self.sender.wait() - self.receiver.wait() - cluster[1].kill() - - class BlockedSend(Thread): - """Send a message, send is expected to block. - Verify that it does block (for a given timeout), then allow - waiting till it unblocks when it is expected to do so.""" - def __init__(self, sender, msg): - self.sender, self.msg = sender, msg - self.blocked = True - self.condition = Condition() - self.timeout = 0.1 # Time to wait for expected results. - Thread.__init__(self) - def run(self): - try: - self.sender.send(self.msg, sync=True) - self.condition.acquire() - try: - self.blocked = False - self.condition.notify() - finally: self.condition.release() - except Exception,e: print "BlockedSend exception: %s"%e - def start(self): - Thread.start(self) - time.sleep(self.timeout) - assert self.blocked # Expected to block - def assert_blocked(self): assert self.blocked - def wait(self): # Now expecting to unblock - self.condition.acquire() - try: - while self.blocked: - self.condition.wait(self.timeout) - if self.blocked: raise Exception("Timed out waiting for send to unblock") - finally: self.condition.release() - self.join() - - def queue_flowlimit_test(self, brokers): - """Verify that the queue's flowlimit configuration and state are - correctly replicated. - The brokers argument allows this test to run on single broker, - cluster of 2 pre-startd brokers or cluster where second broker - starts after queue is in flow control. - """ - # configure a queue with a specific flow limit on first broker - ssn0 = brokers.first().connect().session() - s0 = ssn0.sender("flq; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':5, 'qpid.flow_resume_count':3}}}}") - brokers.first().startQmf() - q1 = [q for q in brokers.first().qmf_session.getObjects(_class="queue") if q.name == "flq"][0] - oid = q1.getObjectId() - self.assertEqual(q1.name, "flq") - self.assertEqual(q1.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L}) - assert not q1.flowStopped - self.assertEqual(q1.flowStoppedCount, 0) - - # fill the queue on one broker until flow control is active - for x in range(5): s0.send(Message(str(x))) - sender = ShortTests.BlockedSend(s0, Message(str(6))) - sender.start() # Tests that sender does block - # Verify the broker queue goes into a flowStopped state - deadline = time.time() + 1 - while not q1.flowStopped and time.time() < deadline: q1.update() - assert q1.flowStopped - self.assertEqual(q1.flowStoppedCount, 1) - sender.assert_blocked() # Still blocked - - # Now verify the both brokers in cluster have same configuration - brokers.second().startQmf() - qs = brokers.second().qmf_session.getObjects(_objectId=oid) - self.assertEqual(len(qs), 1) - q2 = qs[0] - self.assertEqual(q2.name, "flq") - self.assertEqual(q2.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L}) - assert q2.flowStopped - self.assertEqual(q2.flowStoppedCount, 1) - - # now drain the queue using a session to the other broker - ssn1 = brokers.second().connect().session() - r1 = ssn1.receiver("flq", capacity=6) - for x in range(4): - r1.fetch(timeout=0) - ssn1.acknowledge() - sender.wait() # Verify no longer blocked. - - # and re-verify state of queue on both brokers - q1.update() - assert not q1.flowStopped - q2.update() - assert not q2.flowStopped - - ssn0.connection.close() - ssn1.connection.close() - cluster_test_logs.verify_logs() - - def test_queue_flowlimit(self): - """Test flow limits on a standalone broker""" - broker = self.broker() - class Brokers: - def first(self): return broker - def second(self): return broker - self.queue_flowlimit_test(Brokers()) - - def test_queue_flowlimit_cluster(self): - cluster = self.cluster(2) - class Brokers: - def first(self): return cluster[0] - def second(self): return cluster[1] - self.queue_flowlimit_test(Brokers()) - - def test_queue_flowlimit_cluster_join(self): - cluster = self.cluster(1) - class Brokers: - def first(self): return cluster[0] - def second(self): - if len(cluster) == 1: cluster.start() - return cluster[1] - self.queue_flowlimit_test(Brokers()) - - def test_queue_flowlimit_replicate(self): - """ Verify that a queue which is in flow control BUT has drained BELOW - the flow control 'stop' threshold, is correctly replicated when a new - broker is added to the cluster. - """ - - class AsyncSender(Thread): - """Send a fixed number of msgs from a sender in a separate thread - so it may block without blocking the test. - """ - def __init__(self, broker, address, count=1, size=4): - Thread.__init__(self) - self.daemon = True - self.broker = broker - self.queue = address - self.count = count - self.size = size - self.done = False - - def run(self): - self.sender = subprocess.Popen(["qpid-send", - "--capacity=1", - "--content-size=%s" % self.size, - "--messages=%s" % self.count, - "--failover-updates", - "--connection-options={reconnect:true}", - "--address=%s" % self.queue, - "--broker=%s" % self.broker.host_port()]) - self.sender.wait() - self.done = True - - cluster = self.cluster(2) - # create a queue with rather draconian flow control settings - ssn0 = cluster[0].connect().session() - s0 = ssn0.sender("flq; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':100, 'qpid.flow_resume_count':20}}}}") - - # fire off the sending thread to broker[0], and wait until the queue - # hits flow control on broker[1] - sender = AsyncSender(cluster[0], "flq", count=110); - sender.start(); - - cluster[1].startQmf() - q_obj = [q for q in cluster[1].qmf_session.getObjects(_class="queue") if q.name == "flq"][0] - deadline = time.time() + 10 - while not q_obj.flowStopped and time.time() < deadline: - q_obj.update() - assert q_obj.flowStopped - assert not sender.done - assert q_obj.msgDepth < 110 - - # Now drain enough messages on broker[1] to drop below the flow stop - # threshold, but not relieve flow control... - receiver = subprocess.Popen(["qpid-receive", - "--messages=15", - "--timeout=1", - "--print-content=no", - "--failover-updates", - "--connection-options={reconnect:true}", - "--ack-frequency=1", - "--address=flq", - "--broker=%s" % cluster[1].host_port()]) - receiver.wait() - q_obj.update() - assert q_obj.flowStopped - assert not sender.done - current_depth = q_obj.msgDepth - - # add a new broker to the cluster, and verify that the queue is in flow - # control on that broker - cluster.start() - cluster[2].startQmf() - q_obj = [q for q in cluster[2].qmf_session.getObjects(_class="queue") if q.name == "flq"][0] - assert q_obj.flowStopped - assert q_obj.msgDepth == current_depth - - # now drain the queue on broker[2], and verify that the sender becomes - # unblocked - receiver = subprocess.Popen(["qpid-receive", - "--messages=95", - "--timeout=1", - "--print-content=no", - "--failover-updates", - "--connection-options={reconnect:true}", - "--ack-frequency=1", - "--address=flq", - "--broker=%s" % cluster[2].host_port()]) - receiver.wait() - q_obj.update() - assert not q_obj.flowStopped - assert q_obj.msgDepth == 0 - - # verify that the sender has become unblocked - sender.join(timeout=5) - assert not sender.isAlive() - assert sender.done - - def test_blocked_queue_delete(self): - """Verify that producers which are blocked on a queue due to flow - control are unblocked when that queue is deleted. - """ - - cluster = self.cluster(2) - cluster[0].startQmf() - cluster[1].startQmf() - - # configure a queue with a specific flow limit on first broker - ssn0 = cluster[0].connect().session() - s0 = ssn0.sender("flq; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':5, 'qpid.flow_resume_count':3}}}}") - q1 = [q for q in cluster[0].qmf_session.getObjects(_class="queue") if q.name == "flq"][0] - oid = q1.getObjectId() - self.assertEqual(q1.name, "flq") - self.assertEqual(q1.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L}) - assert not q1.flowStopped - self.assertEqual(q1.flowStoppedCount, 0) - - # fill the queue on one broker until flow control is active - for x in range(5): s0.send(Message(str(x))) - sender = ShortTests.BlockedSend(s0, Message(str(6))) - sender.start() # Tests that sender does block - # Verify the broker queue goes into a flowStopped state - deadline = time.time() + 1 - while not q1.flowStopped and time.time() < deadline: q1.update() - assert q1.flowStopped - self.assertEqual(q1.flowStoppedCount, 1) - sender.assert_blocked() # Still blocked - - # Now verify the both brokers in cluster have same configuration - qs = cluster[1].qmf_session.getObjects(_objectId=oid) - self.assertEqual(len(qs), 1) - q2 = qs[0] - self.assertEqual(q2.name, "flq") - self.assertEqual(q2.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L}) - assert q2.flowStopped - self.assertEqual(q2.flowStoppedCount, 1) - - # now delete the blocked queue from other broker - ssn1 = cluster[1].connect().session() - self.evaluate_address(ssn1, "flq;{delete:always}") - sender.wait() # Verify no longer blocked. - - ssn0.connection.close() - ssn1.connection.close() - cluster_test_logs.verify_logs() - - - def test_alternate_exchange_update(self): - """Verify that alternate-exchange on exchanges and queues is propagated to new members of a cluster. """ - cluster = self.cluster(1) - s0 = cluster[0].connect().session() - # create alt queue bound to amq.fanout exchange, will be destination for alternate exchanges - self.evaluate_address(s0, "alt;{create:always,node:{x-bindings:[{exchange:'amq.fanout',queue:alt}]}}") - # create direct exchange ex with alternate-exchange amq.fanout and no queues bound - self.evaluate_address(s0, "ex;{create:always,node:{type:topic, x-declare:{type:'direct', alternate-exchange:'amq.fanout'}}}") - # create queue q with alternate-exchange amq.fanout - self.evaluate_address(s0, "q;{create:always,node:{type:queue, x-declare:{alternate-exchange:'amq.fanout'}}}") - - def verify(broker): - s = broker.connect().session() - # Verify unmatched message goes to ex's alternate. - s.sender("ex").send("foo") - self.assertEqual("foo", s.receiver("alt").fetch(timeout=0).content) - # Verify rejected message goes to q's alternate. - s.sender("q").send("bar") - msg = s.receiver("q").fetch(timeout=0) - self.assertEqual("bar", msg.content) - s.acknowledge(msg, Disposition(REJECTED)) # Reject the message - self.assertEqual("bar", s.receiver("alt").fetch(timeout=0).content) - - verify(cluster[0]) - cluster.start() - verify(cluster[1]) - - def test_binding_order(self): - """Regression test for binding order inconsistency in cluster""" - cluster = self.cluster(1) - c0 = cluster[0].connect() - s0 = c0.session() - # Declare multiple queues bound to same key on amq.topic - def declare(q,max=0): - if max: declare = 'x-declare:{arguments:{"qpid.max_count":%d, "qpid.flow_stop_count":0}}'%max - else: declare = 'x-declare:{}' - bind='x-bindings:[{queue:%s,key:key,exchange:"amq.topic"}]'%(q) - s0.sender("%s;{create:always,node:{%s,%s}}" % (q,declare,bind)) - declare('d',max=4) # Only one with a limit - for q in ['c', 'b','a']: declare(q) - # Add a cluster member, send enough messages to exceed the max count - cluster.start() - try: - s = s0.sender('amq.topic/key') - for m in xrange(1,6): s.send(Message(str(m))) - self.fail("Expected capacity exceeded exception") - except messaging.exceptions.TargetCapacityExceeded: pass - c1 = cluster[1].connect() - s1 = c1.session() - s0 = c0.session() # Old session s0 is broken by exception. - # Verify queue contents are consistent. - for q in ['a','b','c','d']: - self.assertEqual(self.browse(s0, q), self.browse(s1, q)) - # Verify queue contents are "best effort" - for q in ['a','b','c']: self.assert_browse(s1,q,[str(n) for n in xrange(1,6)]) - self.assert_browse(s1,'d',[str(n) for n in xrange(1,5)]) - - def test_deleted_exchange(self): - """QPID-3215: cached exchange reference can cause cluster inconsistencies - if exchange is deleted/recreated - Verify stand-alone case - """ - cluster = self.cluster() - # Verify we do not route message via an exchange that has been destroyed. - cluster.start() - s0 = cluster[0].connect().session() - self.evaluate_address(s0, "ex;{create:always,node:{type:topic}}") - self.evaluate_address(s0, "q;{create:always,node:{x-bindings:[{exchange:'ex',queue:q,key:foo}]}}") - send0 = s0.sender("ex/foo") - send0.send("foo") - self.assert_browse(s0, "q", ["foo"]) - self.evaluate_address(s0, "ex;{delete:always}") - try: - send0.send("bar") # Should fail, exchange is deleted. - self.fail("Expected not-found exception") - except qpid.messaging.NotFound: pass - self.assert_browse(cluster[0].connect().session(), "q", ["foo"]) - - def test_deleted_exchange_inconsistent(self): - """QPID-3215: cached exchange reference can cause cluster inconsistencies - if exchange is deleted/recreated - - Verify cluster inconsistency. - """ - cluster = self.cluster() - cluster.start() - s0 = cluster[0].connect().session() - self.evaluate_address(s0, "ex;{create:always,node:{type:topic}}") - self.evaluate_address(s0, "q;{create:always,node:{x-bindings:[{exchange:'ex',queue:q,key:foo}]}}") - send0 = s0.sender("ex/foo") - send0.send("foo") - self.assert_browse(s0, "q", ["foo"]) - - cluster.start() - s1 = cluster[1].connect().session() - self.evaluate_address(s0, "ex;{delete:always}") - try: - send0.send("bar") - self.fail("Expected not-found exception") - except qpid.messaging.NotFound: pass - - self.assert_browse(s1, "q", ["foo"]) - - -class LongTests(BrokerTest): - """Tests that can run for a long time if -DDURATION=<minutes> is set""" - def duration(self): - d = self.config.defines.get("DURATION") - if d: return float(d)*60 - else: return 3 # Default is to be quick - - def test_failover(self): - """Test fail-over during continuous send-receive with errors""" - - # Original cluster will all be killed so expect exit with failure - cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL) - for b in cluster: ErrorGenerator(b) - - # Start sender and receiver threads - cluster[0].declare_queue("test-queue") - sender = NumberedSender(cluster[1], 1000) # Max queue depth - receiver = NumberedReceiver(cluster[2], sender) - receiver.start() - sender.start() - - # Kill original brokers, start new ones for the duration. - endtime = time.time() + self.duration() - i = 0 - while time.time() < endtime: - cluster[i].kill() - i += 1 - b = cluster.start(expect=EXPECT_EXIT_FAIL) - ErrorGenerator(b) - time.sleep(5) - sender.stop() - receiver.stop() - for i in range(i, len(cluster)): cluster[i].kill() - - def test_management(self, args=[]): - """ - Stress test: Run management clients and other clients concurrently - while killing and restarting brokers. - """ - - class ClientLoop(StoppableThread): - """Run a client executable in a loop.""" - def __init__(self, broker, cmd): - StoppableThread.__init__(self) - self.broker=broker - self.cmd = cmd # Client command. - self.lock = Lock() - self.process = None # Client process. - self.start() - - def run(self): - try: - while True: - self.lock.acquire() - try: - if self.stopped: break - self.process = self.broker.test.popen( - self.cmd, expect=EXPECT_UNKNOWN) - finally: - self.lock.release() - try: - exit = self.process.wait() - except OSError, e: - # Process may already have been killed by self.stop() - break - except Exception, e: - self.process.unexpected( - "client of %s: %s"%(self.broker.name, e)) - self.lock.acquire() - try: - if self.stopped: break - if exit != 0: - self.process.unexpected( - "client of %s exit code %s"%(self.broker.name, exit)) - finally: - self.lock.release() - except Exception, e: - self.error = RethrownException("Error in ClientLoop.run") - - def stop(self): - """Stop the running client and wait for it to exit""" - self.lock.acquire() - try: - if self.stopped: return - self.stopped = True - if self.process: - try: self.process.kill() # Kill the client. - except OSError: pass # The client might not be running. - finally: self.lock.release() - StoppableThread.stop(self) - - # body of test_management() - - args += ["--mgmt-pub-interval", 1] - args += ["--log-enable=trace+:management"] - # Use store if present. - if BrokerTest.store_lib: args +=["--load-module", BrokerTest.store_lib] - cluster = self.cluster(3, args) - - clients = [] # Per-broker list of clients that only connect to one broker. - mclients = [] # Management clients that connect to every broker in the cluster. - - def start_clients(broker): - """Start ordinary clients for a broker.""" - cmds=[ - ["qpid-tool", "localhost:%s"%(broker.port())], - ["qpid-perftest", "--count=5000", "--durable=yes", - "--base-name", str(qpid.datatypes.uuid4()), "--port", broker.port()], - ["qpid-txtest", "--queue-base-name", "tx-%s"%str(qpid.datatypes.uuid4()), - "--port", broker.port()], - ["qpid-queue-stats", "-a", "localhost:%s" %(broker.port())], - ["testagent", "localhost", str(broker.port())] ] - clients.append([ClientLoop(broker, cmd) for cmd in cmds]) - - def start_mclients(broker): - """Start management clients that make multiple connections.""" - cmd = ["qpid-stat", "-b", "localhost:%s" %(broker.port())] - mclients.append(ClientLoop(broker, cmd)) - - endtime = time.time() + self.duration() - # For long duration, first run is a quarter of the duration. - runtime = max(5, self.duration() / 4.0) - alive = 0 # First live cluster member - for i in range(len(cluster)): start_clients(cluster[i]) - start_mclients(cluster[alive]) - - while time.time() < endtime: - time.sleep(runtime) - runtime = 5 # Remaining runs 5 seconds, frequent broker kills - for b in cluster[alive:]: b.ready() # Check if a broker crashed. - # Kill the first broker, expect the clients to fail. - b = cluster[alive] - b.expect = EXPECT_EXIT_FAIL - b.kill() - # Stop the brokers clients and all the mclients. - for c in clients[alive] + mclients: - try: c.stop() - except: pass # Ignore expected errors due to broker shutdown. - clients[alive] = [] - mclients = [] - # Start another broker and clients - alive += 1 - cluster.start() - start_clients(cluster[-1]) - start_mclients(cluster[alive]) - for c in chain(mclients, *clients): - c.stop() - # Verify that logs are consistent - cluster_test_logs.verify_logs() - - def test_management_qmf2(self): - self.test_management(args=["--mgmt-qmf2=yes"]) - - def test_connect_consistent(self): - args=["--mgmt-pub-interval=1","--log-enable=trace+:management"] - cluster = self.cluster(2, args=args) - end = time.time() + self.duration() - while (time.time() < end): # Get a management interval - for i in xrange(1000): cluster[0].connect().close() - cluster_test_logs.verify_logs() - - def test_flowlimit_failover(self): - """Test fail-over during continuous send-receive with flow control - active. - """ - - # Original cluster will all be killed so expect exit with failure - cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL) - #for b in cluster: ErrorGenerator(b) - - # create a queue with rather draconian flow control settings - ssn0 = cluster[0].connect().session() - s0 = ssn0.sender("test-queue; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':2000, 'qpid.flow_resume_count':100}}}}") - - receiver = NumberedReceiver(cluster[2]) - receiver.start() - senders = [NumberedSender(cluster[i]) for i in range(1,3)] - for s in senders: - s.start() - - # Kill original brokers, start new ones for the duration. - endtime = time.time() + self.duration(); - i = 0 - while time.time() < endtime: - cluster[i].kill() - i += 1 - b = cluster.start(expect=EXPECT_EXIT_FAIL) - #ErrorGenerator(b) - time.sleep(5) - #b = cluster[0] - #b.startQmf() - for s in senders: - s.stop() - receiver.stop() - for i in range(i, len(cluster)): cluster[i].kill() - - -class StoreTests(BrokerTest): - """ - Cluster tests that can only be run if there is a store available. - """ - def args(self): - assert BrokerTest.store_lib - return ["--load-module", BrokerTest.store_lib] - - def test_store_loaded(self): - """Ensure we are indeed loading a working store""" - broker = self.broker(self.args(), name="recoverme", expect=EXPECT_EXIT_FAIL) - m = Message("x", durable=True) - broker.send_message("q", m) - broker.kill() - broker = self.broker(self.args(), name="recoverme") - self.assertEqual("x", broker.get_message("q").content) - - def test_kill_restart(self): - """Verify we can kill/resetart a broker with store in a cluster""" - cluster = self.cluster(1, self.args()) - cluster.start("restartme", expect=EXPECT_EXIT_FAIL).kill() - - # Send a message, retrieve from the restarted broker - cluster[0].send_message("q", "x") - m = cluster.start("restartme").get_message("q") - self.assertEqual("x", m.content) - - def stop_cluster(self,broker): - """Clean shut-down of a cluster""" - self.assertEqual(0, qpid_cluster.main( - ["-kf", broker.host_port()])) - - def test_persistent_restart(self): - """Verify persistent cluster shutdown/restart scenarios""" - cluster = self.cluster(0, args=self.args() + ["--cluster-size=3"]) - a = cluster.start("a", expect=EXPECT_EXIT_OK, wait=False) - b = cluster.start("b", expect=EXPECT_EXIT_OK, wait=False) - c = cluster.start("c", expect=EXPECT_EXIT_FAIL, wait=True) - a.send_message("q", Message("1", durable=True)) - # Kill & restart one member. - c.kill() - self.assertEqual(a.get_message("q").content, "1") - a.send_message("q", Message("2", durable=True)) - c = cluster.start("c", expect=EXPECT_EXIT_OK) - self.assertEqual(c.get_message("q").content, "2") - # Shut down the entire cluster cleanly and bring it back up - a.send_message("q", Message("3", durable=True)) - self.stop_cluster(a) - a = cluster.start("a", wait=False) - b = cluster.start("b", wait=False) - c = cluster.start("c", wait=True) - self.assertEqual(a.get_message("q").content, "3") - - def test_persistent_partial_failure(self): - # Kill 2 members, shut down the last cleanly then restart - # Ensure we use the clean database - cluster = self.cluster(0, args=self.args() + ["--cluster-size=3"]) - a = cluster.start("a", expect=EXPECT_EXIT_FAIL, wait=False) - b = cluster.start("b", expect=EXPECT_EXIT_FAIL, wait=False) - c = cluster.start("c", expect=EXPECT_EXIT_OK, wait=True) - a.send_message("q", Message("4", durable=True)) - a.kill() - b.kill() - self.assertEqual(c.get_message("q").content, "4") - c.send_message("q", Message("clean", durable=True)) - self.stop_cluster(c) - a = cluster.start("a", wait=False) - b = cluster.start("b", wait=False) - c = cluster.start("c", wait=True) - self.assertEqual(a.get_message("q").content, "clean") - - def test_wrong_cluster_id(self): - # Start a cluster1 broker, then try to restart in cluster2 - cluster1 = self.cluster(0, args=self.args()) - a = cluster1.start("a", expect=EXPECT_EXIT_OK) - a.terminate() - cluster2 = self.cluster(1, args=self.args()) - try: - a = cluster2.start("a", expect=EXPECT_EXIT_FAIL) - a.ready() - self.fail("Expected exception") - except: pass - - def test_wrong_shutdown_id(self): - # Start 2 members and shut down. - cluster = self.cluster(0, args=self.args()+["--cluster-size=2"]) - a = cluster.start("a", expect=EXPECT_EXIT_OK, wait=False) - b = cluster.start("b", expect=EXPECT_EXIT_OK, wait=False) - self.stop_cluster(a) - self.assertEqual(a.wait(), 0) - self.assertEqual(b.wait(), 0) - - # Restart with a different member and shut down. - a = cluster.start("a", expect=EXPECT_EXIT_OK, wait=False) - c = cluster.start("c", expect=EXPECT_EXIT_OK, wait=False) - self.stop_cluster(a) - self.assertEqual(a.wait(), 0) - self.assertEqual(c.wait(), 0) - # Mix members from both shutdown events, they should fail - # TODO aconway 2010-03-11: can't predict the exit status of these - # as it depends on the order of delivery of initial-status messages. - # See comment at top of this file. - a = cluster.start("a", expect=EXPECT_UNKNOWN, wait=False) - b = cluster.start("b", expect=EXPECT_UNKNOWN, wait=False) - self.assertRaises(Exception, lambda: a.ready()) - self.assertRaises(Exception, lambda: b.ready()) - - def test_solo_store_clean(self): - # A single node cluster should always leave a clean store. - cluster = self.cluster(0, self.args()) - a = cluster.start("a", expect=EXPECT_EXIT_FAIL) - a.send_message("q", Message("x", durable=True)) - a.kill() - a = cluster.start("a") - self.assertEqual(a.get_message("q").content, "x") - - def test_last_store_clean(self): - # Verify that only the last node in a cluster to shut down has - # a clean store. Start with cluster of 3, reduce to 1 then - # increase again to ensure that a node that was once alone but - # finally did not finish as the last node does not get a clean - # store. - cluster = self.cluster(0, self.args()) - a = cluster.start("a", expect=EXPECT_EXIT_FAIL) - self.assertEqual(a.store_state(), "clean") - b = cluster.start("b", expect=EXPECT_EXIT_FAIL) - c = cluster.start("c", expect=EXPECT_EXIT_FAIL) - self.assertEqual(b.store_state(), "dirty") - self.assertEqual(c.store_state(), "dirty") - retry(lambda: a.store_state() == "dirty") - - a.send_message("q", Message("x", durable=True)) - a.kill() - b.kill() # c is last man, will mark store clean - retry(lambda: c.store_state() == "clean") - a = cluster.start("a", expect=EXPECT_EXIT_FAIL) # c no longer last man - retry(lambda: c.store_state() == "dirty") - c.kill() # a is now last man - retry(lambda: a.store_state() == "clean") - a.kill() - self.assertEqual(a.store_state(), "clean") - self.assertEqual(b.store_state(), "dirty") - self.assertEqual(c.store_state(), "dirty") - - def test_restart_clean(self): - """Verify that we can re-start brokers one by one in a - persistent cluster after a clean oshutdown""" - cluster = self.cluster(0, self.args()) - a = cluster.start("a", expect=EXPECT_EXIT_OK) - b = cluster.start("b", expect=EXPECT_EXIT_OK) - c = cluster.start("c", expect=EXPECT_EXIT_OK) - a.send_message("q", Message("x", durable=True)) - self.stop_cluster(a) - a = cluster.start("a") - b = cluster.start("b") - c = cluster.start("c") - self.assertEqual(c.get_message("q").content, "x") - - def test_join_sub_size(self): - """Verify that after starting a cluster with cluster-size=N, - we can join new members even if size < N-1""" - cluster = self.cluster(0, self.args()+["--cluster-size=3"]) - a = cluster.start("a", wait=False, expect=EXPECT_EXIT_FAIL) - b = cluster.start("b", wait=False, expect=EXPECT_EXIT_FAIL) - c = cluster.start("c") - a.send_message("q", Message("x", durable=True)) - a.send_message("q", Message("y", durable=True)) - a.kill() - b.kill() - a = cluster.start("a") - self.assertEqual(c.get_message("q").content, "x") - b = cluster.start("b") - self.assertEqual(c.get_message("q").content, "y") diff --git a/cpp/src/tests/clustered_replication_test b/cpp/src/tests/clustered_replication_test deleted file mode 100755 index d6c72d9d1b..0000000000 --- a/cpp/src/tests/clustered_replication_test +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Test reliability of the replication feature in the face of link -# failures: -source ./test_env.sh - -trap stop_brokers INT EXIT - -fail() { - echo $1 - exit 1 -} - -stop_brokers() { - if [[ $PRIMARY1 ]] ; then - $QPIDD_EXEC --no-module-dir -q --port $PRIMARY1 - unset PRIMARY1 - fi - if [[ $PRIMARY2 ]] ; then - $QPIDD_EXEC --no-module-dir -q --port $PRIMARY2 - unset PRIMARY2 - fi - if [[ $DR1 ]] ; then - $QPIDD_EXEC --no-module-dir -q --port $DR1 - unset DR1 - fi - if [[ $DR2 ]] ; then - $QPIDD_EXEC --no-module-dir -q --port $DR2 - unset DR2 - fi -} - -if test -d $PYTHON_DIR; then - . $srcdir/ais_check - - #todo: these cluster names need to be unique to prevent clashes - PRIMARY_CLUSTER=PRIMARY_$(hostname)_$$ - DR_CLUSTER=DR_$(hostname)_$$ - - GENERAL_OPTS="--auth no --no-module-dir --no-data-dir --daemon --port 0 --log-to-stderr false" - PRIMARY_OPTS="--load-module $REPLICATING_LISTENER_LIB --create-replication-queue true --replication-queue REPLICATION_QUEUE --load-module $CLUSTER_LIB --cluster-name $PRIMARY_CLUSTER" - DR_OPTS="--load-module $REPLICATION_EXCHANGE_LIB --load-module $CLUSTER_LIB --cluster-name $DR_CLUSTER" - - rm -f repl*.tmp #cleanup any files left from previous run - - #start first node of primary cluster and set up test queue - echo Starting primary cluster - PRIMARY1=$(with_ais_group $QPIDD_EXEC $GENERAL_OPTS $PRIMARY_OPTS --log-to-file repl.primary.1.tmp) || fail "Could not start PRIMARY1" - $PYTHON_COMMANDS/qpid-config -a "localhost:$PRIMARY1" add queue test-queue --generate-queue-events 2 - $PYTHON_COMMANDS/qpid-config -a "localhost:$PRIMARY1" add queue control-queue --generate-queue-events 1 - - #send 10 messages, consume 5 of them - for i in `seq 1 10`; do echo Message$i; done | ./sender --port $PRIMARY1 - ./receiver --port $PRIMARY1 --messages 5 > /dev/null - - #add new node to primary cluster, testing correct transfer of state: - echo Adding node to primary cluster - PRIMARY2=$(with_ais_group $QPIDD_EXEC $GENERAL_OPTS $PRIMARY_OPTS --log-to-file repl.primary.2.tmp) || fail "Could not start PRIMARY2 " - - #start DR cluster, set up test queue there and establish replication bridge - echo Starting DR cluster - DR1=$(with_ais_group $QPIDD_EXEC $GENERAL_OPTS $DR_OPTS --log-to-file repl.dr.1.tmp) || fail "Could not start DR1" - DR2=$(with_ais_group $QPIDD_EXEC $GENERAL_OPTS $DR_OPTS --log-to-file repl.dr.2.tmp) || fail "Could not start DR2" - - $PYTHON_COMMANDS/qpid-config -a "localhost:$DR1" add queue test-queue - $PYTHON_COMMANDS/qpid-config -a "localhost:$DR1" add queue control-queue - $PYTHON_COMMANDS/qpid-config -a "localhost:$DR1" add exchange replication REPLICATION_EXCHANGE - $PYTHON_COMMANDS/qpid-route queue add localhost:$DR2 localhost:$PRIMARY2 REPLICATION_EXCHANGE REPLICATION_QUEUE || fail "Could not add route." - - #send more messages to primary - for i in `seq 11 20`; do echo Message$i; done | ./sender --port $PRIMARY1 --send-eos 1 - - #wait for replication events to all be processed: - echo Waiting for replication to complete - echo Done | ./sender --port $PRIMARY1 --routing-key control-queue --send-eos 1 - ./receiver --queue control-queue --port $DR1 > /dev/null - - #verify contents of test queue on dr cluster: - echo Verifying... - ./receiver --port $DR2 > repl.out.tmp - for i in `seq 6 20`; do echo Message$i; done | diff repl.out.tmp - || FAIL=1 - - if [[ $FAIL ]]; then - echo Clustered replication test failed: expectations not met! - exit 1 - else - echo Clustered replication test passed - rm -f repl*.tmp - fi - -fi diff --git a/cpp/src/tests/config.null b/cpp/src/tests/config.null deleted file mode 100644 index 565c7da435..0000000000 --- a/cpp/src/tests/config.null +++ /dev/null @@ -1 +0,0 @@ -# empty config diff --git a/cpp/src/tests/consume.cpp b/cpp/src/tests/consume.cpp deleted file mode 100644 index 69110d151f..0000000000 --- a/cpp/src/tests/consume.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <algorithm> -#include <iostream> -#include <memory> -#include <sstream> -#include <vector> - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using namespace std; - -namespace qpid { -namespace tests { - -typedef vector<string> StringSet; - -struct Args : public qpid::TestOptions { - uint count; - uint ack; - string queue; - bool declare; - bool summary; - bool print; - bool durable; - - Args() : count(1000), ack(0), queue("publish-consume"), - declare(false), summary(false), print(false) - { - addOptions() - ("count", optValue(count, "N"), "number of messages to publish") - ("ack-frequency", optValue(ack, "N"), "ack every N messages (0 means use no-ack mode)") - ("queue", optValue(queue, "<queue name>"), "queue to consume from") - ("declare", optValue(declare), "declare the queue") - ("durable", optValue(durable), "declare the queue durable, use with declare") - ("print-data", optValue(print), "Print the recieved data at info level") - ("s,summary", optValue(summary), "Print undecorated rate."); - } -}; - -Args opts; - -struct Client -{ - Connection connection; - Session session; - - Client() - { - opts.open(connection); - session = connection.newSession(); - } - - void consume() - { - if (opts.declare) - session.queueDeclare(arg::queue=opts.queue, arg::durable=opts.durable); - SubscriptionManager subs(session); - LocalQueue lq; - SubscriptionSettings settings; - settings.acceptMode = opts.ack > 0 ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE; - settings.flowControl = FlowControl(opts.count, SubscriptionManager::UNLIMITED,false); - Subscription sub = subs.subscribe(lq, opts.queue, settings); - Message msg; - AbsTime begin=now(); - for (size_t i = 0; i < opts.count; ++i) { - msg=lq.pop(); - QPID_LOG(info, "Received: " << msg.getMessageProperties().getCorrelationId()); - if (opts.print) QPID_LOG(info, "Data: " << msg.getData()); - } - if (opts.ack != 0) - sub.accept(sub.getUnaccepted()); // Cumulative ack for final batch. - AbsTime end=now(); - double secs(double(Duration(begin,end))/TIME_SEC); - if (opts.summary) cout << opts.count/secs << endl; - else cout << "Time: " << secs << "s Rate: " << opts.count/secs << endl; - } - - ~Client() - { - try{ - session.close(); - connection.close(); - } catch(const exception& e) { - cout << e.what() << endl; - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - Client client; - client.consume(); - return 0; - } catch(const exception& e) { - cout << e.what() << endl; - } - return 1; -} diff --git a/cpp/src/tests/datagen.cpp b/cpp/src/tests/datagen.cpp deleted file mode 100644 index acbc07d63c..0000000000 --- a/cpp/src/tests/datagen.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <exception> -#include <iostream> -#include <stdlib.h> -#include <time.h> -#include "qpid/Options.h" - -namespace qpid { -namespace tests { - -struct Args : public qpid::Options -{ - uint count; - uint minSize; - uint maxSize; - uint minChar; - uint maxChar; - bool help; - - Args() : qpid::Options("Random data generator"), - count(1), minSize(8), maxSize(4096), - minChar(32), maxChar(126),//safely printable ascii chars - help(false) - { - addOptions() - ("count", qpid::optValue(count, "N"), "number of data strings to generate") - ("min-size", qpid::optValue(minSize, "N"), "minimum size of data string") - ("max-size", qpid::optValue(maxSize, "N"), "maximum size of data string") - ("min-char", qpid::optValue(minChar, "N"), "minimum char value used in data string") - ("max-char", qpid::optValue(maxChar, "N"), "maximum char value used in data string") - ("help", qpid::optValue(help), "print this usage statement"); - } - - bool parse(int argc, char** argv) { - try { - qpid::Options::parse(argc, argv); - if (maxSize < minSize) throw qpid::Options::Exception("max-size must be greater than min-size"); - if (maxChar < minChar) throw qpid::Options::Exception("max-char must be greater than min-char"); - - if (help) { - std::cerr << *this << std::endl << std::endl; - } else { - return true; - } - } catch (const std::exception& e) { - std::cerr << *this << std::endl << std::endl << e.what() << std::endl; - } - return false; - } - -}; - -uint random(uint min, uint max) -{ - return (rand() % (max-min+1)) + min; -} - -std::string generateData(uint size, uint min, uint max) -{ - std::string data; - for (uint i = 0; i < size; i++) { - data += (char) random(min, max); - } - return data; -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - Args opts; - if (opts.parse(argc, argv)) { - srand(time(0)); - for (uint i = 0; i < opts.count; i++) { - std::cout << generateData(random(opts.minSize, opts.maxSize), opts.minChar, opts.maxChar) << std::endl; - } - return 0; - } else { - return 1; - } -} diff --git a/cpp/src/tests/declare_queues.cpp b/cpp/src/tests/declare_queues.cpp deleted file mode 100644 index bf85b9c04b..0000000000 --- a/cpp/src/tests/declare_queues.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/client/FailoverManager.h> -#include <qpid/client/Session.h> -#include <qpid/sys/Time.h> -#include <qpid/Exception.h> - -#include <cstdlib> -#include <iostream> -#include <sstream> - -using namespace qpid::client; - -using namespace std; - -int -main(int argc, char ** argv) -{ - ConnectionSettings settings; - if ( argc != 6 ) - { - cerr << "Usage: declare_queues host port durability queue_name_prefix n_queues\n"; - return 1; - } - - settings.host = argv[1]; - settings.port = atoi(argv[2]); - int durability = atoi(argv[3]); - char const * queue_name_prefix = argv[4]; - int n_queues = atoi(argv[5]); - - FailoverManager connection(settings); - - int max_fail = 13; - for ( int i = 0; i < n_queues; ++ i ) { - stringstream queue_name; - queue_name << queue_name_prefix << '_' << i; - - bool queue_created = false; - int failure_count; - - // Any non-transport failure is Bad. - try - { - while ( ! queue_created ) { - Session session = connection.connect().newSession(); - // TransportFailures aren't too bad -- they might happen because - // we are doing a cluster failover test. But if we get too many, - // we will still bug out. - failure_count = 0; - try { - if ( durability ) - session.queueDeclare(arg::queue=queue_name.str(), arg::durable=true); - else - session.queueDeclare(arg::queue=queue_name.str()); - queue_created = true; - cout << "declare_queues: Created queue " << queue_name.str() << endl; - } - catch ( const qpid::TransportFailure& ) { - if ( ++ failure_count >= max_fail ) { - cerr << "declare_queues failed: too many transport errors.\n"; - cerr << " host: " << settings.host - << " port: " << settings.port << endl; - return 1; - } - qpid::sys::sleep ( 1 ); - } - } - } - catch ( const exception & error) { - cerr << "declare_queues failed:" << error.what() << endl; - cerr << " host: " << settings.host - << " port: " << settings.port << endl; - return 1; - } - } -} - - - - - diff --git a/cpp/src/tests/dlclose_noop.c b/cpp/src/tests/dlclose_noop.c deleted file mode 100644 index b78cf486d8..0000000000 --- a/cpp/src/tests/dlclose_noop.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * Loaded via LD_PRELOAD this will turn dlclose into a no-op. - * - * Allows valgrind to generate useful reports from programs that - * dynamically unload libraries before exit, such as CppUnit's - * DllPlugInTester. - * - */ - -#include <stdio.h> -void* dlclose(void* handle) { return 0; } - diff --git a/cpp/src/tests/dynamic_log_level_test b/cpp/src/tests/dynamic_log_level_test deleted file mode 100755 index 990e56b1b1..0000000000 --- a/cpp/src/tests/dynamic_log_level_test +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run a simple test to verify dynamic log level changes -source ./test_env.sh -test -d $PYTHON_DIR || { echo "Skipping python tests, no python dir."; exit 0; } - -LOG_FILE=log_test.log -trap cleanup EXIT - -cleanup() { - test -n "$PORT" && $QPIDD_EXEC --no-module-dir --quit --port $PORT -} - -error() { - echo $*; - exit 1; -} - -rm -rf $LOG_FILE -PORT=$($QPIDD_EXEC --auth=no --no-module-dir --daemon --port=0 --log-to-file $LOG_FILE) || error "Could not start broker" - -echo Broker for log level test started on $PORT, pid is $($QPIDD_EXEC --no-module-dir --check --port $PORT) - -$srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='notice+' > /dev/null -$srcdir/qpid-ctrl -b localhost:$PORT echo sequence=1 body=HIDDEN > /dev/null -$srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='debug+:Broker' > /dev/null -$srcdir/qpid-ctrl -b localhost:$PORT echo sequence=2 body=VISIBLE > /dev/null -$srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='notice+' > /dev/null - -#check log includes debug statement for last echo, but not the first -if [[ $(grep echo $LOG_FILE | wc -l) -ne 1 ]]; then - cat $LOG_FILE - error "Log contents not as expected" -else - rm -rf $LOG_FILE - echo OK -fi - diff --git a/cpp/src/tests/echotest.cpp b/cpp/src/tests/echotest.cpp deleted file mode 100644 index 5114ab883d..0000000000 --- a/cpp/src/tests/echotest.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/client/Connection.h> -#include <qpid/client/SubscriptionManager.h> -#include <qpid/client/AsyncSession.h> -#include <qpid/client/Message.h> -#include <qpid/client/MessageListener.h> -#include <qpid/sys/Time.h> -#include <qpid/Options.h> - -#include <iostream> - -using namespace qpid::client; -using namespace qpid::framing; -using namespace qpid::sys; -using namespace std; - -namespace qpid { -namespace tests { - -struct Args : public qpid::Options, - public qpid::client::ConnectionSettings -{ - bool help; - uint count; - uint size; - bool summary; - - Args() : qpid::Options("Simple latency test optins"), help(false), count(20), size(0), summary() - { - using namespace qpid; - addOptions() - ("help", optValue(help), "Print this usage statement") - ("count", optValue(count, "N"), "Number of messages to send") - ("size", optValue(count, "N"), "Size of messages") - ("broker,b", optValue(host, "HOST"), "Broker host to connect to") - ("port,p", optValue(port, "PORT"), "Broker port to connect to") - ("username", optValue(username, "USER"), "user name for broker log in.") - ("password", optValue(password, "PASSWORD"), "password for broker log in.") - ("mechanism", optValue(mechanism, "MECH"), "SASL mechanism to use when authenticating.") - ("tcp-nodelay", optValue(tcpNoDelay), "Turn on tcp-nodelay") - ("s,summary", optValue(summary), "Print only average latency."); - } -}; - -uint64_t current_time() -{ - Duration t(EPOCH, now()); - return t; -} - -class Listener : public MessageListener -{ - private: - Session session; - SubscriptionManager subscriptions; - uint counter; - const uint limit; - std::string queue; - Message request; - double total, min, max; - bool summary; - - public: - Listener(Session& session, uint limit, bool summary); - void start(uint size); - void received(Message& message); -}; - -Listener::Listener(Session& s, uint l, bool summary_) : - session(s), subscriptions(s), counter(0), limit(l), - queue(session.getId().getName()), total(), - min(std::numeric_limits<double>::max()), max(), summary(summary_) -{} - -void Listener::start(uint size) -{ - session.queueDeclare(arg::queue=queue, arg::exclusive=true, arg::autoDelete=true); - request.getDeliveryProperties().setRoutingKey(queue); - subscriptions.subscribe(*this, queue, SubscriptionSettings(FlowControl::unlimited(), ACCEPT_MODE_NONE)); - - request.getDeliveryProperties().setTimestamp(current_time()); - if (size) request.setData(std::string(size, 'X')); - async(session).messageTransfer(arg::content=request); - subscriptions.run(); -} - -void Listener::received(Message& response) -{ - //extract timestamp and compute latency: - uint64_t sentAt = response.getDeliveryProperties().getTimestamp(); - uint64_t receivedAt = current_time(); - - double latency = ((double) (receivedAt - sentAt)) / TIME_MSEC; - if (!summary) cout << "Latency: " << latency << "ms" << endl; - min = std::min(latency, min); - max = std::max(latency, max); - total += latency; - - if (++counter < limit) { - request.getDeliveryProperties().setTimestamp(current_time()); - async(session).messageTransfer(arg::content=request); - } else { - subscriptions.cancel(queue); - if (summary) cout << min << "\t" << max << "\t" << total/limit << endl; - else cout << "min: " << min << " max: " << max << " average: " << total/limit << endl; - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - Args opts; - opts.parse(argc, argv); - - if (opts.help) { - std::cout << opts << std::endl; - return 0; - } - - Connection connection; - try { - connection.open(opts); - Session session = connection.newSession(); - Listener listener(session, opts.count, opts.summary); - listener.start(opts.size); - - connection.close(); - return 0; - } catch(const std::exception& error) { - std::cout << error.what() << std::endl; - } - return 1; -} - - diff --git a/cpp/src/tests/exception_test.cpp b/cpp/src/tests/exception_test.cpp deleted file mode 100644 index 3536ffddbe..0000000000 --- a/cpp/src/tests/exception_test.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "unit_test.h" -#include "test_tools.h" -#include "BrokerFixture.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/MessageListener.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Thread.h" -#include "qpid/framing/reply_exceptions.h" - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(exception_test) - -// FIXME aconway 2008-06-12: need to update our exception handling to -// 0-10 handling and extend this test to provoke all the exceptional -// conditions we know of and verify the correct exception is thrown. - -using namespace std; -using namespace qpid; -using namespace sys; -using namespace client; -using namespace framing; - -using qpid::broker::Broker; -using boost::bind; -using boost::function; - -template <class Ex> -struct Catcher : public Runnable { - function<void ()> f; - bool caught; - Thread thread; - - Catcher(function<void ()> f_) : f(f_), caught(false), thread(this) {} - ~Catcher() { join(); } - - void run() { - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f(); - } - catch(const Ex& e) { - caught=true; - BOOST_MESSAGE(string("Caught expected exception: ")+e.what()+"["+typeid(e).name()+"]"); - } - catch(const std::exception& e) { - BOOST_ERROR(string("Bad exception: ")+e.what()+"["+typeid(e).name()+"] expected: "+typeid(Ex).name()); - } - catch(...) { - BOOST_ERROR(string("Bad exception: unknown")); - } - } - - bool join() { - if (thread) { - thread.join(); - thread=Thread(); - } - return caught; - } -}; - -QPID_AUTO_TEST_CASE(TestSessionBusy) { - SessionFixture f; - try { - ScopedSuppressLogging sl; // Suppress messages for expected errors. - f.connection.newSession(f.session.getId().getName()); - BOOST_FAIL("Expected SessionBusyException for " << f.session.getId().getName()); - } catch (const SessionBusyException&) {} // FIXME aconway 2008-09-22: client is not throwing correct exception. -} - -QPID_AUTO_TEST_CASE(DisconnectedPop) { - ProxySessionFixture fix; - ProxyConnection c(fix.broker->getPort(Broker::TCP_TRANSPORT)); - fix.session.queueDeclare(arg::queue="q"); - fix.subs.subscribe(fix.lq, "q"); - Catcher<TransportFailure> pop(bind(&LocalQueue::pop, &fix.lq, sys::TIME_SEC)); - fix.connection.proxy.close(); - BOOST_CHECK(pop.join()); -} - -QPID_AUTO_TEST_CASE(DisconnectedListen) { - ProxySessionFixture fix; - struct NullListener : public MessageListener { - void received(Message&) { BOOST_FAIL("Unexpected message"); } - } l; - ProxyConnection c(fix.broker->getPort(Broker::TCP_TRANSPORT)); - fix.session.queueDeclare(arg::queue="q"); - fix.subs.subscribe(l, "q"); - - Catcher<TransportFailure> runner(bind(&SubscriptionManager::run, boost::ref(fix.subs))); - fix.connection.proxy.close(); - runner.join(); - BOOST_CHECK_THROW(fix.session.queueDeclare(arg::queue="x"), TransportFailure); -} - -QPID_AUTO_TEST_CASE(NoSuchQueueTest) { - ProxySessionFixture fix; - ScopedSuppressLogging sl; // Suppress messages for expected errors. - BOOST_CHECK_THROW(fix.subs.subscribe(fix.lq, "no such queue"), NotFoundException); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/failover_soak.cpp b/cpp/src/tests/failover_soak.cpp deleted file mode 100644 index c2ac36a757..0000000000 --- a/cpp/src/tests/failover_soak.cpp +++ /dev/null @@ -1,827 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/time.h> -#include <string.h> -#include <sys/types.h> -#include <signal.h> - -#include <string> -#include <iostream> -#include <sstream> -#include <vector> - -#include <boost/assign.hpp> - -#include "qpid/framing/Uuid.h" - -#include <ForkedBroker.h> -#include <qpid/client/Connection.h> - - - - - -using namespace std; -using boost::assign::list_of; -using namespace qpid::framing; -using namespace qpid::client; - - -namespace qpid { -namespace tests { - -vector<pid_t> pids; - -typedef vector<ForkedBroker *> brokerVector; - -typedef enum -{ - NO_STATUS, - RUNNING, - COMPLETED -} -childStatus; - - -typedef enum -{ - NO_TYPE, - DECLARING_CLIENT, - SENDING_CLIENT, - RECEIVING_CLIENT -} -childType; - - -ostream& operator<< ( ostream& os, const childType& ct ) { - switch ( ct ) { - case DECLARING_CLIENT: os << "Declaring Client"; break; - case SENDING_CLIENT: os << "Sending Client"; break; - case RECEIVING_CLIENT: os << "Receiving Client"; break; - default: os << "No Client"; break; - } - - return os; -} - - - - -struct child -{ - child ( string & name, pid_t pid, childType type ) - : name(name), pid(pid), retval(-999), status(RUNNING), type(type) - { - gettimeofday ( & startTime, 0 ); - } - - - void - done ( int _retval ) - { - retval = _retval; - status = COMPLETED; - gettimeofday ( & stopTime, 0 ); - } - - - void - setType ( childType t ) - { - type = t; - } - - - string name; - pid_t pid; - int retval; - childStatus status; - childType type; - struct timeval startTime, - stopTime; -}; - - - - -struct children : public vector<child *> -{ - - void - add ( string & name, pid_t pid, childType type ) - { - push_back ( new child ( name, pid, type ) ); - } - - - child * - get ( pid_t pid ) - { - vector<child *>::iterator i; - for ( i = begin(); i != end(); ++ i ) - if ( pid == (*i)->pid ) - return *i; - - return 0; - } - - - void - exited ( pid_t pid, int retval ) - { - child * kid = get ( pid ); - if(! kid) - { - if ( verbosity > 1 ) - { - cerr << "children::exited warning: Can't find child with pid " - << pid - << endl; - } - return; - } - - kid->done ( retval ); - } - - - int - unfinished ( ) - { - int count = 0; - - vector<child *>::iterator i; - for ( i = begin(); i != end(); ++ i ) - if ( COMPLETED != (*i)->status ) - ++ count; - - return count; - } - - - int - checkChildren ( ) - { - for ( unsigned int i = 0; i < pids.size(); ++ i ) - { - int pid = pids[i]; - int returned_pid; - int status; - - child * kid = get ( pid ); - - if ( kid->status != COMPLETED ) - { - returned_pid = waitpid ( pid, &status, WNOHANG ); - - if ( returned_pid == pid ) - { - int exit_status = WEXITSTATUS(status); - exited ( pid, exit_status ); - if ( exit_status ) // this is a child error. - return exit_status; - } - } - } - - return 0; - } - - - void - killEverybody ( ) - { - vector<child *>::iterator i; - for ( i = begin(); i != end(); ++ i ) - kill ( (*i)->pid, 9 ); - } - - - - void - print ( ) - { - cout << "--- status of all children --------------\n"; - vector<child *>::iterator i; - for ( i = begin(); i != end(); ++ i ) - cout << "child: " << (*i)->name - << " status: " << (*i)->status - << endl; - cout << "\n\n\n\n"; - } - - int verbosity; -}; - - -children allMyChildren; - - -void -childExit ( int ) -{ - int childReturnCode; - pid_t pid = waitpid ( 0, & childReturnCode, WNOHANG); - - if ( pid > 0 ) - allMyChildren.exited ( pid, childReturnCode ); -} - - - -int -mrand ( int maxDesiredVal ) { - double zeroToOne = (double) rand() / (double) RAND_MAX; - return (int) (zeroToOne * (double) maxDesiredVal); -} - - - -int -mrand ( int minDesiredVal, int maxDesiredVal ) { - int interval = maxDesiredVal - minDesiredVal; - return minDesiredVal + mrand ( interval ); -} - - - -void -makeClusterName ( string & s ) { - stringstream ss; - ss << "soakTestCluster_" << Uuid(true).str(); - s = ss.str(); -} - - - - - -void -printBrokers ( brokerVector & brokers ) -{ - cout << "Broker List ------------ size: " << brokers.size() << "\n"; - for ( brokerVector::iterator i = brokers.begin(); i != brokers.end(); ++ i) { - cout << "pid: " - << (*i)->getPID() - << " port: " - << (*i)->getPort() - << endl; - } - cout << "end Broker List ------------\n"; -} - - - - -ForkedBroker * newbie = 0; -int newbie_port = 0; - - - -bool -wait_for_newbie ( ) -{ - if ( ! newbie ) - return true; - - try - { - Connection connection; - connection.open ( "127.0.0.1", newbie_port ); - connection.close(); - newbie = 0; // He's no newbie anymore! - return true; - } - catch ( const std::exception& error ) - { - std::cerr << "wait_for_newbie error: " - << error.what() - << endl; - return false; - } -} - -bool endsWith(const char* str, const char* suffix) { - return (strlen(suffix) < strlen(str) && 0 == strcmp(str+strlen(str)-strlen(suffix), suffix)); -} - - -void -startNewBroker ( brokerVector & brokers, - char const * moduleOrDir, - string const clusterName, - int verbosity, - int durable ) -{ - static int brokerId = 0; - stringstream path, prefix; - prefix << "soak-" << brokerId; - std::vector<std::string> argv = list_of<string> - ("qpidd") - ("--cluster-name")(clusterName) - ("--auth=no") - ("--mgmt-enable=no") - ("--log-prefix")(prefix.str()) - ("--log-to-file")(prefix.str()+".log") - ("--log-enable=info+") - ("--log-enable=debug+:cluster") - ("TMP_DATA_DIR"); - - if (endsWith(moduleOrDir, "cluster.so")) { - // Module path specified, load only that module. - argv.push_back(string("--load-module=")+moduleOrDir); - argv.push_back("--no-module-dir"); - if ( durable ) { - std::cerr << "failover_soak warning: durable arg hass no effect. Use \"dir\" option of \"moduleOrDir\".\n"; - } - } - else { - // Module directory specified, load all modules in dir. - argv.push_back(string("--module-dir=")+moduleOrDir); - } - - newbie = new ForkedBroker (argv); - newbie_port = newbie->getPort(); - ForkedBroker * broker = newbie; - - if ( verbosity > 0 ) - std::cerr << "new broker created: pid == " - << broker->getPID() - << " log-prefix == " - << "soak-" << brokerId - << endl; - brokers.push_back ( broker ); - - ++ brokerId; -} - - - - - -bool -killFrontBroker ( brokerVector & brokers, int verbosity ) -{ - cerr << "killFrontBroker: waiting for newbie sync...\n"; - if ( ! wait_for_newbie() ) - return false; - cerr << "killFrontBroker: newbie synced.\n"; - - if ( verbosity > 0 ) - cout << "killFrontBroker pid: " << brokers[0]->getPID() << " on port " << brokers[0]->getPort() << endl; - try { brokers[0]->kill(9); } - catch ( const exception& error ) { - if ( verbosity > 0 ) - { - cout << "error killing broker: " - << error.what() - << endl; - } - - return false; - } - delete brokers[0]; - brokers.erase ( brokers.begin() ); - return true; -} - - - - - -/* - * The optional delay is to avoid killing newbie brokers that have just - * been added and are still in the process of updating. This causes - * spurious, test-generated errors that scare everybody. - */ -void -killAllBrokers ( brokerVector & brokers, int delay ) -{ - if ( delay > 0 ) - { - std::cerr << "Killing all brokers after delay of " << delay << endl; - sleep ( delay ); - } - - for ( uint i = 0; i < brokers.size(); ++ i ) - try { brokers[i]->kill(9); } - catch ( const exception& error ) - { - std::cerr << "killAllBrokers Warning: exception during kill on broker " - << i - << " " - << error.what() - << endl; - } -} - - - - - -pid_t -runDeclareQueuesClient ( brokerVector brokers, - char const * host, - char const * path, - int verbosity, - int durable, - char const * queue_prefix, - int n_queues - ) -{ - string name("declareQueues"); - int port = brokers[0]->getPort ( ); - - if ( verbosity > 1 ) - cout << "startDeclareQueuesClient: host: " - << host - << " port: " - << port - << endl; - stringstream portSs; - portSs << port; - - vector<const char*> argv; - argv.push_back ( "declareQueues" ); - argv.push_back ( host ); - string portStr = portSs.str(); - argv.push_back ( portStr.c_str() ); - if ( durable ) - argv.push_back ( "1" ); - else - argv.push_back ( "0" ); - - argv.push_back ( queue_prefix ); - - char n_queues_str[20]; - sprintf ( n_queues_str, "%d", n_queues ); - argv.push_back ( n_queues_str ); - - argv.push_back ( 0 ); - pid_t pid = fork(); - - if ( ! pid ) { - execv ( path, const_cast<char * const *>(&argv[0]) ); - perror ( "error executing declareQueues: " ); - return 0; - } - - allMyChildren.add ( name, pid, DECLARING_CLIENT ); - return pid; -} - - - - - -pid_t -startReceivingClient ( brokerVector brokers, - char const * host, - char const * receiverPath, - char const * reportFrequency, - int verbosity, - char const * queue_name - ) -{ - string name("receiver"); - int port = brokers[0]->getPort ( ); - - if ( verbosity > 1 ) - cout << "startReceivingClient: port " << port << endl; - - // verbosity has to be > 1 to let clients talk. - int client_verbosity = (verbosity > 1 ) ? 1 : 0; - - char portStr[100]; - char verbosityStr[100]; - sprintf(portStr, "%d", port); - sprintf(verbosityStr, "%d", client_verbosity); - - - vector<const char*> argv; - argv.push_back ( "resumingReceiver" ); - argv.push_back ( host ); - argv.push_back ( portStr ); - argv.push_back ( reportFrequency ); - argv.push_back ( verbosityStr ); - argv.push_back ( queue_name ); - argv.push_back ( 0 ); - - pid_t pid = fork(); - pids.push_back ( pid ); - - if ( ! pid ) { - execv ( receiverPath, const_cast<char * const *>(&argv[0]) ); - perror ( "error executing receiver: " ); - return 0; - } - - allMyChildren.add ( name, pid, RECEIVING_CLIENT ); - return pid; -} - - - - - -pid_t -startSendingClient ( brokerVector brokers, - char const * host, - char const * senderPath, - char const * nMessages, - char const * reportFrequency, - int verbosity, - int durability, - char const * queue_name - ) -{ - string name("sender"); - int port = brokers[0]->getPort ( ); - - if ( verbosity > 1) - cout << "startSenderClient: port " << port << endl; - char portStr[100]; - char verbosityStr[100]; - // - // verbosity has to be > 1 to let clients talk. - int client_verbosity = (verbosity > 1 ) ? 1 : 0; - - sprintf ( portStr, "%d", port); - sprintf ( verbosityStr, "%d", client_verbosity); - - vector<const char*> argv; - argv.push_back ( "replayingSender" ); - argv.push_back ( host ); - argv.push_back ( portStr ); - argv.push_back ( nMessages ); - argv.push_back ( reportFrequency ); - argv.push_back ( verbosityStr ); - if ( durability ) - argv.push_back ( "1" ); - else - argv.push_back ( "0" ); - argv.push_back ( queue_name ); - argv.push_back ( 0 ); - - pid_t pid = fork(); - pids.push_back ( pid ); - - if ( ! pid ) { - execv ( senderPath, const_cast<char * const *>(&argv[0]) ); - perror ( "error executing sender: " ); - return 0; - } - - allMyChildren.add ( name, pid, SENDING_CLIENT ); - return pid; -} - - - -#define HUNKY_DORY 0 -#define BAD_ARGS 1 -#define CANT_FORK_DQ 2 -#define CANT_FORK_RECEIVER 3 -#define CANT_FORK_SENDER 4 -#define DQ_FAILED 5 -#define ERROR_ON_CHILD 6 -#define HANGING 7 -#define ERROR_KILLING_BROKER 8 - -}} // namespace qpid::tests - -using namespace qpid::tests; - -// If you want durability, use the "dir" option of "moduleOrDir" . -int -main ( int argc, char const ** argv ) -{ - int brokerKills = 0; - if ( argc != 11 ) { - cerr << "Usage: " - << argv[0] - << "moduleOrDir declareQueuesPath senderPath receiverPath nMessages reportFrequency verbosity durable n_queues n_brokers" - << endl; - cerr << "\tverbosity is an integer, durable is 0 or 1\n"; - return BAD_ARGS; - } - signal ( SIGCHLD, childExit ); - - int i = 1; - char const * moduleOrDir = argv[i++]; - char const * declareQueuesPath = argv[i++]; - char const * senderPath = argv[i++]; - char const * receiverPath = argv[i++]; - char const * nMessages = argv[i++]; - char const * reportFrequency = argv[i++]; - int verbosity = atoi(argv[i++]); - int durable = atoi(argv[i++]); - int n_queues = atoi(argv[i++]); - int n_brokers = atoi(argv[i++]); - - char const * host = "127.0.0.1"; - - allMyChildren.verbosity = verbosity; - - string clusterName; - - srand ( getpid() ); - - makeClusterName ( clusterName ); - - brokerVector brokers; - - if ( verbosity > 1 ) - cout << "Starting initial cluster...\n"; - - for ( int i = 0; i < n_brokers; ++ i ) { - startNewBroker ( brokers, - moduleOrDir, - clusterName, - verbosity, - durable ); - } - - - if ( verbosity > 0 ) - printBrokers ( brokers ); - - // Get prefix for each queue name. - stringstream queue_prefix; - queue_prefix << "failover_soak_" << getpid(); - string queue_prefix_str(queue_prefix.str()); - - // Run the declareQueues child. - int childStatus; - pid_t dqClientPid = - runDeclareQueuesClient ( brokers, - host, - declareQueuesPath, - verbosity, - durable, - queue_prefix_str.c_str(), - n_queues - ); - if ( -1 == dqClientPid ) { - cerr << "END_OF_TEST ERROR_START_DECLARE_1\n"; - return CANT_FORK_DQ; - } - - // Don't continue until declareQueues is finished. - pid_t retval = waitpid ( dqClientPid, & childStatus, 0); - if ( retval != dqClientPid) { - cerr << "END_OF_TEST ERROR_START_DECLARE_2\n"; - return DQ_FAILED; - } - allMyChildren.exited ( dqClientPid, childStatus ); - - - /* - Start one receiving and one sending client for each queue. - */ - for ( int i = 0; i < n_queues; ++ i ) { - - stringstream queue_name; - queue_name << queue_prefix.str() << '_' << i; - string queue_name_str(queue_name.str()); - - // Receiving client --------------------------- - pid_t receivingClientPid = - startReceivingClient ( brokers, - host, - receiverPath, - reportFrequency, - verbosity, - queue_name_str.c_str() ); - if ( -1 == receivingClientPid ) { - cerr << "END_OF_TEST ERROR_START_RECEIVER\n"; - return CANT_FORK_RECEIVER; - } - - - // Sending client --------------------------- - pid_t sendingClientPid = - startSendingClient ( brokers, - host, - senderPath, - nMessages, - reportFrequency, - verbosity, - durable, - queue_name_str.c_str() ); - if ( -1 == sendingClientPid ) { - cerr << "END_OF_TEST ERROR_START_SENDER\n"; - return CANT_FORK_SENDER; - } - } - - - int minSleep = 2, - maxSleep = 6; - - int totalBrokers = n_brokers; - - int loop = 0; - - while ( 1 ) - { - ++ loop; - - /* - if ( verbosity > 1 ) - std::cerr << "------- loop " << loop << " --------\n"; - - if ( verbosity > 0 ) - cout << totalBrokers << " brokers have been added to the cluster.\n\n\n"; - */ - - // Sleep for a while. ------------------------- - int sleepyTime = mrand ( minSleep, maxSleep ); - sleep ( sleepyTime ); - - int bullet = mrand ( 100 ); - if ( bullet >= 95 ) - { - fprintf ( stderr, "Killing oldest broker...\n" ); - - // Kill the oldest broker. -------------------------- - if ( ! killFrontBroker ( brokers, verbosity ) ) - { - allMyChildren.killEverybody(); - killAllBrokers ( brokers, 5 ); - std::cerr << "END_OF_TEST ERROR_BROKER\n"; - return ERROR_KILLING_BROKER; - } - ++ brokerKills; - - // Start a new broker. -------------------------- - if ( verbosity > 0 ) - cout << "Starting new broker.\n\n"; - - startNewBroker ( brokers, - moduleOrDir, - clusterName, - verbosity, - durable ); - ++ totalBrokers; - printBrokers ( brokers ); - cerr << brokerKills << " brokers have been killed.\n\n\n"; - } - - int retval = allMyChildren.checkChildren(); - if ( retval ) - { - std::cerr << "END_OF_TEST ERROR_CLIENT\n"; - allMyChildren.killEverybody(); - killAllBrokers ( brokers, 5 ); - return ERROR_ON_CHILD; - } - - // If all children have exited, quit. - int unfinished = allMyChildren.unfinished(); - if ( unfinished == 0 ) { - killAllBrokers ( brokers, 5 ); - - if ( verbosity > 1 ) - cout << "failoverSoak: all children have exited.\n"; - - std::cerr << "END_OF_TEST SUCCESSFUL\n"; - return HUNKY_DORY; - } - - } - - allMyChildren.killEverybody(); - killAllBrokers ( brokers, 5 ); - - std::cerr << "END_OF_TEST SUCCESSFUL\n"; - - return HUNKY_DORY; -} - - - diff --git a/cpp/src/tests/fanout_perftest b/cpp/src/tests/fanout_perftest deleted file mode 100755 index d8a7661f49..0000000000 --- a/cpp/src/tests/fanout_perftest +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -exec `dirname $0`/run_perftest 10000 --mode fanout --npubs 16 --nsubs 16 --size 64 diff --git a/cpp/src/tests/federated_cluster_test b/cpp/src/tests/federated_cluster_test deleted file mode 100755 index 70bec5e703..0000000000 --- a/cpp/src/tests/federated_cluster_test +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Test reliability of the replication feature in the face of link -# failures: -srcdir=`dirname $0` -source ./test_env.sh - -trap stop_brokers EXIT - -fail() { - echo $1 - exit 1 -} - -stop_brokers() { - if [[ $BROKER_A ]] ; then - ../qpidd --no-module-dir -q --port $BROKER_A - unset BROKER_A - fi - if [[ $NODE_1 ]] ; then - ../qpidd --no-module-dir -q --port $NODE_1 - unset NODE_1 - fi - if [[ $NODE_2 ]] ; then - ../qpidd --no-module-dir -q --port $NODE_2 - unset NODE_2 - fi - if [ -f cluster.ports ]; then - rm cluster.ports - fi -} - -start_brokers() { - #start single node... - BROKER_A=`../qpidd --daemon --port 0 --no-data-dir --no-module-dir --auth no --log-enable info+` || fail "BROKER_A failed to start" - - #...and start cluster - $srcdir/start_cluster 2 || fail "Could not start cluster" - NODE_1=$(head -1 cluster.ports) - NODE_2=$(tail -1 cluster.ports) - test -n "$NODE_1" || fail "NODE_1 failed to start" - test -n "$NODE_2" || fail "NODE_2 failed to start" -} - -setup() { - #create exchange on both cluster and single broker - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add exchange direct test-exchange - $PYTHON_COMMANDS/qpid-config -a "localhost:$NODE_1" add exchange direct test-exchange - - #create dynamic routes for test exchange - $PYTHON_COMMANDS/qpid-route dynamic add "localhost:$NODE_2" "localhost:$BROKER_A" test-exchange - $PYTHON_COMMANDS/qpid-route dynamic add "localhost:$BROKER_A" "localhost:$NODE_2" test-exchange - - #create test queue on cluster and bind it to the test exchange - $PYTHON_COMMANDS/qpid-config -a "localhost:$NODE_1" add queue test-queue - $PYTHON_COMMANDS/qpid-config -a "localhost:$NODE_1" bind test-exchange test-queue to-cluster - - #create test queue on single broker and bind it to the test exchange - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue test-queue - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" bind test-exchange test-queue from-cluster -} - -run_test_pull_to_cluster_two_consumers() { - #start consumers on each of the two nodes of the cluster - ./receiver --port $NODE_1 --queue test-queue --credit-window 1 > fed1.out.tmp & - ./receiver --port $NODE_2 --queue test-queue --credit-window 1 > fed2.out.tmp & - - #send stream of messages to test exchange on single broker - for i in `seq 1 1000`; do echo Message $i >> fed.in.tmp; done - ./sender --port $BROKER_A --exchange test-exchange --routing-key to-cluster --send-eos 2 < fed.in.tmp - - #combine output of the two consumers, sort it and compare with the expected stream - wait - sort -g -k 2 fed1.out.tmp fed2.out.tmp > fed.out.tmp - diff fed.in.tmp fed.out.tmp || fail "federated link to cluster failed: expectations not met!" - - rm -f fed*.tmp #cleanup -} - -run_test_pull_to_cluster() { - #send stream of messages to test exchange on single broker - for i in `seq 1 1000`; do echo Message $i >> fed.in.tmp; done - ./sender --port $BROKER_A --exchange test-exchange --routing-key to-cluster --send-eos 1 < fed.in.tmp - - #consume from remaining node of the cluster - ./receiver --port $NODE_2 --queue test-queue > fed.out.tmp - - #verify all messages are received - diff fed.in.tmp fed.out.tmp || fail "federated link to cluster failed: expectations not met!" - - rm -f fed*.tmp #cleanup -} - -run_test_pull_from_cluster() { - #start consumer on single broker - ./receiver --port $BROKER_A --queue test-queue --credit-window 1 > fed.out.tmp & - - #send stream of messages to test exchange on cluster - for i in `seq 1 1000`; do echo Message $i >> fed.in.tmp; done - ./sender --port $NODE_2 --exchange test-exchange --routing-key from-cluster --send-eos 1 < fed.in.tmp - - #verify all messages are received - wait - diff fed.in.tmp fed.out.tmp || fail "federated link from cluster failed: expectations not met!" - - rm -f fed*.tmp #cleanup -} - - -if test -d ${PYTHON_DIR}; then - . $srcdir/ais_check - - rm -f fed*.tmp #cleanup any files left from previous run - start_brokers - echo "brokers started" - setup - echo "setup completed" - run_test_pull_to_cluster_two_consumers - echo "federated link to cluster verified" - run_test_pull_from_cluster - echo "federated link from cluster verified" - if [[ $TEST_NODE_FAILURE ]] ; then - #kill first cluster node and retest - kill -9 $(../qpidd --check --port $NODE_1) && unset NODE_1 - echo "killed first cluster node; waiting for links to re-establish themselves..." - sleep 5 - echo "retesting..." - run_test_pull_to_cluster - echo "federated link to cluster verified" - run_test_pull_from_cluster - echo "federated link from cluster verified" - fi -fi diff --git a/cpp/src/tests/federated_cluster_test_with_node_failure b/cpp/src/tests/federated_cluster_test_with_node_failure deleted file mode 100755 index f144a676de..0000000000 --- a/cpp/src/tests/federated_cluster_test_with_node_failure +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -srcdir=`dirname $0` -TEST_NODE_FAILURE=1 $srcdir/federated_cluster_test diff --git a/cpp/src/tests/federated_topic_test b/cpp/src/tests/federated_topic_test deleted file mode 100755 index b1063c7e8c..0000000000 --- a/cpp/src/tests/federated_topic_test +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the topic test on a federated setup - -# Clean up old log files -rm -f subscriber_*.log - -# Defaults values -SUBSCRIBERS=2 -MESSAGES=1000 -BATCHES=1 -VERBOSE=1 - -while getopts "s:m:b:" opt ; do - case $opt in - s) SUBSCRIBERS=$OPTARG ;; - m) MESSAGES=$OPTARG ;; - b) BATCHES=$OPTARG ;; - ?) - echo "Usage: %0 [-s <subscribers>] [-m <messages.] [-b <batches>]" - exit 1 - ;; - esac -done - -MY_DIR=$(dirname $(which $0)) -source ./test_env.sh - -trap stop_brokers EXIT - -start_broker() { - ${MY_DIR}/../qpidd --daemon --port 0 --no-module-dir --no-data-dir --auth no > qpidd.port -} - -start_brokers() { - start_broker - PORT_A=`cat qpidd.port` - start_broker - PORT_B=`cat qpidd.port` - start_broker - PORT_C=`cat qpidd.port` -} - -stop_brokers() { - for p in $PORT_A $PORT_B $PORT_C; do - $QPIDD_EXEC --no-module-dir -q --port $p - done -} - -subscribe() { - #which broker should we connect to? - if (( $1 % 2 )); then - MY_PORT=$PORT_C; - else - MY_PORT=$PORT_A; - fi - - echo Subscriber $1 connecting on $MY_PORT - LOG="subscriber_$1.log" - ${MY_DIR}/topic_listener -p $MY_PORT > $LOG 2>&1 && rm -f $LOG -} - -publish() { - ${MY_DIR}/topic_publisher --messages $MESSAGES --batches $BATCHES --subscribers $SUBSCRIBERS -p $PORT_A -} - -setup_routes() { - BROKER_A="localhost:$PORT_A" - BROKER_B="localhost:$PORT_B" - BROKER_C="localhost:$PORT_C" - if (($VERBOSE)); then - echo "Establishing routes for topic..." - fi - $PYTHON_COMMANDS/qpid-route route add $BROKER_B $BROKER_A amq.topic topic_control B B - $PYTHON_COMMANDS/qpid-route route add $BROKER_C $BROKER_B amq.topic topic_control C C - if (($VERBOSE)); then - echo "linked A->B->C" - fi - $PYTHON_COMMANDS/qpid-route route add $BROKER_B $BROKER_C amq.topic topic_control B B - $PYTHON_COMMANDS/qpid-route route add $BROKER_A $BROKER_B amq.topic topic_control A A - if (($VERBOSE)); then - echo "linked C->B->A" - echo "Establishing routes for response queue..." - fi - - $PYTHON_COMMANDS/qpid-route route add $BROKER_B $BROKER_C amq.direct response B B - $PYTHON_COMMANDS/qpid-route route add $BROKER_A $BROKER_B amq.direct response A A - if (($VERBOSE)); then - echo "linked C->B->A" - for b in $BROKER_A $BROKER_B $BROKER_C; do - echo "Routes for $b" - $PYTHON_COMMANDS/qpid-route route list $b - done - fi -} - -if test -d ${PYTHON_DIR} ; then - start_brokers - if (($VERBOSE)); then - echo "Running federated topic test against brokers on ports $PORT_A $PORT_B $PORT_C" - fi - - for ((i=$SUBSCRIBERS ; i--; )); do - subscribe $i & - done - - setup_routes - - publish || exit 1 -fi diff --git a/cpp/src/tests/federation.py b/cpp/src/tests/federation.py deleted file mode 100755 index 201b06a4a2..0000000000 --- a/cpp/src/tests/federation.py +++ /dev/null @@ -1,2091 +0,0 @@ -#!/usr/bin/env python -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import sys -from qpid.testlib import TestBase010 -from qpid.datatypes import Message -from qpid.queue import Empty -from qpid.util import URL -from time import sleep, time - - -class _FedBroker(object): - """ - A proxy object for a remote broker. Contains connection and management - state. - """ - def __init__(self, host, port, - conn=None, session=None, qmf_broker=None): - self.host = host - self.port = port - self.url = "%s:%d" % (host, port) - self.client_conn = None - self.client_session = None - self.qmf_broker = None - self.qmf_object = None - if conn is not None: - self.client_conn = conn - if session is not None: - self.client_session = session - if qmf_broker is not None: - self.qmf_broker = qmf_broker - - -class FederationTests(TestBase010): - - def remote_host(self): - return self.defines.get("remote-host", "localhost") - - def remote_port(self): - return int(self.defines["remote-port"]) - - def verify_cleanup(self): - attempts = 0 - total = len(self.qmf.getObjects(_class="bridge")) + len(self.qmf.getObjects(_class="link")) - while total > 0: - attempts += 1 - if attempts >= 10: - self.fail("Bridges and links didn't clean up") - return - sleep(1) - total = len(self.qmf.getObjects(_class="bridge")) + len(self.qmf.getObjects(_class="link")) - - def _setup_brokers(self): - ports = [self.remote_port()] - extra = self.defines.get("extra-brokers") - if extra: - for p in extra.split(): - ports.append(int(p)) - - # broker[0] has already been set up. - self._brokers = [_FedBroker(self.broker.host, - self.broker.port, - self.conn, - self.session, - self.qmf_broker)] - self._brokers[0].qmf_object = self.qmf.getObjects(_class="broker")[0] - - # setup remaining brokers - for _p in ports: - _b = _FedBroker(self.remote_host(), _p) - _b.client_conn = self.connect(host=self.remote_host(), port=_p) - _b.client_session = _b.client_conn.session("Fed_client_session_" + str(_p)) - _b.qmf_broker = self.qmf.addBroker(_b.url) - for _bo in self.qmf.getObjects(_class="broker"): - if _bo.getBroker().getUrl() == _b.qmf_broker.getUrl(): - _b.qmf_object = _bo - break - self._brokers.append(_b) - - def _teardown_brokers(self): - """ Un-does _setup_brokers() - """ - # broker[0] is configured at test setup, so it must remain configured - for _b in self._brokers[1:]: - self.qmf.delBroker(_b.qmf_broker) - if not _b.client_session.error(): - _b.client_session.close(timeout=10) - _b.client_conn.close(timeout=10) - - - def test_bridge_create_and_close(self): - self.startQmf(); - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "amq.direct", "amq.direct", "my-key", "", "", False, False, False, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - result = bridge.close() - self.assertEqual(result.status, 0) - - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_pull_from_exchange(self): - session = self.session - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "amq.direct", "amq.fanout", "my-key", "", "", False, False, False, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - - #setup queue to receive messages from local broker - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - sleep(6) - - #send messages to remote broker and confirm it is routed to local broker - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_pull_from_exchange") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="my-key") - r_session.message_transfer(destination="amq.direct", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_push_to_exchange(self): - session = self.session - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "amq.direct", "amq.fanout", "my-key", "", "", False, True, False, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - - #setup queue to receive messages from remote broker - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_push_to_exchange") - r_session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - r_session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(session=r_session, queue="fed1", destination="f1") - queue = r_session.incoming("f1") - sleep(6) - - #send messages to local broker and confirm it is routed to remote broker - for i in range(1, 11): - dp = session.delivery_properties(routing_key="my-key") - session.message_transfer(destination="amq.direct", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_pull_from_queue(self): - session = self.session - - #setup queue on remote broker and add some messages - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_pull_from_queue") - r_session.queue_declare(queue="my-bridge-queue", auto_delete=True) - for i in range(1, 6): - dp = r_session.delivery_properties(routing_key="my-bridge-queue") - r_session.message_transfer(message=Message(dp, "Message %d" % i)) - - #setup queue to receive messages from local broker - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "my-bridge-queue", "amq.fanout", "my-key", "", "", True, False, False, 1) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - sleep(3) - - #add some more messages (i.e. after bridge was created) - for i in range(6, 11): - dp = r_session.delivery_properties(routing_key="my-bridge-queue") - r_session.message_transfer(message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - try: - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - except Empty: - self.fail("Failed to find expected message containing 'Message %d'" % i) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_tracing_automatic(self): - remoteUrl = "%s:%d" % (self.remote_host(), self.remote_port()) - self.startQmf() - l_broker = self.qmf_broker - r_broker = self.qmf.addBroker(remoteUrl) - - l_brokerObj = self.qmf.getObjects(_class="broker", _broker=l_broker)[0] - r_brokerObj = self.qmf.getObjects(_class="broker", _broker=r_broker)[0] - - l_res = l_brokerObj.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - r_res = r_brokerObj.connect(self.broker.host, self.broker.port, False, "PLAIN", "guest", "guest", "tcp") - - self.assertEqual(l_res.status, 0) - self.assertEqual(r_res.status, 0) - - l_link = self.qmf.getObjects(_class="link", _broker=l_broker)[0] - r_link = self.qmf.getObjects(_class="link", _broker=r_broker)[0] - - l_res = l_link.bridge(False, "amq.direct", "amq.direct", "key", "", "", False, False, False, 0) - r_res = r_link.bridge(False, "amq.direct", "amq.direct", "key", "", "", False, False, False, 0) - - self.assertEqual(l_res.status, 0) - self.assertEqual(r_res.status, 0) - - count = 0 - while l_link.state != "Operational" or r_link.state != "Operational": - count += 1 - if count > 10: - self.fail("Fed links didn't become operational after 10 seconds") - sleep(1) - l_link = self.qmf.getObjects(_class="link", _broker=l_broker)[0] - r_link = self.qmf.getObjects(_class="link", _broker=r_broker)[0] - sleep(3) - - #setup queue to receive messages from local broker - session = self.session - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.direct", binding_key="key") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - #setup queue on remote broker and add some messages - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_trace") - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="key") - r_session.message_transfer(destination="amq.direct", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - try: - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - except Empty: - self.fail("Failed to find expected message containing 'Message %d'" % i) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - def test_tracing(self): - session = self.session - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "amq.direct", "amq.fanout", "my-key", "my-bridge-id", - "exclude-me,also-exclude-me", False, False, False, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - - #setup queue to receive messages from local broker - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="amq.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - sleep(6) - - #send messages to remote broker and confirm it is routed to local broker - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_tracing") - - trace = [None, "exclude-me", "a,exclude-me,b", "also-exclude-me,c", "dont-exclude-me"] - body = ["yes", "first-bad", "second-bad", "third-bad", "yes"] - for b, t in zip(body, trace): - headers = {} - if (t): headers["x-qpid.trace"]=t - dp = r_session.delivery_properties(routing_key="my-key", ttl=1000*60*5) - mp = r_session.message_properties(application_headers=headers) - r_session.message_transfer(destination="amq.direct", message=Message(dp, mp, b)) - - for e in ["my-bridge-id", "dont-exclude-me,my-bridge-id"]: - msg = queue.get(timeout=5) - self.assertEqual("yes", msg.body) - self.assertEqual(e, self.getAppHeader(msg, "x-qpid.trace")) - assert(msg.get("delivery_properties").ttl > 0) - assert(msg.get("delivery_properties").ttl < 1000*60*50) - - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_fanout(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_fanout") - - session.exchange_declare(exchange="fed.fanout", type="fanout") - r_session.exchange_declare(exchange="fed.fanout", type="fanout") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.fanout", "fed.fanout", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.fanout") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties() - r_session.message_transfer(destination="fed.fanout", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - - def test_dynamic_direct(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_direct") - - session.exchange_declare(exchange="fed.direct", type="direct") - r_session.exchange_declare(exchange="fed.direct", type="direct") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.direct", "fed.direct", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.direct", binding_key="fd-key") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="fd-key") - r_session.message_transfer(destination="fed.direct", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_topic(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_topic") - - session.exchange_declare(exchange="fed.topic", type="topic") - r_session.exchange_declare(exchange="fed.topic", type="topic") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.topic", "fed.topic", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.topic", binding_key="ft-key.#") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="ft-key.one.two") - r_session.message_transfer(destination="fed.topic", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_topic_reorigin(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_topic_reorigin") - - session.exchange_declare(exchange="fed.topic_reorigin", type="topic") - r_session.exchange_declare(exchange="fed.topic_reorigin", type="topic") - - session.exchange_declare(exchange="fed.topic_reorigin_2", type="topic") - r_session.exchange_declare(exchange="fed.topic_reorigin_2", type="topic") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - session.queue_declare(queue="fed2", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed2", exchange="fed.topic_reorigin_2", binding_key="ft-key.one.#") - self.subscribe(queue="fed2", destination="f2") - queue2 = session.incoming("f2") - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.topic_reorigin", "fed.topic_reorigin", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - result = link.bridge(False, "fed.topic_reorigin_2", "fed.topic_reorigin_2", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - bridge2 = qmf.getObjects(_class="bridge")[1] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.topic_reorigin", binding_key="ft-key.#") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="ft-key.one.two") - r_session.message_transfer(destination="fed.topic_reorigin", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = bridge2.close() - self.assertEqual(result.status, 0) - - # extra check: verify we don't leak bridge objects - keep the link - # around and verify the bridge count has gone to zero - - attempts = 0 - bridgeCount = len(qmf.getObjects(_class="bridge")) - while bridgeCount > 0: - attempts += 1 - if attempts >= 5: - self.fail("Bridges didn't clean up") - return - sleep(1) - bridgeCount = len(qmf.getObjects(_class="bridge")) - - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_direct_reorigin(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_direct_reorigin") - - session.exchange_declare(exchange="fed.direct_reorigin", type="direct") - r_session.exchange_declare(exchange="fed.direct_reorigin", type="direct") - - session.exchange_declare(exchange="fed.direct_reorigin_2", type="direct") - r_session.exchange_declare(exchange="fed.direct_reorigin_2", type="direct") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - session.queue_declare(queue="fed2", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed2", exchange="fed.direct_reorigin_2", binding_key="ft-key.two") - self.subscribe(queue="fed2", destination="f2") - queue2 = session.incoming("f2") - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.direct_reorigin", "fed.direct_reorigin", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - result = link.bridge(False, "fed.direct_reorigin_2", "fed.direct_reorigin_2", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - bridge2 = qmf.getObjects(_class="bridge")[1] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.direct_reorigin", binding_key="ft-key.one") - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="ft-key.one") - r_session.message_transfer(destination="fed.direct_reorigin", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - - # Extra test: don't explicitly close() bridge2. When the link is closed, - # it should clean up bridge2 automagically. verify_cleanup() will detect - # if bridge2 isn't cleaned up and will fail the test. - # - #result = bridge2.close() - #self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers") - - session.exchange_declare(exchange="fed.headers", type="headers") - r_session.exchange_declare(exchange="fed.headers", type="headers") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.headers", "fed.headers", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.headers", binding_key="key1", arguments={'x-match':'any', 'class':'first'}) - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - props = r_session.message_properties(application_headers={'class':'first'}) - for i in range(1, 11): - r_session.message_transfer(destination="fed.headers", message=Message(props, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - content = msg.body - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers_reorigin(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_reorigin") - - session.exchange_declare(exchange="fed.headers_reorigin", type="headers") - r_session.exchange_declare(exchange="fed.headers_reorigin", type="headers") - - session.exchange_declare(exchange="fed.headers_reorigin_2", type="headers") - r_session.exchange_declare(exchange="fed.headers_reorigin_2", type="headers") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - session.queue_declare(queue="fed2", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed2", exchange="fed.headers_reorigin_2", binding_key="key2", arguments={'x-match':'any', 'class':'second'}) - self.subscribe(queue="fed2", destination="f2") - queue2 = session.incoming("f2") - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.headers_reorigin", "fed.headers_reorigin", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - result = link.bridge(False, "fed.headers_reorigin_2", "fed.headers_reorigin_2", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - bridge2 = qmf.getObjects(_class="bridge")[1] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.headers_reorigin", binding_key="key1", arguments={'x-match':'any', 'class':'first'}) - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - props = r_session.message_properties(application_headers={'class':'first'}) - for i in range(1, 11): - r_session.message_transfer(destination="fed.headers_reorigin", message=Message(props, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - - # Extra test: don't explicitly close() bridge2. When the link is closed, - # it should clean up bridge2 automagically. verify_cleanup() will detect - # if bridge2 isn't cleaned up and will fail the test. - # - #result = bridge2.close() - #self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers_unbind(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_unbind") - - session.exchange_declare(exchange="fed.headers_unbind", type="headers") - r_session.exchange_declare(exchange="fed.headers_unbind", type="headers") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.headers_unbind", "fed.headers_unbind", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - queue = qmf.getObjects(_class="queue", name="fed1")[0] - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - session.exchange_bind(queue="fed1", exchange="fed.headers_unbind", binding_key="key1", arguments={'x-match':'any', 'class':'first'}) - queue.update() - self.assertEqual(queue.bindingCount, 2, - "bindings not accounted for (expected 2, got %d)" % queue.bindingCount) - - session.exchange_unbind(queue="fed1", exchange="fed.headers_unbind", binding_key="key1") - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - - def test_dynamic_headers_xml(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_xml") - - session.exchange_declare(exchange="fed.xml", type="xml") - r_session.exchange_declare(exchange="fed.xml", type="xml") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.xml", "fed.xml", "", "", "", False, False, True, 0) - - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.xml", binding_key="key1", arguments={'xquery':'true()'}) - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - props = r_session.delivery_properties(routing_key="key1") - for i in range(1, 11): - r_session.message_transfer(destination="fed.xml", message=Message(props, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - content = msg.body - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers_reorigin_xml(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_reorigin_xml") - - session.exchange_declare(exchange="fed.xml_reorigin", type="xml") - r_session.exchange_declare(exchange="fed.xml_reorigin", type="xml") - - session.exchange_declare(exchange="fed.xml_reorigin_2", type="xml") - r_session.exchange_declare(exchange="fed.xml_reorigin_2", type="xml") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - session.queue_declare(queue="fed2", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed2", exchange="fed.xml_reorigin_2", binding_key="key2", arguments={'xquery':'true()'}) - self.subscribe(queue="fed2", destination="f2") - queue2 = session.incoming("f2") - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.xml_reorigin", "fed.xml_reorigin", "", "", "", False, False, True, 0) - - self.assertEqual(result.status, 0) - result = link.bridge(False, "fed.xml_reorigin_2", "fed.xml_reorigin_2", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - - bridge = qmf.getObjects(_class="bridge")[0] - bridge2 = qmf.getObjects(_class="bridge")[1] - sleep(5) - - foo=qmf.getObjects(_class="link") - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.xml_reorigin", binding_key="key1", arguments={'xquery':'true()'}) - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - props = r_session.delivery_properties(routing_key="key1") - for i in range(1, 11): - r_session.message_transfer(destination="fed.xml_reorigin", message=Message(props, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - - # Extra test: don't explicitly close() bridge2. When the link is closed, - # it should clean up bridge2 automagically. verify_cleanup() will detect - # if bridge2 isn't cleaned up and will fail the test. - # - #result = bridge2.close() - #self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def test_dynamic_headers_unbind_xml(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_xml_unbind") - - session.exchange_declare(exchange="fed.xml_unbind", type="xml") - r_session.exchange_declare(exchange="fed.xml_unbind", type="xml") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.xml_unbind", "fed.xml_unbind", "", "", "", False, False, True, 0) - - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - queue = qmf.getObjects(_class="queue", name="fed1")[0] - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - session.exchange_bind(queue="fed1", exchange="fed.xml_unbind", binding_key="key1", arguments={'xquery':'true()'}) - queue.update() - self.assertEqual(queue.bindingCount, 2, - "bindings not accounted for (expected 2, got %d)" % queue.bindingCount) - - session.exchange_unbind(queue="fed1", exchange="fed.xml_unbind", binding_key="key1") - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - - def test_dynamic_topic_nodup(self): - """Verify that a message whose routing key matches more than one - binding does not get duplicated to the same queue. - """ - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_topic_nodup") - - session.exchange_declare(exchange="fed.topic", type="topic") - r_session.exchange_declare(exchange="fed.topic", type="topic") - - self.startQmf() - qmf = self.qmf - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.topic", "fed.topic", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - session.exchange_bind(queue="fed1", exchange="fed.topic", binding_key="red.*") - session.exchange_bind(queue="fed1", exchange="fed.topic", binding_key="*.herring") - - self.subscribe(queue="fed1", destination="f1") - queue = session.incoming("f1") - - for i in range(1, 11): - dp = r_session.delivery_properties(routing_key="red.herring") - r_session.message_transfer(destination="fed.topic", message=Message(dp, "Message %d" % i)) - - for i in range(1, 11): - msg = queue.get(timeout=5) - self.assertEqual("Message %d" % i, msg.body) - try: - extra = queue.get(timeout=1) - self.fail("Got unexpected message in queue: " + extra.body) - except Empty: None - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - - def test_dynamic_direct_route_prop(self): - """ Set up a tree of uni-directional routes across the direct exchange. - Bind the same key to the same queues on the leaf nodes. Verify a - message sent with the routing key transverses the tree an arrives at - each leaf. Remove one leaf's queue, and verify that messages still - reach the other leaf. - - Route Topology: - - +---> B2 queue:"test-queue", binding key:"spudboy" - B0 --> B1 --+ - +---> B3 queue:"test-queue", binding key:"spudboy" - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create direct exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers: - _b.client_session.exchange_declare(exchange="fedX.direct", type="direct") - self.assertEqual(_b.client_session.exchange_query(name="fedX.direct").type, - "direct", "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - while my_exchange is None: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX.direct": - my_exchange = ooo - break - if my_exchange is None: - retries += 1 - self.failIfEqual(retries, 10, - "QMF failed to find new exchange!") - sleep(1) - exchanges.append(my_exchange) - - self.assertEqual(len(exchanges), len(self._brokers), "Exchange creation failed!") - - # connect B0 --> B1 - result = self._brokers[1].qmf_object.connect(self._brokers[0].host, - self._brokers[0].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B2 - result = self._brokers[2].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B3 - result = self._brokers[3].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # for each link, bridge the "fedX.direct" exchanges: - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX.direct", # src - "fedX.direct", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0) # sync - self.assertEqual(result.status, 0) - - # wait for the inter-broker links to become operational - retries = 0 - operational = False - while not operational: - operational = True - for _l in qmf.getObjects(_class="link"): - #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - if not operational: - retries += 1 - self.failIfEqual(retries, 10, - "inter-broker links failed to become operational.") - sleep(1) - - # @todo - There is no way to determine when the bridge objects become - # active. Hopefully, this is long enough! - sleep(6) - - # create a queue on B2, bound to "spudboy" - self._brokers[2].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[2].client_session.exchange_bind(queue="fedX1", exchange="fedX.direct", binding_key="spudboy") - - # create a queue on B3, bound to "spudboy" - self._brokers[3].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[3].client_session.exchange_bind(queue="fedX1", exchange="fedX.direct", binding_key="spudboy") - - # subscribe to messages arriving on B2's queue - self.subscribe(self._brokers[2].client_session, queue="fedX1", destination="f1") - queue_2 = self._brokers[2].client_session.incoming("f1") - - # subscribe to messages arriving on B3's queue - self.subscribe(self._brokers[3].client_session, queue="fedX1", destination="f1") - queue_3 = self._brokers[3].client_session.incoming("f1") - - # wait until the binding key has propagated to each broker (twice at - # broker B1). Work backwards from binding brokers. - - binding_counts = [1, 2, 1, 1] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(3,-1,-1): - retries = 0 - exchanges[i].update() - while exchanges[i].bindingCount < binding_counts[i]: - retries += 1 - self.failIfEqual(retries, 10, - "binding failed to propagate to broker %d" - % i) - sleep(3) - exchanges[i].update() - - # send 10 msgs from B0 - for i in range(1, 11): - dp = self._brokers[0].client_session.delivery_properties(routing_key="spudboy") - self._brokers[0].client_session.message_transfer(destination="fedX.direct", message=Message(dp, "Message_drp %d" % i)) - - # wait for 10 messages to be forwarded from B0->B1, - # 10 messages from B1->B2, - # and 10 messages from B1->B3 - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 10 or exchanges[0].msgRoutes != 10 or - exchanges[1].msgReceives != 10 or exchanges[1].msgRoutes != 20 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 10 or exchanges[3].msgRoutes != 10): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B2 and B3 - for i in range(1, 11): - msg = queue_2.get(timeout=5) - self.assertEqual("Message_drp %d" % i, msg.body) - msg = queue_3.get(timeout=5) - self.assertEqual("Message_drp %d" % i, msg.body) - - try: - extra = queue_2.get(timeout=1) - self.fail("Got unexpected message in queue_2: " + extra.body) - except Empty: None - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - - # tear down the queue on B2 - self._brokers[2].client_session.exchange_unbind(queue="fedX1", exchange="fedX.direct", binding_key="spudboy") - self._brokers[2].client_session.message_cancel(destination="f1") - self._brokers[2].client_session.queue_delete(queue="fedX1") - - # @todo - restore code when QPID-2499 fixed!! - sleep(6) - # wait for the binding count on B1 to drop from 2 to 1 - retries = 0 - exchanges[1].update() - while exchanges[1].bindingCount != 1: - retries += 1 - self.failIfEqual(retries, 10, - "unbinding failed to propagate to broker B1: %d" - % exchanges[1].bindingCount) - sleep(1) - exchanges[1].update() - - # send 10 msgs from B0 - for i in range(11, 21): - dp = self._brokers[0].client_session.delivery_properties(routing_key="spudboy") - self._brokers[0].client_session.message_transfer(destination="fedX.direct", message=Message(dp, "Message_drp %d" % i)) - - # verify messages are forwarded to B3 only - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 20 or exchanges[0].msgRoutes != 20 or - exchanges[1].msgReceives != 20 or exchanges[1].msgRoutes != 30 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 20 or exchanges[3].msgRoutes != 20): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route more msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B3 only - for i in range(11, 21): - msg = queue_3.get(timeout=5) - self.assertEqual("Message_drp %d" % i, msg.body) - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # cleanup - - self._brokers[3].client_session.exchange_unbind(queue="fedX1", exchange="fedX.direct", binding_key="spudboy") - self._brokers[3].client_session.message_cancel(destination="f1") - self._brokers[3].client_session.queue_delete(queue="fedX1") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers: - _b.client_session.exchange_delete(exchange="fedX.direct") - - self._teardown_brokers() - - self.verify_cleanup() - - def test_dynamic_topic_route_prop(self): - """ Set up a tree of uni-directional routes across a topic exchange. - Bind the same key to the same queues on the leaf nodes. Verify a - message sent with the routing key transverses the tree an arrives at - each leaf. Remove one leaf's queue, and verify that messages still - reach the other leaf. - - Route Topology: - - +---> B2 queue:"test-queue", binding key:"spud.*" - B0 --> B1 --+ - +---> B3 queue:"test-queue", binding key:"spud.*" - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers: - _b.client_session.exchange_declare(exchange="fedX.topic", type="topic") - self.assertEqual(_b.client_session.exchange_query(name="fedX.topic").type, - "topic", "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - while my_exchange is None: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX.topic": - my_exchange = ooo - break - if my_exchange is None: - retries += 1 - self.failIfEqual(retries, 10, - "QMF failed to find new exchange!") - sleep(1) - exchanges.append(my_exchange) - - self.assertEqual(len(exchanges), len(self._brokers), "Exchange creation failed!") - - # connect B0 --> B1 - result = self._brokers[1].qmf_object.connect(self._brokers[0].host, - self._brokers[0].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B2 - result = self._brokers[2].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B3 - result = self._brokers[3].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # for each link, bridge the "fedX.topic" exchanges: - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX.topic", # src - "fedX.topic", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0) # sync - self.assertEqual(result.status, 0) - - # wait for the inter-broker links to become operational - retries = 0 - operational = False - while not operational: - operational = True - for _l in qmf.getObjects(_class="link"): - #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - if not operational: - retries += 1 - self.failIfEqual(retries, 10, - "inter-broker links failed to become operational.") - sleep(1) - - # @todo - There is no way to determine when the bridge objects become - # active. - sleep(6) - - # create a queue on B2, bound to "spudboy" - self._brokers[2].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[2].client_session.exchange_bind(queue="fedX1", exchange="fedX.topic", binding_key="spud.*") - - # create a queue on B3, bound to "spudboy" - self._brokers[3].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[3].client_session.exchange_bind(queue="fedX1", exchange="fedX.topic", binding_key="spud.*") - - # subscribe to messages arriving on B2's queue - self.subscribe(self._brokers[2].client_session, queue="fedX1", destination="f1") - queue_2 = self._brokers[2].client_session.incoming("f1") - - # subscribe to messages arriving on B3's queue - self.subscribe(self._brokers[3].client_session, queue="fedX1", destination="f1") - queue_3 = self._brokers[3].client_session.incoming("f1") - - # wait until the binding key has propagated to each broker (twice at - # broker B1). Work backwards from binding brokers. - - binding_counts = [1, 2, 1, 1] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(3,-1,-1): - retries = 0 - exchanges[i].update() - while exchanges[i].bindingCount < binding_counts[i]: - retries += 1 - self.failIfEqual(retries, 10, - "binding failed to propagate to broker %d" - % i) - sleep(3) - exchanges[i].update() - - # send 10 msgs from B0 - for i in range(1, 11): - dp = self._brokers[0].client_session.delivery_properties(routing_key="spud.boy") - self._brokers[0].client_session.message_transfer(destination="fedX.topic", message=Message(dp, "Message_trp %d" % i)) - - # wait for 10 messages to be forwarded from B0->B1, - # 10 messages from B1->B2, - # and 10 messages from B1->B3 - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 10 or exchanges[0].msgRoutes != 10 or - exchanges[1].msgReceives != 10 or exchanges[1].msgRoutes != 20 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 10 or exchanges[3].msgRoutes != 10): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B2 and B3 - for i in range(1, 11): - msg = queue_2.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - msg = queue_3.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - - try: - extra = queue_2.get(timeout=1) - self.fail("Got unexpected message in queue_2: " + extra.body) - except Empty: None - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # tear down the queue on B2 - self._brokers[2].client_session.exchange_unbind(queue="fedX1", exchange="fedX.topic", binding_key="spud.*") - self._brokers[2].client_session.message_cancel(destination="f1") - self._brokers[2].client_session.queue_delete(queue="fedX1") - - # wait for the binding count on B1 to drop from 2 to 1 - retries = 0 - exchanges[1].update() - while exchanges[1].bindingCount != 1: - retries += 1 - self.failIfEqual(retries, 10, - "unbinding failed to propagate to broker B1: %d" - % exchanges[1].bindingCount) - sleep(1) - exchanges[1].update() - - # send 10 msgs from B0 - for i in range(11, 21): - dp = self._brokers[0].client_session.delivery_properties(routing_key="spud.boy") - self._brokers[0].client_session.message_transfer(destination="fedX.topic", message=Message(dp, "Message_trp %d" % i)) - - # verify messages are forwarded to B3 only - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 20 or exchanges[0].msgRoutes != 20 or - exchanges[1].msgReceives != 20 or exchanges[1].msgRoutes != 30 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 20 or exchanges[3].msgRoutes != 20): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route more msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B3 only - for i in range(11, 21): - msg = queue_3.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # cleanup - - self._brokers[3].client_session.exchange_unbind(queue="fedX1", exchange="fedX.topic", binding_key="spud.*") - self._brokers[3].client_session.message_cancel(destination="f1") - self._brokers[3].client_session.queue_delete(queue="fedX1") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers: - _b.client_session.exchange_delete(exchange="fedX.topic") - - self._teardown_brokers() - - self.verify_cleanup() - - - def test_dynamic_fanout_route_prop(self): - """ Set up a tree of uni-directional routes across a fanout exchange. - Bind the same key to the same queues on the leaf nodes. Verify a - message sent with the routing key transverses the tree an arrives at - each leaf. Remove one leaf's queue, and verify that messages still - reach the other leaf. - - Route Topology: - - +---> B2 queue:"test-queue", binding key:"spud.*" - B0 --> B1 --+ - +---> B3 queue:"test-queue", binding key:"spud.*" - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create fanout exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers: - _b.client_session.exchange_declare(exchange="fedX.fanout", type="fanout") - self.assertEqual(_b.client_session.exchange_query(name="fedX.fanout").type, - "fanout", "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - while my_exchange is None: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX.fanout": - my_exchange = ooo - break - if my_exchange is None: - retries += 1 - self.failIfEqual(retries, 10, - "QMF failed to find new exchange!") - sleep(1) - exchanges.append(my_exchange) - - self.assertEqual(len(exchanges), len(self._brokers), "Exchange creation failed!") - - # connect B0 --> B1 - result = self._brokers[1].qmf_object.connect(self._brokers[0].host, - self._brokers[0].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B2 - result = self._brokers[2].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B3 - result = self._brokers[3].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # for each link, bridge the "fedX.fanout" exchanges: - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX.fanout", # src - "fedX.fanout", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0) # sync - self.assertEqual(result.status, 0) - - # wait for the inter-broker links to become operational - retries = 0 - operational = False - while not operational: - operational = True - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - if not operational: - retries += 1 - self.failIfEqual(retries, 10, - "inter-broker links failed to become operational.") - sleep(1) - - # @todo - There is no way to determine when the bridge objects become - # active. - sleep(6) - - # create a queue on B2, bound to the exchange - self._brokers[2].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[2].client_session.exchange_bind(queue="fedX1", exchange="fedX.fanout") - - # create a queue on B3, bound to the exchange - self._brokers[3].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - self._brokers[3].client_session.exchange_bind(queue="fedX1", exchange="fedX.fanout") - - # subscribe to messages arriving on B2's queue - self.subscribe(self._brokers[2].client_session, queue="fedX1", destination="f1") - queue_2 = self._brokers[2].client_session.incoming("f1") - - # subscribe to messages arriving on B3's queue - self.subscribe(self._brokers[3].client_session, queue="fedX1", destination="f1") - queue_3 = self._brokers[3].client_session.incoming("f1") - - # wait until the binding key has propagated to each broker (twice at - # broker B1). Work backwards from binding brokers. - - binding_counts = [1, 2, 1, 1] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(3,-1,-1): - retries = 0 - exchanges[i].update() - while exchanges[i].bindingCount < binding_counts[i]: - retries += 1 - self.failIfEqual(retries, 10, - "binding failed to propagate to broker %d" - % i) - sleep(3) - exchanges[i].update() - - # send 10 msgs from B0 - for i in range(1, 11): - dp = self._brokers[0].client_session.delivery_properties() - self._brokers[0].client_session.message_transfer(destination="fedX.fanout", message=Message(dp, "Message_frp %d" % i)) - - # wait for 10 messages to be forwarded from B0->B1, - # 10 messages from B1->B2, - # and 10 messages from B1->B3 - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 10 or exchanges[0].msgRoutes != 10 or - exchanges[1].msgReceives != 10 or exchanges[1].msgRoutes != 20 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 10 or exchanges[3].msgRoutes != 10): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B2 and B3 - for i in range(1, 11): - msg = queue_2.get(timeout=5) - self.assertEqual("Message_frp %d" % i, msg.body) - msg = queue_3.get(timeout=5) - self.assertEqual("Message_frp %d" % i, msg.body) - - try: - extra = queue_2.get(timeout=1) - self.fail("Got unexpected message in queue_2: " + extra.body) - except Empty: None - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # tear down the queue on B2 - self._brokers[2].client_session.exchange_unbind(queue="fedX1", exchange="fedX.fanout") - self._brokers[2].client_session.message_cancel(destination="f1") - self._brokers[2].client_session.queue_delete(queue="fedX1") - - # wait for the binding count on B1 to drop from 2 to 1 - retries = 0 - exchanges[1].update() - while exchanges[1].bindingCount != 1: - retries += 1 - self.failIfEqual(retries, 10, - "unbinding failed to propagate to broker B1: %d" - % exchanges[1].bindingCount) - sleep(1) - exchanges[1].update() - - # send 10 msgs from B0 - for i in range(11, 21): - dp = self._brokers[0].client_session.delivery_properties() - self._brokers[0].client_session.message_transfer(destination="fedX.fanout", message=Message(dp, "Message_frp %d" % i)) - - # verify messages are forwarded to B3 only - retries = 0 - for ex in exchanges: - ex.update() - while (exchanges[0].msgReceives != 20 or exchanges[0].msgRoutes != 20 or - exchanges[1].msgReceives != 20 or exchanges[1].msgRoutes != 30 or - exchanges[2].msgReceives != 10 or exchanges[2].msgRoutes != 10 or - exchanges[3].msgReceives != 20 or exchanges[3].msgRoutes != 20): - retries += 1 - self.failIfEqual(retries, 10, - "federation failed to route more msgs %d:%d %d:%d %d:%d %d:%d" - % (exchanges[0].msgReceives, - exchanges[0].msgRoutes, - exchanges[1].msgReceives, - exchanges[1].msgRoutes, - exchanges[2].msgReceives, - exchanges[2].msgRoutes, - exchanges[3].msgReceives, - exchanges[3].msgRoutes)) - sleep(1) - for ex in exchanges: - ex.update() - - # get exactly 10 msgs on B3 only - for i in range(11, 21): - msg = queue_3.get(timeout=5) - self.assertEqual("Message_frp %d" % i, msg.body) - - try: - extra = queue_3.get(timeout=1) - self.fail("Got unexpected message in queue_3: " + extra.body) - except Empty: None - - # cleanup - - self._brokers[3].client_session.exchange_unbind(queue="fedX1", exchange="fedX.fanout") - self._brokers[3].client_session.message_cancel(destination="f1") - self._brokers[3].client_session.queue_delete(queue="fedX1") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers: - _b.client_session.exchange_delete(exchange="fedX.fanout") - - self._teardown_brokers() - - self.verify_cleanup() - - - def getProperty(self, msg, name): - for h in msg.headers: - if hasattr(h, name): return getattr(h, name) - return None - - def getAppHeader(self, msg, name): - headers = self.getProperty(msg, "application_headers") - if headers: - return headers[name] - return None - - def test_dynamic_topic_bounce(self): - """ Bounce the connection between federated Topic Exchanges. - """ - class Params: - def exchange_type(self): return "topic" - def bind_queue(self, ssn, qname, ename): - ssn.exchange_bind(queue=qname, exchange=ename, - binding_key="spud.*") - def unbind_queue(self, ssn, qname, ename): - ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud.*") - def delivery_properties(self, ssn): - return ssn.delivery_properties(routing_key="spud.boy") - - self.generic_dynamic_bounce_test(Params()) - - def test_dynamic_direct_bounce(self): - """ Bounce the connection between federated Direct Exchanges. - """ - class Params: - def exchange_type(self): return "direct" - def bind_queue(self, ssn, qname, ename): - ssn.exchange_bind(queue=qname, exchange=ename, binding_key="spud") - def unbind_queue(self, ssn, qname, ename): - ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud") - def delivery_properties(self, ssn): - return ssn.delivery_properties(routing_key="spud") - self.generic_dynamic_bounce_test(Params()) - - def test_dynamic_fanout_bounce(self): - """ Bounce the connection between federated Fanout Exchanges. - """ - class Params: - def exchange_type(self): return "fanout" - def bind_queue(self, ssn, qname, ename): - ssn.exchange_bind(queue=qname, exchange=ename) - def unbind_queue(self, ssn, qname, ename): - ssn.exchange_unbind(queue=qname, exchange=ename) - def delivery_properties(self, ssn): - return ssn.delivery_properties(routing_key="spud") - self.generic_dynamic_bounce_test(Params()) - - def test_dynamic_headers_bounce(self): - """ Bounce the connection between federated Headers Exchanges. - """ - class Params: - def exchange_type(self): return "headers" - def bind_queue(self, ssn, qname, ename): - ssn.exchange_bind(queue=qname, exchange=ename, - binding_key="spud", arguments={'x-match':'any', 'class':'first'}) - def unbind_queue(self, ssn, qname, ename): - ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud") - def delivery_properties(self, ssn): - return ssn.message_properties(application_headers={'class':'first'}) - ## @todo KAG - re-enable once federation bugs with headers exchanges - ## are fixed. - #self.generic_dynamic_bounce_test(Params()) - return - - - def generic_dynamic_bounce_test(self, params): - """ Verify that a federated broker can maintain a binding to a local - queue using the same key as a remote binding. Destroy and reconnect - the federation link, and verify routes are restored correctly. - See QPID-3170. - Topology: - - Queue1 <---"Key"---B0<==[Federated Exchange]==>B1---"Key"--->Queue2 - """ - session = self.session - - # create the federation - - self.startQmf() - qmf = self.qmf - - self._setup_brokers() - - # create exchange on each broker, and retrieve the corresponding - # management object for that exchange - - exchanges=[] - for _b in self._brokers[0:2]: - _b.client_session.exchange_declare(exchange="fedX", type=params.exchange_type()) - self.assertEqual(_b.client_session.exchange_query(name="fedX").type, - params.exchange_type(), "exchange_declare failed!") - # pull the exchange out of qmf... - retries = 0 - my_exchange = None - timeout = time() + 10 - while my_exchange is None and time() <= timeout: - objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange") - for ooo in objs: - if ooo.name == "fedX": - my_exchange = ooo - break - if my_exchange is None: - self.fail("QMF failed to find new exchange!") - exchanges.append(my_exchange) - - # - # on each broker, create a local queue bound to the exchange with the - # same key value. - # - - self._brokers[0].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - params.bind_queue(self._brokers[0].client_session, "fedX1", "fedX") - self.subscribe(self._brokers[0].client_session, queue="fedX1", destination="f1") - queue_0 = self._brokers[0].client_session.incoming("f1") - - self._brokers[1].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True) - params.bind_queue(self._brokers[1].client_session, "fedX1", "fedX") - self.subscribe(self._brokers[1].client_session, queue="fedX1", destination="f1") - queue_1 = self._brokers[1].client_session.incoming("f1") - - # now federate the two brokers - - # connect B0 --> B1 - result = self._brokers[1].qmf_object.connect(self._brokers[0].host, - self._brokers[0].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # connect B1 --> B0 - result = self._brokers[0].qmf_object.connect(self._brokers[1].host, - self._brokers[1].port, - False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - # for each link, bridge the "fedX" exchanges: - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX", # src - "fedX", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0) # sync - self.assertEqual(result.status, 0) - - # wait for all the inter-broker links to become operational - operational = False - timeout = time() + 10 - while not operational and time() <= timeout: - operational = True - for _l in qmf.getObjects(_class="link"): - #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state))) - if _l.state != "Operational": - operational = False - self.failUnless(operational, "inter-broker links failed to become operational.") - - # @todo - There is no way to determine when the bridge objects become - # active. - - # wait until the binding key has propagated to each broker - each - # broker should see 2 bindings (1 local, 1 remote) - - binding_counts = [2, 2] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(2): - exchanges[i].update() - timeout = time() + 10 - while exchanges[i].bindingCount < binding_counts[i] and time() <= timeout: - exchanges[i].update() - self.failUnless(exchanges[i].bindingCount == binding_counts[i]) - - # send 10 msgs to B0 - for i in range(1, 11): - # dp = self._brokers[0].client_session.delivery_properties(routing_key=params.routing_key()) - dp = params.delivery_properties(self._brokers[0].client_session) - self._brokers[0].client_session.message_transfer(destination="fedX", message=Message(dp, "Message_trp %d" % i)) - - # get exactly 10 msgs on B0's local queue and B1's queue - for i in range(1, 11): - try: - msg = queue_0.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - msg = queue_1.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - except Empty: - self.fail("Only got %d msgs - expected 10" % i) - try: - extra = queue_0.get(timeout=1) - self.fail("Got unexpected message in queue_0: " + extra.body) - except Empty: None - - try: - extra = queue_1.get(timeout=1) - self.fail("Got unexpected message in queue_1: " + extra.body) - except Empty: None - - # - # Tear down the bridges between the two exchanges, then wait - # for the bindings to be cleaned up - # - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - binding_counts = [1, 1] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(2): - exchanges[i].update() - timeout = time() + 10 - while exchanges[i].bindingCount != binding_counts[i] and time() <= timeout: - exchanges[i].update() - self.failUnless(exchanges[i].bindingCount == binding_counts[i]) - - # - # restore the bridges between the two exchanges, and wait for the - # bindings to propagate. - # - - for _l in qmf.getObjects(_class="link"): - # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker()))) - result = _l.bridge(False, # durable - "fedX", # src - "fedX", # dst - "", # key - "", # tag - "", # excludes - False, # srcIsQueue - False, # srcIsLocal - True, # dynamic - 0) # sync - self.assertEqual(result.status, 0) - - binding_counts = [2, 2] - self.assertEqual(len(binding_counts), len(exchanges), "Update Test!") - for i in range(2): - exchanges[i].update() - timeout = time() + 10 - while exchanges[i].bindingCount != binding_counts[i] and time() <= timeout: - exchanges[i].update() - self.failUnless(exchanges[i].bindingCount == binding_counts[i]) - - # - # verify traffic flows correctly - # - - for i in range(1, 11): - #dp = self._brokers[1].client_session.delivery_properties(routing_key=params.routing_key()) - dp = params.delivery_properties(self._brokers[1].client_session) - self._brokers[1].client_session.message_transfer(destination="fedX", message=Message(dp, "Message_trp %d" % i)) - - # get exactly 10 msgs on B0's queue and B1's queue - for i in range(1, 11): - try: - msg = queue_0.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - msg = queue_1.get(timeout=5) - self.assertEqual("Message_trp %d" % i, msg.body) - except Empty: - self.fail("Only got %d msgs - expected 10" % i) - try: - extra = queue_0.get(timeout=1) - self.fail("Got unexpected message in queue_0: " + extra.body) - except Empty: None - - try: - extra = queue_1.get(timeout=1) - self.fail("Got unexpected message in queue_1: " + extra.body) - except Empty: None - - - # - # cleanup - # - params.unbind_queue(self._brokers[0].client_session, "fedX1", "fedX") - self._brokers[0].client_session.message_cancel(destination="f1") - self._brokers[0].client_session.queue_delete(queue="fedX1") - - params.unbind_queue(self._brokers[1].client_session, "fedX1", "fedX") - self._brokers[1].client_session.message_cancel(destination="f1") - self._brokers[1].client_session.queue_delete(queue="fedX1") - - for _b in qmf.getObjects(_class="bridge"): - result = _b.close() - self.assertEqual(result.status, 0) - - for _l in qmf.getObjects(_class="link"): - result = _l.close() - self.assertEqual(result.status, 0) - - for _b in self._brokers[0:2]: - _b.client_session.exchange_delete(exchange="fedX") - - self._teardown_brokers() - - self.verify_cleanup() - - diff --git a/cpp/src/tests/find_prog.ps1 b/cpp/src/tests/find_prog.ps1 deleted file mode 100644 index 5c482debbf..0000000000 --- a/cpp/src/tests/find_prog.ps1 +++ /dev/null @@ -1,36 +0,0 @@ -#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Locate the subdirectory where the specified program resides; the program
-# must have a directory and a file name, even if the directory is .
-param(
- [string] $prog # program to look for somewhere below cwd
-)
-
-$dir = Split-Path $prog
-$exe = Split-Path $prog -leaf
-$sub = ""
-$subs = "Debug","Release","MinSizeRel","RelWithDebInfo"
-foreach ($try in $subs) {
- $prog = "$dir\$try\$exe"
- if (Test-Path $prog) {
- $sub = $try
- break
- }
-}
diff --git a/cpp/src/tests/header_test.cpp b/cpp/src/tests/header_test.cpp deleted file mode 100644 index c36b4f3bc3..0000000000 --- a/cpp/src/tests/header_test.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <iostream> - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" - -using namespace qpid; -using namespace qpid::client; -using namespace std; - -int main(int argc, char** argv) -{ - TestOptions opts; - try { - opts.parse(argc, argv); - Connection connection; - connection.open(opts.con); - Session session = connection.newSession(); - std::string q("header_interop_test_queue"); - session.queueDeclare(arg::queue=q); - double pi = 3.14159265; - float e = 2.71828f; - Message msg("", q); - msg.getMessageProperties().getApplicationHeaders().setDouble("pi", pi); - msg.getMessageProperties().getApplicationHeaders().setFloat("e", e); - session.messageTransfer(arg::content=msg); - - session.close(); - connection.close(); - - return 0; - } catch(const exception& e) { - cout << e.what() << endl; - } - return 1; -} diff --git a/cpp/src/tests/header_test.py b/cpp/src/tests/header_test.py deleted file mode 100755 index d5a2c16c01..0000000000 --- a/cpp/src/tests/header_test.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import qpid -import sys -import os -from qpid.util import connect -from qpid.connection import Connection -from qpid.datatypes import Message, RangedSet, uuid4 -from qpid.queue import Empty -from math import fabs - -def getApplicationHeaders(msg): - for h in msg.headers: - if hasattr(h, 'application_headers'): return getattr(h, 'application_headers') - return None - -# Set parameters for login - -host="127.0.0.1" -port=5672 -user="guest" -password="guest" - -if len(sys.argv) > 1 : - host=sys.argv[1] -if len(sys.argv) > 2 : - port=int(sys.argv[2]) - -# Create a connection. -socket = connect(host, port) -connection = Connection (sock=socket) -connection.start() -session = connection.session(str(uuid4())) - -q = "header_interop_test_queue" -session.queue_declare(queue=q) - -session.message_subscribe(queue=q, destination="received") -queue = session.incoming("received") -queue.start() - -msg = queue.get(timeout=10) -pi = 3.14159265 -e = 2.71828 - -headers = getApplicationHeaders(msg) -pi_ = headers["pi"] -e_ = headers["e"] -session.close(timeout=10) - -failed = False - -if pi != pi_: - print "got incorrect value for pi: ", pi_, " expected:", pi - failed = True - -if fabs(e - e_) > 0.0001: - print "got incorrect value for e: ", e_, " expected:", e - failed = True - -if failed: - sys.exit(1) -else: - print "Correct header values received." - sys.exit(0) - - - diff --git a/cpp/src/tests/headers_federation.py b/cpp/src/tests/headers_federation.py deleted file mode 100644 index 60cff1da54..0000000000 --- a/cpp/src/tests/headers_federation.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import sys -from qpid.testlib import TestBase010 -from qpid.datatypes import Message -from qpid.queue import Empty -from time import sleep - -class HeadersFederationTests(TestBase010): - - def remote_host(self): - return self.defines.get("remote-host", "localhost") - - def remote_port(self): - return int(self.defines["remote-port"]) - - def verify_cleanup(self): - attempts = 0 - total = len(self.qmf.getObjects(_class="bridge")) + len(self.qmf.getObjects(_class="link")) - while total > 0: - attempts += 1 - if attempts >= 10: - self.fail("Bridges and links didn't clean up") - return - sleep(1) - total = len(self.qmf.getObjects(_class="bridge")) + len(self.qmf.getObjects(_class="link")) - - def test_dynamic_headers_unbind(self): - session = self.session - r_conn = self.connect(host=self.remote_host(), port=self.remote_port()) - r_session = r_conn.session("test_dynamic_headers_unbind") - - session.exchange_declare(exchange="fed.headers_unbind", type="headers") - r_session.exchange_declare(exchange="fed.headers_unbind", type="headers") - - self.startQmf() - qmf = self.qmf - - broker = qmf.getObjects(_class="broker")[0] - result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp") - self.assertEqual(result.status, 0) - - link = qmf.getObjects(_class="link")[0] - result = link.bridge(False, "fed.headers_unbind", "fed.headers_unbind", "", "", "", False, False, True, 0) - self.assertEqual(result.status, 0) - bridge = qmf.getObjects(_class="bridge")[0] - sleep(5) - - session.queue_declare(queue="fed1", exclusive=True, auto_delete=True) - queue = qmf.getObjects(_class="queue", name="fed1")[0] - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - session.exchange_bind(queue="fed1", exchange="fed.headers_unbind", binding_key="key1", arguments={'x-match':'any', 'class':'first'}) - queue.update() - self.assertEqual(queue.bindingCount, 2, - "bindings not accounted for (expected 2, got %d)" % queue.bindingCount) - - session.exchange_unbind(queue="fed1", exchange="fed.headers_unbind", binding_key="key1") - queue.update() - self.assertEqual(queue.bindingCount, 1, - "bindings not accounted for (expected 1, got %d)" % queue.bindingCount) - - result = bridge.close() - self.assertEqual(result.status, 0) - result = link.close() - self.assertEqual(result.status, 0) - - self.verify_cleanup() - - def getProperty(self, msg, name): - for h in msg.headers: - if hasattr(h, name): return getattr(h, name) - return None - - def getAppHeader(self, msg, name): - headers = self.getProperty(msg, "application_headers") - if headers: - return headers[name] - return None diff --git a/cpp/src/tests/install_env.sh.in b/cpp/src/tests/install_env.sh.in deleted file mode 100644 index 2231954cb8..0000000000 --- a/cpp/src/tests/install_env.sh.in +++ /dev/null @@ -1,26 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -absdir() { echo `cd $1 && pwd`; } - -prefix=`absdir @prefix@` -export QPID_INSTALL_PREFIX=$prefix -export PATH=$prefix/bin:$prefix/sbin:$prefix/libexec/qpid/tests:$PATH -export LD_LIBRARY_PATH=$prefix/lib:$LD_LIBRARY_PATH -export PYTHONPATH=$prefix/lib/python2.4/site-packages:$PYTHONPATH diff --git a/cpp/src/tests/logging.cpp b/cpp/src/tests/logging.cpp deleted file mode 100644 index fc55d642c3..0000000000 --- a/cpp/src/tests/logging.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test_tools.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/OstreamOutput.h" -#include "qpid/memory.h" -#include "qpid/Options.h" -#if defined (_WIN32) -# include "qpid/log/windows/SinkOptions.h" -#else -# include "qpid/log/posix/SinkOptions.h" -#endif - -#include <boost/test/floating_point_comparison.hpp> -#include <boost/format.hpp> -#include "unit_test.h" - -#include <exception> -#include <fstream> -#include <time.h> - - -namespace qpid { -namespace tests { - -QPID_AUTO_TEST_SUITE(loggingTestSuite) - -using namespace std; -using namespace boost; -using namespace qpid::log; - -QPID_AUTO_TEST_CASE(testStatementInit) { - Statement s=QPID_LOG_STATEMENT_INIT(debug); int line=__LINE__; - BOOST_CHECK(!s.enabled); - BOOST_CHECK_EQUAL(string(__FILE__), s.file); - BOOST_CHECK_EQUAL(line, s.line); - BOOST_CHECK_EQUAL(debug, s.level); -} - - -QPID_AUTO_TEST_CASE(testSelector_enable) { - Selector s; - // Simple enable - s.enable(debug,"foo"); - BOOST_CHECK(s.isEnabled(debug,"foo")); - BOOST_CHECK(!s.isEnabled(error,"foo")); - BOOST_CHECK(!s.isEnabled(error,"bar")); - - // Substring match - BOOST_CHECK(s.isEnabled(debug, "bazfoobar")); - BOOST_CHECK(!s.isEnabled(debug, "bazbar")); - - // Different levels for different substrings. - s.enable(info, "bar"); - BOOST_CHECK(s.isEnabled(debug, "foobar")); - BOOST_CHECK(s.isEnabled(info, "foobar")); - BOOST_CHECK(!s.isEnabled(debug, "bar")); - BOOST_CHECK(!s.isEnabled(info, "foo")); - - // Enable-strings - s.enable("notice:blob"); - BOOST_CHECK(s.isEnabled(notice, "blob")); - s.enable("error+:oops"); - BOOST_CHECK(s.isEnabled(error, "oops")); - BOOST_CHECK(s.isEnabled(critical, "oops")); -} - -QPID_AUTO_TEST_CASE(testStatementEnabled) { - // Verify that the singleton enables and disables static - // log statements. - Logger& l = Logger::instance(); - ScopedSuppressLogging ls(l); - l.select(Selector(debug)); - static Statement s=QPID_LOG_STATEMENT_INIT(debug); - BOOST_CHECK(!s.enabled); - static Statement::Initializer init(s); - BOOST_CHECK(s.enabled); - - static Statement s2=QPID_LOG_STATEMENT_INIT(warning); - static Statement::Initializer init2(s2); - BOOST_CHECK(!s2.enabled); - - l.select(Selector(warning)); - BOOST_CHECK(!s.enabled); - BOOST_CHECK(s2.enabled); -} - -struct TestOutput : public Logger::Output { - vector<string> msg; - vector<Statement> stmt; - - TestOutput(Logger& l) { - l.output(std::auto_ptr<Logger::Output>(this)); - } - - void log(const Statement& s, const string& m) { - msg.push_back(m); - stmt.push_back(s); - } - string last() { return msg.back(); } -}; - -using boost::assign::list_of; - -QPID_AUTO_TEST_CASE(testLoggerOutput) { - Logger l; - l.clear(); - l.select(Selector(debug)); - Statement s=QPID_LOG_STATEMENT_INIT(debug); - - TestOutput* out=new TestOutput(l); - - // Verify message is output. - l.log(s, "foo"); - vector<string> expect=list_of("foo\n"); - BOOST_CHECK_EQUAL(expect, out->msg); - - // Verify multiple outputs - TestOutput* out2=new TestOutput(l); - l.log(Statement(), "baz"); - expect.push_back("baz\n"); - BOOST_CHECK_EQUAL(expect, out->msg); - expect.erase(expect.begin()); - BOOST_CHECK_EQUAL(expect, out2->msg); -} - -QPID_AUTO_TEST_CASE(testMacro) { - Logger& l=Logger::instance(); - ScopedSuppressLogging ls(l); - l.select(Selector(info)); - TestOutput* out=new TestOutput(l); - QPID_LOG(info, "foo"); - vector<string> expect=list_of("foo\n"); - BOOST_CHECK_EQUAL(expect, out->msg); - BOOST_CHECK_EQUAL(__FILE__, out->stmt.front().file); - - // Not enabled: - QPID_LOG(debug, "bar"); - BOOST_CHECK_EQUAL(expect, out->msg); - - QPID_LOG(info, 42 << " bingo"); - expect.push_back("42 bingo\n"); - BOOST_CHECK_EQUAL(expect, out->msg); -} - -QPID_AUTO_TEST_CASE(testLoggerFormat) { - Logger& l = Logger::instance(); - ScopedSuppressLogging ls(l); - l.select(Selector(critical)); - TestOutput* out=new TestOutput(l); - - l.format(Logger::FILE); - QPID_LOG(critical, "foo"); - BOOST_CHECK_EQUAL(out->last(), string(__FILE__)+": foo\n"); - - l.format(Logger::FILE|Logger::LINE); - QPID_LOG(critical, "foo"); - BOOST_CHECK_EQUAL(out->last().find(__FILE__), 0u); - - l.format(Logger::FUNCTION); - QPID_LOG(critical, "foo"); - BOOST_CHECK_EQUAL(string(BOOST_CURRENT_FUNCTION) + ": foo\n", out->last()); - - l.format(Logger::LEVEL); - QPID_LOG(critical, "foo"); - BOOST_CHECK_EQUAL("critical foo\n", out->last()); -} - -QPID_AUTO_TEST_CASE(testOstreamOutput) { - Logger& l=Logger::instance(); - ScopedSuppressLogging ls(l); - l.select(Selector(error)); - ostringstream os; - l.output(qpid::make_auto_ptr<Logger::Output>(new OstreamOutput(os))); - QPID_LOG(error, "foo"); - QPID_LOG(error, "bar"); - QPID_LOG(error, "baz"); - BOOST_CHECK_EQUAL("foo\nbar\nbaz\n", os.str()); -} - -#if 0 // This test requires manual intervention. Normally disabled. -QPID_AUTO_TEST_CASE(testSyslogOutput) { - Logger& l=Logger::instance(); - Logger::StateSaver ls(l); - l.clear(); - l.select(Selector(info)); - l.syslog("qpid_test"); - QPID_LOG(info, "Testing QPID"); - BOOST_ERROR("Manually verify that /var/log/messages contains a recent line 'Testing QPID'"); -} -#endif // 0 - -int count() { - static int n = 0; - return n++; -} - -int loggedCount() { - static int n = 0; - QPID_LOG(debug, "counting: " << n); - return n++; -} - - -using namespace qpid::sys; - -// Measure CPU time. -clock_t timeLoop(int times, int (*fp)()) { - clock_t start=clock(); - while (times-- > 0) - (*fp)(); - return clock() - start; -} - -// Overhead test disabled because it consumes a ton of CPU and takes -// forever under valgrind. Not friendly for regular test runs. -// -#if 0 -QPID_AUTO_TEST_CASE(testOverhead) { - // Ensure that the ratio of CPU time for an incrementing loop - // with and without disabled log statements is in acceptable limits. - // - int times=100000000; - clock_t noLog=timeLoop(times, count); - clock_t withLog=timeLoop(times, loggedCount); - double ratio=double(withLog)/double(noLog); - - // NB: in initial tests the ratio was consistently below 1.5, - // 2.5 is reasonable and should avoid spurios failures - // due to machine load. - // - BOOST_CHECK_SMALL(ratio, 2.5); -} -#endif // 0 - -Statement statement( - Level level, const char* file="", int line=0, const char* fn=0) -{ - Statement s={0, file, line, fn, level}; - return s; -} - - -#define ARGC(argv) (sizeof(argv)/sizeof(char*)) - -QPID_AUTO_TEST_CASE(testOptionsParse) { - const char* argv[]={ - 0, - "--log-enable", "error+:foo", - "--log-enable", "debug:bar", - "--log-enable", "info", - "--log-to-stderr", "no", - "--log-to-file", "logout", - "--log-level", "yes", - "--log-source", "1", - "--log-thread", "true", - "--log-function", "YES" - }; - qpid::log::Options opts(""); -#ifdef _WIN32 - qpid::log::windows::SinkOptions sinks("test"); -#else - qpid::log::posix::SinkOptions sinks("test"); -#endif - opts.parse(ARGC(argv), const_cast<char**>(argv)); - sinks = *opts.sinkOptions; - vector<string> expect=list_of("error+:foo")("debug:bar")("info"); - BOOST_CHECK_EQUAL(expect, opts.selectors); - BOOST_CHECK(!sinks.logToStderr); - BOOST_CHECK(!sinks.logToStdout); - BOOST_CHECK(sinks.logFile == "logout"); - BOOST_CHECK(opts.level); - BOOST_CHECK(opts.source); - BOOST_CHECK(opts.function); - BOOST_CHECK(opts.thread); -} - -QPID_AUTO_TEST_CASE(testOptionsDefault) { - qpid::log::Options opts(""); -#ifdef _WIN32 - qpid::log::windows::SinkOptions sinks("test"); -#else - qpid::log::posix::SinkOptions sinks("test"); -#endif - sinks = *opts.sinkOptions; - BOOST_CHECK(sinks.logToStderr); - BOOST_CHECK(!sinks.logToStdout); - BOOST_CHECK(sinks.logFile.length() == 0); - vector<string> expect=list_of("notice+"); - BOOST_CHECK_EQUAL(expect, opts.selectors); - BOOST_CHECK(opts.time && opts.level); - BOOST_CHECK(!(opts.source || opts.function || opts.thread)); -} - -QPID_AUTO_TEST_CASE(testSelectorFromOptions) { - const char* argv[]={ - 0, - "--log-enable", "error+:foo", - "--log-enable", "debug:bar", - "--log-enable", "info" - }; - qpid::log::Options opts(""); - opts.parse(ARGC(argv), const_cast<char**>(argv)); - vector<string> expect=list_of("error+:foo")("debug:bar")("info"); - BOOST_CHECK_EQUAL(expect, opts.selectors); - Selector s(opts); - BOOST_CHECK(!s.isEnabled(warning, "x")); - BOOST_CHECK(!s.isEnabled(debug, "x")); - BOOST_CHECK(s.isEnabled(debug, "bar")); - BOOST_CHECK(s.isEnabled(error, "foo")); - BOOST_CHECK(s.isEnabled(critical, "foo")); -} - -QPID_AUTO_TEST_CASE(testLoggerStateure) { - Logger& l=Logger::instance(); - ScopedSuppressLogging ls(l); - qpid::log::Options opts("test"); - const char* argv[]={ - 0, - "--log-time", "no", - "--log-source", "yes", - "--log-to-stderr", "no", - "--log-to-file", "logging.tmp", - "--log-enable", "critical" - }; - opts.parse(ARGC(argv), const_cast<char**>(argv)); - l.configure(opts); - QPID_LOG(critical, "foo"); int srcline=__LINE__; - ifstream log("logging.tmp"); - string line; - getline(log, line); - string expect=(format("critical %s:%d: foo")%__FILE__%srcline).str(); - BOOST_CHECK_EQUAL(expect, line); - log.close(); - unlink("logging.tmp"); -} - -QPID_AUTO_TEST_CASE(testQuoteNonPrintable) { - Logger& l=Logger::instance(); - ScopedSuppressLogging ls(l); - qpid::log::Options opts("test"); - opts.time=false; -#ifdef _WIN32 - qpid::log::windows::SinkOptions *sinks = - dynamic_cast<qpid::log::windows::SinkOptions *>(opts.sinkOptions.get()); -#else - qpid::log::posix::SinkOptions *sinks = - dynamic_cast<qpid::log::posix::SinkOptions *>(opts.sinkOptions.get()); -#endif - sinks->logToStderr = false; - sinks->logFile = "logging.tmp"; - l.configure(opts); - - char s[] = "null\0tab\tspace newline\nret\r\x80\x99\xff"; - string str(s, sizeof(s)); - QPID_LOG(critical, str); - ifstream log("logging.tmp"); - string line; - getline(log, line, '\0'); - string expect="critical null\\x00tab\tspace newline\nret\r\\x80\\x99\\xFF\\x00\n"; - BOOST_CHECK_EQUAL(expect, line); - log.close(); - unlink("logging.tmp"); -} - -QPID_AUTO_TEST_SUITE_END() - -}} // namespace qpid::tests diff --git a/cpp/src/tests/long_cluster_tests.py b/cpp/src/tests/long_cluster_tests.py deleted file mode 100755 index f77837f0c4..0000000000 --- a/cpp/src/tests/long_cluster_tests.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import os, signal, sys, unittest -from testlib import TestBaseCluster - -class LongClusterTests(TestBaseCluster): - """Long/Soak cluster tests with async store ability""" - - - def test_LongCluster_01_DummyTest(self): - """Dummy test - a placeholder for the first of the long/soak python cluster tests""" - pass - -# Start the test here - -if __name__ == '__main__': - if os.getenv("STORE_LIB") != None: - print "NOTE: Store enabled for the following tests:" - if not unittest.main(): sys.exit(1) - diff --git a/cpp/src/tests/multiq_perftest b/cpp/src/tests/multiq_perftest deleted file mode 100755 index 10f9edd2a6..0000000000 --- a/cpp/src/tests/multiq_perftest +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -exec `dirname $0`/run_perftest 10000 --mode shared --qt 16 diff --git a/cpp/src/tests/perfdist b/cpp/src/tests/perfdist deleted file mode 100755 index 59548b23f7..0000000000 --- a/cpp/src/tests/perfdist +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -# -# Distributed perftest. -# Runs perftest clients on multiple hosts using ssh. -# - -set -e -usage() { -cat <<EOF -usage: $0 <perftest-args> -- <client-hosts ...> [ --- <broker hosts...> ] -Client & broker hosts can also be set in env vars CLIENTS and BROKERS. - -Run perftest clients on the client hosts against brokers on the broker -hosts Clients are assigned to client hosts round robin: publishers -first, then subscribers. If there are multiple brokers (for cluster -tests) clients connect to them round robin. - -Broker hosts can be listed with -b in perftest-args or after --- -at the end of the arguments. - -Error: $* -EOF -exit 1 -} - -TESTDIR=${TESTDIR:-$PWD} # Absolute path to test exes on all hosts. - -collect() { eval $COLLECT=\""\$$COLLECT $*"\"; } -NPUBS=1 -NSUBS=1 -COLLECT=ARGS -while test $# -gt 0; do - case $1 in - --publish|--subscribe|--setup|--control) usage "Don't pass perftest action flags: $1" ;; - --npubs) collect $1 $2; NPUBS=$2; shift 2 ;; - --nsubs) collect $1 $2; NSUBS=$2; shift 2 ;; - -s|--summary) collect $1; QUIET=yes; shift 1 ;; - -b|--broker) BROKERS="$BROKERS $2"; shift 2;; - --) COLLECT=CLIENTARG; shift ;; - ---) COLLECT=BROKERARG; shift;; - *) collect $1; shift ;; - esac -done - -CLIENTS=${CLIENTARG:-$CLIENTS} -if [ -z "$CLIENTS" ]; then usage "No client hosts listed after --"; fi -BROKERS=${BROKERARG:-$BROKERS} -if [ -z "$BROKERS" ]; then usage "No brokers specified"; fi - -PERFTEST="$TESTDIR/perftest $ARGS" - -CLIENTS=($CLIENTS) -BROKERS=($BROKERS) -start() { - CLIENT=${CLIENTS[i % ${#CLIENTS[*]}]} - BROKER=${BROKERS[i % ${#BROKERS[*]}]} - ARGS="$* --broker $BROKER" - cmd="ssh -n $CLIENT $PERFTEST $ARGS" - test -z "$QUIET" && echo "Client $i: $cmd" - $cmd & -} - -$PERFTEST --setup -b ${BROKERS[0]} -for (( i=0 ; i < $NPUBS ; ++i)); do start --publish; done -for (( ; i < $NPUBS+$NSUBS ; ++i)); do start --subscribe; done -$PERFTEST --control -b ${BROKERS[0]} diff --git a/cpp/src/tests/policy.acl b/cpp/src/tests/policy.acl deleted file mode 100644 index ef46026555..0000000000 --- a/cpp/src/tests/policy.acl +++ /dev/null @@ -1 +0,0 @@ -acl allow all all diff --git a/cpp/src/tests/publish.cpp b/cpp/src/tests/publish.cpp deleted file mode 100644 index 3f456e7588..0000000000 --- a/cpp/src/tests/publish.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <algorithm> -#include <iostream> -#include <memory> -#include <sstream> -#include <vector> - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using namespace std; - -namespace qpid { -namespace tests { - -typedef vector<string> StringSet; - -struct Args : public qpid::TestOptions { - uint size; - uint count; - bool durable; - string destination; - string routingKey; - bool summary; - bool id; - - Args() : size(256), count(1000), durable(true), routingKey("publish-consume"), summary(false), id(false) { - addOptions() - ("size", optValue(size, "N"), "message size") - ("count", optValue(count, "N"), "number of messages to publish") - ("durable", optValue(durable, "yes|no"), "use durable messages") - ("destination", optValue(destination, "<exchange name>"), "destination to publish to") - ("routing-key", optValue(routingKey, "<key>"), "routing key to publish with") - ("summary,s", optValue(summary), "Output only the rate.") - ("id", optValue(id), "Add unique correlation ID"); - } -}; - -Args opts; - -struct Client -{ - Connection connection; - AsyncSession session; - - Client() - { - opts.open(connection); - session = connection.newSession(); - } - - // Cheap hex calculation, avoid expensive ostrstream and string - // creation to generate correlation ids in message loop. - char hex(char i) { return i<10 ? '0'+i : 'A'+i-10; } - void hex(char i, string& s) { - s[0]=hex(i>>24); s[1]=hex(i>>16); s[2]=hex(i>>8); s[3]=i; - } - - void publish() - { - AbsTime begin=now(); - Message msg(string(opts.size, 'X'), opts.routingKey); - string correlationId = "0000"; - if (opts.durable) - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - - for (uint i = 0; i < opts.count; i++) { - if (opts.id) { - hex(i+1, correlationId); - msg.getMessageProperties().setCorrelationId(correlationId); - } - session.messageTransfer(arg::destination=opts.destination, - arg::content=msg, - arg::acceptMode=1); - } - session.sync(); - AbsTime end=now(); - double secs(double(Duration(begin,end))/TIME_SEC); - if (opts.summary) cout << opts.count/secs << endl; - else cout << "Time: " << secs << "s Rate: " << opts.count/secs << endl; - } - - ~Client() - { - try{ - session.close(); - connection.close(); - } catch(const exception& e) { - cout << e.what() << endl; - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - Client client; - client.publish(); - return 0; - } catch(const exception& e) { - cout << e.what() << endl; - } - return 1; -} diff --git a/cpp/src/tests/python_tests b/cpp/src/tests/python_tests deleted file mode 100755 index 0216b5ca7b..0000000000 --- a/cpp/src/tests/python_tests +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the python tests. -source ./test_env.sh -test -d $PYTHON_DIR || { echo "Skipping python tests, no python dir."; exit 0; } -QPID_PORT=${QPID_PORT:-5672} -PYTHON_TESTS=${PYTHON_TESTS:-$*} -FAILING=${FAILING:-/dev/null} - -python $QPID_PYTHON_TEST -m qpid_tests.broker_0_10 -m qpid.tests -b localhost:$QPID_PORT -I $FAILING $PYTHON_TESTS || exit 1 diff --git a/cpp/src/tests/python_tests.ps1 b/cpp/src/tests/python_tests.ps1 deleted file mode 100644 index 9f8b9890c4..0000000000 --- a/cpp/src/tests/python_tests.ps1 +++ /dev/null @@ -1,45 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the python tests; intended to be run by run_test.ps1 which sets up -# QPID_PORT -$srcdir = Split-Path $myInvocation.InvocationName -$PYTHON_DIR = "$srcdir\..\..\..\python" -if (!(Test-Path $PYTHON_DIR -pathType Container)) { - "Skipping python tests as python libs not found" - exit 1 -} - -$PYTHON_TEST_DIR = "$srcdir\..\..\..\tests\src\py" -$QMF_LIB = "$srcdir\..\..\..\extras\qmf\src\py" - -if (Test-Path env:FAILING) { - $fails = "-I $env:FAILING" -} -if (Test-Path env:PYTHON_TESTS) { - $tests = "$env:PYTHON_TESTS" -} -else { - $tests = "$args" -} - -#cd $PYTHON_DIR -$env:PYTHONPATH="$PYTHON_DIR;$PYTHON_TEST_DIR;$env:PYTHONPATH;$QMF_LIB" -python $PYTHON_DIR/qpid-python-test -m qpid_tests.broker_0_10 -m qpid.tests -b localhost:$env:QPID_PORT $fails $tests -exit $LASTEXITCODE diff --git a/cpp/src/tests/qpid-build-rinstall b/cpp/src/tests/qpid-build-rinstall deleted file mode 100755 index 1a92f8750a..0000000000 --- a/cpp/src/tests/qpid-build-rinstall +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under onemake -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run "make install"" locally then copy the install tree to each of $HOSTS -# Must be run in a configured qpid build directory. -# -test -f config.status || { echo "Not in a configured build directory."; usage; } -. src/tests/install_env.sh -set -ex -make && make -j1 install -rsynchosts $QPID_INSTALL_PREFIX diff --git a/cpp/src/tests/qpid-client-test.cpp b/cpp/src/tests/qpid-client-test.cpp deleted file mode 100644 index 2f5e8e5afe..0000000000 --- a/cpp/src/tests/qpid-client-test.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * This file provides a simple test (and example) of basic - * functionality including declaring an exchange and a queue, binding - * these together, publishing a message and receiving that message - * asynchronously. - */ - -#include <iostream> - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/Session.h" -#include "qpid/client/SubscriptionManager.h" - - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; -using std::string; - -namespace qpid { -namespace tests { - -struct Args : public TestOptions { - uint msgSize; - bool verbose; - - Args() : TestOptions("Simple test of Qpid c++ client; sends and receives a single message."), msgSize(26) - { - addOptions() - ("size", optValue(msgSize, "N"), "message size") - ("verbose", optValue(verbose), "print out some status messages"); - } -}; - -const std::string chars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); - -std::string generateData(uint size) -{ - if (size < chars.length()) { - return chars.substr(0, size); - } - std::string data; - for (uint i = 0; i < (size / chars.length()); i++) { - data += chars; - } - data += chars.substr(0, size % chars.length()); - return data; -} - -void print(const std::string& text, const Message& msg) -{ - std::cout << text; - if (msg.getData().size() > 16) { - std::cout << msg.getData().substr(0, 16) << "..."; - } else { - std::cout << msg.getData(); - } - std::cout << std::endl; -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - Args opts; - opts.parse(argc, argv); - - //Connect to the broker: - Connection connection; - opts.open(connection); - if (opts.verbose) std::cout << "Opened connection." << std::endl; - - //Create and open a session on the connection through which - //most functionality is exposed: - Session session = connection.newSession(); - if (opts.verbose) std::cout << "Opened session." << std::endl; - - - //'declare' the exchange and the queue, which will create them - //as they don't exist - session.exchangeDeclare(arg::exchange="MyExchange", arg::type="direct"); - if (opts.verbose) std::cout << "Declared exchange." << std::endl; - session.queueDeclare(arg::queue="MyQueue", arg::autoDelete=true, arg::exclusive=true); - if (opts.verbose) std::cout << "Declared queue." << std::endl; - - //now bind the queue to the exchange - session.exchangeBind(arg::exchange="MyExchange", arg::queue="MyQueue", arg::bindingKey="MyKey"); - if (opts.verbose) std::cout << "Bound queue to exchange." << std::endl; - - //create and send a message to the exchange using the routing - //key we bound our queue with: - Message msgOut(generateData(opts.msgSize)); - msgOut.getDeliveryProperties().setRoutingKey("MyKey"); - session.messageTransfer(arg::destination="MyExchange", arg::content=msgOut, arg::acceptMode=1); - if (opts.verbose) print("Published message: ", msgOut); - - // Using the SubscriptionManager, get the message from the queue. - SubscriptionManager subs(session); - Message msgIn = subs.get("MyQueue"); - if (msgIn.getData() == msgOut.getData()) - if (opts.verbose) std::cout << "Received the exepected message." << std::endl; - - //close the session & connection - session.close(); - if (opts.verbose) std::cout << "Closed session." << std::endl; - connection.close(); - if (opts.verbose) std::cout << "Closed connection." << std::endl; - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - } - return 1; -} diff --git a/cpp/src/tests/qpid-cluster-benchmark b/cpp/src/tests/qpid-cluster-benchmark deleted file mode 100755 index ff787a46dd..0000000000 --- a/cpp/src/tests/qpid-cluster-benchmark +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Benchmark script for comparing cluster performance. - -# Default values -PORT="5672" -COUNT=10000 -FLOW=100 # Flow control limit on queue depth for latency. -REPEAT=10 -QUEUES=4 -CLIENTS=3 - -while getopts "p:c:f:r:t:b:q:c" opt; do - case $opt in - p) PORT=$OPTARG;; - c) COUNT=$OPTARG;; - f) FLOW=$OPTARG;; - r) REPEAT=$OPTARG;; - s) SCALE=$OPTARG;; - b) BROKERS=$OPTARG;; - q) QUEUES=$OPTARG;; - c) CLIENTS=$OPTARG;; - *) echo "Unknown option"; exit 1;; - esac -done - -BROKERS=${BROKERS:-$(echo $HOSTS | sed "s/\>/:$PORT/g;s/ /,/g")} # Broker URL list -BROKER=`echo $BROKERS | awk -F, '{print $1}'` # First broker - -run_test() { echo $*; shift; "$@"; echo; echo; echo; } - -# Multiple pubs/subs connect via multiple brokers (active-active) -run_test "multi-host-thruput" qpid-cpp-benchmark --repeat $REPEAT -b $BROKERS --no-timestamp --summarize -q$QUEUES -s$CLIENTS -r$CLIENTS -m $COUNT - -# Multiple pubs/subs connect via single broker (active-passive) -run_test "single-host-thruput" qpid-cpp-benchmark --repeat $REPEAT -b $BROKER --no-timestamp --summarize -q$QUEUES -s$CLIENTS -r$CLIENTS -m $COUNT - -# Latency -run_test "latency" qpid-cpp-benchmark --repeat $REPEAT -b $BROKER --connection-options '{tcp-nodelay:true}' -m $COUNT --flow-control $FLOW - diff --git a/cpp/src/tests/qpid-cluster-lag.py b/cpp/src/tests/qpid-cluster-lag.py deleted file mode 100755 index 5b24353241..0000000000 --- a/cpp/src/tests/qpid-cluster-lag.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -"""%prog [options] broker... -Check for brokers that lag behind other brokers in a cluster.""" - -import os, os.path, sys, socket, time, re -from qpid.messaging import * -from optparse import OptionParser -from threading import Thread - -class Browser(Thread): - def __init__(self, broker, queue, timeout): - Thread.__init__(self) - self.broker = broker - self.queue = queue - self.timeout = timeout - self.error = None - self.time = None - - def run(self): - try: - self.connection = Connection(self.broker) - self.connection.open() - self.session = self.connection.session() - self.receiver = self.session.receiver("%s;{mode:browse}"%self.queue) - self.msg = self.receiver.fetch(timeout=self.timeout) - self.time = time.time() - if (self.msg.content != self.queue): - raise Exception("Wrong message content, expected '%s' found '%s'"% - (self.queue, self.msg.content)) - except Empty: - self.error = "No message on queue %s"%self.queue - except Exception, e: - self.error = "Error: %s"%e - -def main(argv): - op = OptionParser(usage=__doc__) - op.add_option("--timeout", type="float", default=None, metavar="TIMEOUT", - help="Give up after TIMEOUT milliseconds, default never timeout") - (opts, args) = op.parse_args(argv) - if (len(args) <= 1): op.error("No brokers were specified") - brokers = args[1:] - - # Put a message on a uniquely named queue. - queue = "%s:%s:%s"%(os.path.basename(args[0]), socket.gethostname(), os.getpid()) - connection = Connection(brokers[0]) - connection.open() - session = connection.session() - sender = session.sender( - "%s;{create:always,delete:always,node:{durable:False}}"%queue) - sender.send(Message(content=queue)) - start = time.time() - # Browse for the message on each broker - if opts.timeout: opts.timeout - threads = [Browser(b, queue, opts.timeout) for b in brokers] - for t in threads: t.start() - delays=[] - - for t in threads: - t.join() - if t.error: - delay=t.error - else: - delay = t.time-start - delays.append([delay, t.broker]) - print "%s: %s"%(t.broker,delay) - if delays: - delays.sort() - print "lag: %s (%s-%s)"%(delays[-1][0] - delays[0][0], delays[-1][1], delays[0][1]) - # Clean up - sender.close() - session.close() - connection.close() - -if __name__ == "__main__": sys.exit(main(sys.argv)) diff --git a/cpp/src/tests/qpid-cpp-benchmark b/cpp/src/tests/qpid-cpp-benchmark deleted file mode 100755 index 6138108558..0000000000 --- a/cpp/src/tests/qpid-cpp-benchmark +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/env python -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import optparse, time, qpid.messaging, re -from threading import Thread -from subprocess import Popen, PIPE, STDOUT - -op = optparse.OptionParser(usage="usage: %prog [options]", - description="simple performance benchmarks") -op.add_option("-b", "--broker", default=[], action="append", type="str", - help="url of broker(s) to connect to, round robin on multiple brokers") -op.add_option("-c", "--client-host", default=[], action="append", type="str", - help="host(s) to run clients on via ssh, round robin on mulple hosts") -op.add_option("-q", "--queues", default=1, type="int", metavar="N", - help="create N queues (default %default)") -op.add_option("-s", "--senders", default=1, type="int", metavar="N", - help="start N senders per queue (default %default)") -op.add_option("-r", "--receivers", default=1, type="int", metavar="N", - help="start N receivers per queue (default %default)") -op.add_option("-m", "--messages", default=100000, type="int", metavar="N", - help="send N messages per sender (default %default)") -op.add_option("--queue-name", default="benchmark", metavar="NAME", - help="base name for queues (default %default)") -op.add_option("--send-rate", default=0, metavar="N", - help="send rate limited to N messages/second, 0 means no limit (default %default)") -op.add_option("--receive-rate", default=0, metavar="N", - help="receive rate limited to N messages/second, 0 means no limit (default %default)") -op.add_option("--content-size", default=1024, type="int", metavar="BYTES", - help="message size in bytes (default %default)") -op.add_option("--ack-frequency", default=100, metavar="N", type="int", - help="receiver ack's every N messages, 0 means unconfirmed (default %default)") -op.add_option("--no-report-header", dest="report_header", default=True, - action="store_false", help="don't print header on report") -op.add_option("--summarize", default=False, action="store_true", - help="print summary statistics for multiple senders/receivers: total throughput, average latency") -op.add_option("--repeat", default=1, metavar="N", help="repeat N times", type="int") -op.add_option("--send-option", default=[], action="append", type="str", - help="Additional option for sending addresses") -op.add_option("--receive-option", default=[], action="append", type="str", - help="Additional option for receiving addresses") -op.add_option("--send-arg", default=[], action="append", type="str", - help="Additional argument for qpid-send") -op.add_option("--receive-arg", default=[], action="append", type="str", - help="Additional argument for qpid-receive") -op.add_option("--no-timestamp", dest="timestamp", default=True, - action="store_false", help="don't add a timestamp, no latency results") -op.add_option("--connection-options", type="str", - help="Connection options for senders & receivers") -op.add_option("--flow-control", default=0, type="int", metavar="N", - help="Flow control each sender to limit queue depth to 2*N. 0 means no flow control.") -op.add_option("--durable", default=False, action="store_true", - help="Use durable queues and messages") - -single_quote_re = re.compile("'") -def posix_quote(string): - """ Quote a string for use as an argument in a posix shell""" - return "'" + single_quote_re.sub("\\'", string) + "'"; - -def ssh_command(host, command): - """Convert command into an ssh command on host with quoting""" - return ["ssh", host] + [posix_quote(arg) for arg in command] - -class Clients: - def __init__(self): self.clients=[] - - def add(self, client): - self.clients.append(client) - return client - - def kill(self): - for c in self.clients: - try: c.kill() - except: pass - -clients = Clients() - -def start_receive(queue, index, opts, ready_queue, broker, host): - address_opts=["create:receiver"] + opts.receive_option - if opts.durable: address_opts += ["node:{durable:true}"] - address="%s;{%s}"%(queue,",".join(address_opts)) - msg_total=opts.senders*opts.messages - messages = msg_total/opts.receivers; - if (index < msg_total%opts.receivers): messages += 1 - if (messages == 0): return None - command = ["qpid-receive", - "-b", broker, - "-a", address, - "-m", str(messages), - "--forever", - "--print-content=no", - "--receive-rate", str(opts.receive_rate), - "--report-total", - "--ack-frequency", str(opts.ack_frequency), - "--ready-address", ready_queue, - "--report-header=no" - ] - command += opts.receive_arg - if opts.connection_options: - command += ["--connection-options",opts.connection_options] - if host: command = ssh_command(host, command) - return clients.add(Popen(command, stdout=PIPE)) - -def start_send(queue, opts, broker, host): - address="%s;{%s}"%(queue,",".join(opts.send_option)) - command = ["qpid-send", - "-b", broker, - "-a", address, - "--messages", str(opts.messages), - "--content-size", str(opts.content_size), - "--send-rate", str(opts.send_rate), - "--report-total", - "--report-header=no", - "--timestamp=%s"%(opts.timestamp and "yes" or "no"), - "--sequence=no", - "--flow-control", str(opts.flow_control), - "--durable", str(opts.durable) - ] - command += opts.send_arg - if opts.connection_options: - command += ["--connection-options",opts.connection_options] - if host: command = ssh_command(host, command) - return clients.add(Popen(command, stdout=PIPE)) - -def first_line(p): - out,err=p.communicate() - if p.returncode != 0: raise Exception("Process failed: %s"%(out.strip())) - return out.split("\n")[0] - -def delete_queues(queues, broker): - c = qpid.messaging.Connection(broker) - c.open() - for q in queues: - try: - s = c.session() - snd = s.sender("%s;{delete:always}"%(q)) - snd.close() - s.sync() - except qpid.messaging.exceptions.NotFound: pass # Ignore "no such queue" - c.close() - -def print_header(timestamp): - if timestamp: latency_header="\tl-min\tl-max\tl-avg" - else: latency_header="" - print "send-tp\t\trecv-tp%s"%latency_header - -def parse(parser, lines): # Parse sender/receiver output - for l in lines: - fn_val = zip(parser, l) - return [map(lambda p: p[0](p[1]), zip(parser,line.split())) for line in lines] - -def parse_senders(senders): - return parse([int],[first_line(p) for p in senders]) - -def parse_receivers(receivers): - return parse([int,float,float,float],[first_line(p) for p in receivers if p]) - -def print_data(send_stats, recv_stats): - for send,recv in map(None, send_stats, recv_stats): - line="" - if send: line += "%d"%send[0] - if recv: - line += "\t\t%d"%recv[0] - if len(recv) == 4: line += "\t%.2f\t%.2f\t%.2f"%tuple(recv[1:]) - print line - -def print_summary(send_stats, recv_stats): - def avg(s): sum(s) / len(s) - send_tp = sum([l[0] for l in send_stats]) - recv_tp = sum([l[0] for l in recv_stats]) - summary = "%d\t\t%d"%(send_tp, recv_tp) - if recv_stats and len(recv_stats[0]) == 4: - l_min = sum(l[1] for l in recv_stats)/len(recv_stats) - l_max = sum(l[2] for l in recv_stats)/len(recv_stats) - l_avg = sum(l[3] for l in recv_stats)/len(recv_stats) - summary += "\t%.2f\t%.2f\t%.2f"%(l_min, l_max, l_avg) - print summary - - -class ReadyReceiver: - """A receiver for ready messages""" - def __init__(self, queue, broker): - delete_queues([queue], broker) - self.connection = qpid.messaging.Connection(broker) - self.connection.open() - self.receiver = self.connection.session().receiver( - "%s;{create:receiver,delete:receiver,node:{durable:false}}"%(queue)) - self.receiver.session.sync() - self.timeout=10 - - def wait(self, receivers): - try: - for i in receivers: self.receiver.fetch(self.timeout) - self.connection.close() - except qpid.messaging.Empty: - for r in receivers: - if (r.poll() is not None): - out,err=r.communicate() - raise Exception("Receiver error: %s"%(out)) - raise Exception("Timed out waiting for receivers to be ready") - -def flatten(l): return sum(map(lambda s: s.split(","), l),[]) - -class RoundRobin: - def __init__(self,items): - self.items = items - self.index = 0 - - def next(self): - if not self.items: return None - ret = self.items[self.index] - self.index = (self.index+1)%len(self.items) - return ret - -def main(): - opts, args = op.parse_args() - if not opts.broker: opts.broker = ["127.0.0.1"] # Deafult to local broker - opts.broker = flatten(opts.broker) - opts.client_host = flatten(opts.client_host) - brokers = RoundRobin(opts.broker) - client_hosts = RoundRobin(opts.client_host) - send_out = "" - receive_out = "" - ready_queue="%s-ready"%(opts.queue_name) - queues = ["%s-%s"%(opts.queue_name, i) for i in xrange(opts.queues)] - try: - for i in xrange(opts.repeat): - delete_queues(queues, opts.broker[0]) - ready_receiver = ReadyReceiver(ready_queue, opts.broker[0]) - receivers = [start_receive(q, j, opts, ready_queue, brokers.next(), client_hosts.next()) - for q in queues for j in xrange(opts.receivers)] - ready_receiver.wait(filter(None, receivers)) # Wait for receivers to be ready. - senders = [start_send(q, opts,brokers.next(), client_hosts.next()) - for q in queues for j in xrange(opts.senders)] - if opts.report_header and i == 0: print_header(opts.timestamp) - send_stats=parse_senders(senders) - recv_stats=parse_receivers(receivers) - if opts.summarize: print_summary(send_stats, recv_stats) - else: print_data(send_stats, recv_stats) - delete_queues(queues, opts.broker[0]) - finally: clients.kill() # No strays - -if __name__ == "__main__": main() - diff --git a/cpp/src/tests/qpid-ctrl b/cpp/src/tests/qpid-ctrl deleted file mode 100755 index 4246c57898..0000000000 --- a/cpp/src/tests/qpid-ctrl +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import optparse -from qpid.messaging import * -from qpid.util import URL -from qpid.log import enable, DEBUG, WARN - -def nameval(st): - idx = st.find("=") - if idx >= 0: - name = st[0:idx] - value = st[idx+1:] - else: - name = st - value = None - return name, value - -def list_map_entries(m): - r = "" - for t in m: - r += "%s=%s " % (t, m[t]) - return r - -def get_qmfv2_result(m): - if m.properties['x-amqp-0-10.app-id'] == 'qmf2': - if m.properties['qmf.opcode'] == '_method_response': - return m.content['_arguments'] - elif m.properties['qmf.opcode'] == '_exception': - raise Exception("Error: %s" % list_map_entries(m.content['_values'])) - else: raise Exception("Invalid response received, unexpected opcode: %s" % m) - else: raise Exception("Invalid response received, not a qmfv2 method: %s" % m) - - -parser = optparse.OptionParser(usage="usage: %prog [options] COMMAND ...", - description="Invoke the specified command.") -parser.add_option("-b", "--broker", default="localhost", - help="connect to specified BROKER (default %default)") -parser.add_option("-c", "--class", dest="qmfclass", default="broker", - help="class of object on which command is being invoked (default %default)") -parser.add_option("-p", "--package", default="org.apache.qpid.broker", - help="package of object on which command is being invoked (default %default)") -parser.add_option("-i", "--id", default="amqp-broker", - help="identifier of object on which command is being invoked (default %default)") -parser.add_option("-a", "--address", default="qmf.default.direct/broker", - help="address to send commands to (default %default)") -parser.add_option("-t", "--timeout", type="float", default=5, - help="timeout in seconds to wait for response before exiting (default %default)") -parser.add_option("-v", dest="verbose", action="store_true", - help="enable logging") - -opts, args = parser.parse_args() - -if opts.verbose: - enable("qpid", DEBUG) -else: - enable("qpid", WARN) - -if args: - command = args.pop(0) -else: - parser.error("command is required") - - -conn = Connection(opts.broker) -try: - conn.open() - ssn = conn.session() - snd = ssn.sender(opts.address) - reply_to = "qmf.default.direct/%s; {node: {type: topic}}" % str(uuid4()) - rcv = ssn.receiver(reply_to) - - object_name = "%s:%s:%s" % (opts.package, opts.qmfclass, opts.id) - method_name = command - arguments = {} - for a in args: - name, val = nameval(a) - if val[0] == '{' or val[0] == '[': - arguments[name] = eval(val) - else: - arguments[name] = val - content = { - "_object_id": {"_object_name": object_name}, - "_method_name": method_name, - "_arguments": arguments - } - msg = Message(reply_to=reply_to, content=content) - msg.properties["x-amqp-0-10.app-id"] = "qmf2" - msg.properties["qmf.opcode"] = "_method_request" - snd.send(msg) - - try: - print list_map_entries(get_qmfv2_result(rcv.fetch(timeout=opts.timeout))) - except Empty: - print "No response received!" - except Exception, e: - print e -except ReceiverError, e: - print e -except KeyboardInterrupt: - pass - -conn.close() diff --git a/cpp/src/tests/qpid-latency-test.cpp b/cpp/src/tests/qpid-latency-test.cpp deleted file mode 100644 index 20eb4568f3..0000000000 --- a/cpp/src/tests/qpid-latency-test.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -#include <algorithm> -#include <limits> -#include <iostream> -#include <memory> -#include <sstream> -#include <vector> - -#include "TestOptions.h" -#include "qpid/sys/Thread.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/sys/Time.h" - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using std::string; - -namespace qpid { -namespace tests { - -typedef std::vector<std::string> StringSet; - -struct Args : public qpid::TestOptions { - uint size; - uint count; - uint rate; - bool sync; - uint reportFrequency; - uint timeLimit; - uint concurrentConnections; - uint prefetch; - uint ack; - bool cumulative; - bool csv; - bool durable; - string base; - bool singleConnect; - - Args() : size(256), count(1000), rate(0), reportFrequency(1000), - timeLimit(0), concurrentConnections(1), - prefetch(100), ack(0), - durable(false), base("latency-test"), singleConnect(false) - - { - addOptions() - - ("size", optValue(size, "N"), "message size") - ("concurrentTests", optValue(concurrentConnections, "N"), "number of concurrent test setups, will create another publisher,\ - subcriber, queue, and connections") - ("single-connection", optValue(singleConnect, "yes|no"), "Use one connection for multiple sessions.") - ("count", optValue(count, "N"), "number of messages to send") - ("rate", optValue(rate, "N"), "target message rate (causes count to be ignored)") - ("sync", optValue(sync), "send messages synchronously") - ("report-frequency", optValue(reportFrequency, "N"), - "number of milliseconds to wait between reports (ignored unless rate specified)") - ("time-limit", optValue(timeLimit, "N"), - "test duration, in seconds") - ("prefetch", optValue(prefetch, "N"), "prefetch count (0 implies no flow control, and no acking)") - ("ack", optValue(ack, "N"), "Ack frequency in messages (defaults to half the prefetch value)") - ("durable", optValue(durable, "yes|no"), "use durable messages") - ("csv", optValue(csv), "print stats in csv format (rate,min,max,avg)") - ("cumulative", optValue(cumulative), "cumulative stats in csv format") - ("queue-base-name", optValue(base, "<name>"), "base name for queues"); - } -}; - -const std::string chars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); - -Args opts; -double c_min, c_avg, c_max; -Connection globalConnection; - -uint64_t current_time() -{ - Duration t(EPOCH, now()); - return t; -} - -struct Stats -{ - Mutex lock; - uint count; - double minLatency; - double maxLatency; - double totalLatency; - - Stats(); - void update(double l); - void print(); - void reset(); -}; - -class Client : public Runnable -{ -protected: - Connection* connection; - Connection localConnection; - AsyncSession session; - Thread thread; - string queue; - -public: - Client(const string& q); - virtual ~Client(); - - void start(); - void join(); - void run(); - virtual void test() = 0; -}; - -class Receiver : public Client, public MessageListener -{ - SubscriptionManager mgr; - uint count; - Stats& stats; - -public: - Receiver(const string& queue, Stats& stats); - void test(); - void received(Message& msg); - Stats getStats(); - uint getCount() { return count; } - void stop() { mgr.stop(); mgr.cancel(queue); } -}; - - -class Sender : public Client -{ - string generateData(uint size); - void sendByRate(); - void sendByCount(); - Receiver& receiver; - const string data; - -public: - Sender(const string& queue, Receiver& receiver); - void test(); -}; - - -class Test -{ - const string queue; - Stats stats; - Receiver receiver; - Sender sender; - AbsTime begin; - -public: - Test(const string& q) : queue(q), receiver(queue, stats), sender(queue, receiver), begin(now()) {} - void start(); - void join(); - void report(); -}; - - -Client::Client(const string& q) : queue(q) -{ - if (opts.singleConnect){ - connection = &globalConnection; - if (!globalConnection.isOpen()) opts.open(globalConnection); - }else{ - connection = &localConnection; - opts.open(localConnection); - } - session = connection->newSession(); -} - -void Client::start() -{ - thread = Thread(this); -} - -void Client::join() -{ - thread.join(); -} - -void Client::run() -{ - try{ - test(); - } catch(const std::exception& e) { - std::cout << "Error in receiver: " << e.what() << std::endl; - } -} - -Client::~Client() -{ - try{ - session.close(); - connection->close(); - } catch(const std::exception& e) { - std::cout << "Error in receiver: " << e.what() << std::endl; - } -} - -Receiver::Receiver(const string& q, Stats& s) : Client(q), mgr(session), count(0), stats(s) -{ - session.queueDeclare(arg::queue=queue, arg::durable=opts.durable, arg::autoDelete=true); - uint msgCount = session.queueQuery(arg::queue=queue).get().getMessageCount(); - if (msgCount) { - std::cout << "Warning: found " << msgCount << " msgs on " << queue << ". Purging..." << std::endl; - session.queuePurge(arg::queue=queue); - session.sync(); - } - SubscriptionSettings settings; - if (opts.prefetch) { - settings.autoAck = (opts.ack ? opts.ack : (opts.prefetch / 2)); - settings.flowControl = FlowControl::messageWindow(opts.prefetch); - } else { - settings.acceptMode = ACCEPT_MODE_NONE; - settings.flowControl = FlowControl::unlimited(); - } - mgr.subscribe(*this, queue, settings); -} - -void Receiver::test() -{ - mgr.run(); - mgr.cancel(queue); -} - -void Receiver::received(Message& msg) -{ - ++count; - uint64_t receivedAt = current_time(); - uint64_t sentAt = msg.getDeliveryProperties().getTimestamp(); - - stats.update(((double) (receivedAt - sentAt)) / TIME_MSEC); - - if (!opts.rate && count >= opts.count) { - mgr.stop(); - } -} - -void Stats::update(double latency) -{ - Mutex::ScopedLock l(lock); - count++; - minLatency = std::min(minLatency, latency); - maxLatency = std::max(maxLatency, latency); - totalLatency += latency; -} - -Stats::Stats() : count(0), minLatency(std::numeric_limits<double>::max()), maxLatency(0), totalLatency(0) {} - -void Stats::print() -{ - static bool already_have_stats = false; - uint value; - - if (opts.rate) - value = opts.rate; - else - value = opts.count; - Mutex::ScopedLock l(lock); - double aux_avg = (totalLatency / count); - if (!opts.cumulative) { - if (!opts.csv) { - if (count) { - std::cout << "Latency(ms): min=" << minLatency << ", max=" << - maxLatency << ", avg=" << aux_avg; - } else { - std::cout << "Stalled: no samples for interval"; - } - } else { - if (count) { - std::cout << value << "," << minLatency << "," << maxLatency << - "," << aux_avg; - } else { - std::cout << value << "," << minLatency << "," << maxLatency << - ", Stalled"; - } - } - } else { - if (count) { - if (already_have_stats) { - c_avg = (c_min + aux_avg) / 2; - if (c_min > minLatency) c_min = minLatency; - if (c_max < maxLatency) c_max = maxLatency; - } else { - c_avg = aux_avg; - c_min = minLatency; - c_max = maxLatency; - already_have_stats = true; - } - std::cout << value << "," << c_min << "," << c_max << - "," << c_avg; - } else { - std::cout << "Stalled: no samples for interval"; - } - } -} - -void Stats::reset() -{ - Mutex::ScopedLock l(lock); - count = 0; - totalLatency = maxLatency = 0; - minLatency = std::numeric_limits<double>::max(); -} - -Sender::Sender(const string& q, Receiver& receiver) : Client(q), receiver(receiver), data(generateData(opts.size)) {} - -void Sender::test() -{ - if (opts.rate) sendByRate(); - else sendByCount(); -} - -void Sender::sendByCount() -{ - Message msg(data, queue); - if (opts.durable) { - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - - for (uint i = 0; i < opts.count; i++) { - uint64_t sentAt(current_time()); - msg.getDeliveryProperties().setTimestamp(sentAt); - async(session).messageTransfer(arg::content=msg, arg::acceptMode=1); - if (opts.sync) session.sync(); - } - session.sync(); -} - -void Sender::sendByRate() -{ - Message msg(data, queue); - if (opts.durable) { - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - uint64_t interval = TIME_SEC/opts.rate; - int64_t timeLimit = opts.timeLimit * TIME_SEC; - uint64_t sent = 0, missedRate = 0; - AbsTime start = now(); - while (true) { - AbsTime sentAt=now(); - msg.getDeliveryProperties().setTimestamp(Duration(EPOCH, sentAt)); - async(session).messageTransfer(arg::content=msg, arg::acceptMode=1); - if (opts.sync) session.sync(); - ++sent; - AbsTime waitTill(start, sent*interval); - Duration delay(sentAt, waitTill); - if (delay < 0) - ++missedRate; - else - sys::usleep(delay / TIME_USEC); - if (timeLimit != 0 && Duration(start, now()) > timeLimit) { - session.sync(); - receiver.stop(); - break; - } - } -} - -string Sender::generateData(uint size) -{ - if (size < chars.length()) { - return chars.substr(0, size); - } - std::string data; - for (uint i = 0; i < (size / chars.length()); i++) { - data += chars; - } - data += chars.substr(0, size % chars.length()); - return data; -} - - -void Test::start() -{ - receiver.start(); - begin = AbsTime(now()); - sender.start(); -} - -void Test::join() -{ - sender.join(); - receiver.join(); - AbsTime end = now(); - Duration time(begin, end); - double msecs(time / TIME_MSEC); - if (!opts.csv) { - std::cout << "Sent " << receiver.getCount() << " msgs through " << queue - << " in " << msecs << "ms (" << (receiver.getCount() * 1000 / msecs) << " msgs/s) "; - } - stats.print(); - std::cout << std::endl; -} - -void Test::report() -{ - stats.print(); - std::cout << std::endl; - stats.reset(); -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - if (opts.cumulative) - opts.csv = true; - - Connection localConnection; - AsyncSession session; - - boost::ptr_vector<Test> tests(opts.concurrentConnections); - for (uint i = 0; i < opts.concurrentConnections; i++) { - std::ostringstream out; - out << opts.base << "-" << (i+1); - tests.push_back(new Test(out.str())); - } - for (boost::ptr_vector<Test>::iterator i = tests.begin(); i != tests.end(); i++) { - i->start(); - } - if (opts.rate && !opts.timeLimit) { - while (true) { - qpid::sys::usleep(opts.reportFrequency * 1000); - //print latency report: - for (boost::ptr_vector<Test>::iterator i = tests.begin(); i != tests.end(); i++) { - i->report(); - } - } - } else { - for (boost::ptr_vector<Test>::iterator i = tests.begin(); i != tests.end(); i++) { - i->join(); - } - } - - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - } - return 1; -} diff --git a/cpp/src/tests/qpid-perftest.cpp b/cpp/src/tests/qpid-perftest.cpp deleted file mode 100644 index 8a5cf05775..0000000000 --- a/cpp/src/tests/qpid-perftest.cpp +++ /dev/null @@ -1,746 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "TestOptions.h" - -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Completion.h" -#include "qpid/client/Message.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" - -#include <boost/lexical_cast.hpp> -#include <boost/bind.hpp> -#include <boost/function.hpp> -#include <boost/ptr_container/ptr_vector.hpp> - -#include <iostream> -#include <sstream> -#include <numeric> -#include <algorithm> -#include <math.h> - - -using namespace std; -using namespace qpid; -using namespace client; -using namespace sys; -using boost::lexical_cast; -using boost::bind; - -namespace qpid { -namespace tests { - -enum Mode { SHARED, FANOUT, TOPIC }; -const char* modeNames[] = { "shared", "fanout", "topic" }; - -// istream/ostream ops so Options can read/display Mode. -istream& operator>>(istream& in, Mode& mode) { - string s; - in >> s; - int i = find(modeNames, modeNames+3, s) - modeNames; - if (i >= 3) throw Exception("Invalid mode: "+s); - mode = Mode(i); - return in; -} - -ostream& operator<<(ostream& out, Mode mode) { - return out << modeNames[mode]; -} - - -struct Opts : public TestOptions { - - // Actions - bool setup, control, publish, subscribe; - - // Queue policy - uint32_t queueMaxCount; - uint64_t queueMaxSize; - std::string baseName; - bool queueDurable; - - // Publisher - size_t pubs; - size_t count ; - size_t size; - bool confirm; - bool durable; - bool uniqueData; - bool syncPub; - - // Subscriber - size_t subs; - size_t ack; - - // General - size_t qt; - bool singleConnect; - size_t iterations; - Mode mode; - bool summary; - uint32_t intervalSub; - uint32_t intervalPub; - size_t tx; - size_t txPub; - size_t txSub; - bool commitAsync; - - static const std::string helpText; - - Opts() : - TestOptions(helpText), - setup(false), control(false), publish(false), subscribe(false), baseName("qpid-perftest"), - pubs(1), count(500000), size(1024), confirm(true), durable(false), uniqueData(false), syncPub(false), - subs(1), ack(0), - qt(1),singleConnect(false), iterations(1), mode(SHARED), summary(false), - intervalSub(0), intervalPub(0), tx(0), txPub(0), txSub(0), commitAsync(false) - { - addOptions() - ("setup", optValue(setup), "Create shared queues.") - ("control", optValue(control), "Run test, print report.") - ("publish", optValue(publish), "Publish messages.") - ("subscribe", optValue(subscribe), "Subscribe for messages.") - - ("mode", optValue(mode, "shared|fanout|topic"), "Test mode." - "\nshared: --qt queues, --npubs publishers and --nsubs subscribers per queue.\n" - "\nfanout: --npubs publishers, --nsubs subscribers, fanout exchange." - "\ntopic: --qt topics, --npubs publishers and --nsubs subscribers per topic.\n") - - ("npubs", optValue(pubs, "N"), "Create N publishers.") - ("count", optValue(count, "N"), "Each publisher sends N messages.") - ("size", optValue(size, "BYTES"), "Size of messages in bytes.") - ("pub-confirm", optValue(confirm, "yes|no"), "Publisher use confirm-mode.") - ("durable", optValue(durable, "yes|no"), "Publish messages as durable.") - ("unique-data", optValue(uniqueData, "yes|no"), "Make data for each message unique.") - ("sync-publish", optValue(syncPub, "yes|no"), "Wait for confirmation of each message before sending the next one.") - - ("nsubs", optValue(subs, "N"), "Create N subscribers.") - ("sub-ack", optValue(ack, "N"), "N>0: Subscriber acks batches of N.\n" - "N==0: Subscriber uses unconfirmed mode") - - ("qt", optValue(qt, "N"), "Create N queues or topics.") - ("single-connection", optValue(singleConnect, "yes|no"), "Use one connection for multiple sessions.") - - ("iterations", optValue(iterations, "N"), "Desired number of iterations of the test.") - ("summary,s", optValue(summary), "Summary output: pubs/sec subs/sec transfers/sec Mbytes/sec") - - ("queue-max-count", optValue(queueMaxCount, "N"), "queue policy: count to trigger 'flow to disk'") - ("queue-max-size", optValue(queueMaxSize, "N"), "queue policy: accumulated size to trigger 'flow to disk'") - ("base-name", optValue(baseName, "NAME"), "base name used for queues or topics") - ("queue-durable", optValue(queueDurable, "N"), "Make queue durable (implied if durable set)") - - ("interval_sub", optValue(intervalSub, "ms"), ">=0 delay between msg consume") - ("interval_pub", optValue(intervalPub, "ms"), ">=0 delay between msg publish") - - ("tx", optValue(tx, "N"), "if non-zero, the transaction batch size for publishing and consuming") - ("pub-tx", optValue(txPub, "N"), "if non-zero, the transaction batch size for publishing") - ("async-commit", optValue(commitAsync, "yes|no"), "Don't wait for completion of commit") - ("sub-tx", optValue(txSub, "N"), "if non-zero, the transaction batch size for consuming"); - } - - // Computed values - size_t totalPubs; - size_t totalSubs; - size_t transfers; - size_t subQuota; - - void parse(int argc, char** argv) { - TestOptions::parse(argc, argv); - switch (mode) { - case SHARED: - if (count % subs) { - count += subs - (count % subs); - cout << "WARNING: Adjusted --count to " << count - << " the nearest multiple of --nsubs" << endl; - } - totalPubs = pubs*qt; - totalSubs = subs*qt; - subQuota = (pubs*count)/subs; - break; - case FANOUT: - if (qt != 1) cerr << "WARNING: Fanout mode, ignoring --qt=" - << qt << endl; - qt=1; - totalPubs = pubs; - totalSubs = subs; - subQuota = totalPubs*count; - break; - case TOPIC: - totalPubs = pubs*qt; - totalSubs = subs*qt; - subQuota = pubs*count; - break; - } - transfers=(totalPubs*count) + (totalSubs*subQuota); - if (tx) { - if (txPub) { - cerr << "WARNING: Using overriden tx value for publishers: " << txPub << std::endl; - } else { - txPub = tx; - } - if (txSub) { - cerr << "WARNING: Using overriden tx value for subscribers: " << txSub << std::endl; - } else { - txSub = tx; - } - } - } -}; - -const std::string Opts::helpText= -"There are two ways to use qpid-perftest: single process or multi-process.\n\n" -"If none of the --setup, --publish, --subscribe or --control options\n" -"are given qpid-perftest will run a single-process test.\n" -"For a multi-process test first run:\n" -" qpid-perftest --setup <other options>\n" -"and wait for it to complete. The remaining process should run concurrently::\n" -"Run --npubs times: qpid-perftest --publish <other options>\n" -"Run --nsubs times: qpid-perftest --subscribe <other options>\n" -"Run once: qpid-perftest --control <other options>\n" -"Note the <other options> must be identical for all processes.\n"; - -Opts opts; -Connection globalConnection; - -std::string fqn(const std::string& name) -{ - ostringstream fqn; - fqn << opts.baseName << "_" << name; - return fqn.str(); -} - -struct Client : public Runnable { - Connection* connection; - Connection localConnection; - AsyncSession session; - Thread thread; - - Client() { - if (opts.singleConnect){ - connection = &globalConnection; - if (!globalConnection.isOpen()) opts.open(globalConnection); - }else{ - connection = &localConnection; - opts.open(localConnection); - } - session = connection->newSession(); - } - - ~Client() { - try { - if (connection->isOpen()) { - session.close(); - connection->close(); - } - } catch (const std::exception& e) { - std::cerr << "Error in shutdown: " << e.what() << std::endl; - } - } -}; - -struct Setup : public Client { - - void queueInit(string name, bool durable=false, const framing::FieldTable& settings=framing::FieldTable()) { - session.queueDeclare(arg::queue=name, arg::durable=durable, arg::arguments=settings); - session.queuePurge(arg::queue=name); - session.sync(); - } - - void run() { - queueInit(fqn("pub_start")); - queueInit(fqn("pub_done")); - queueInit(fqn("sub_ready")); - queueInit(fqn("sub_done")); - if (opts.iterations > 1) queueInit(fqn("sub_iteration")); - if (opts.mode==SHARED) { - framing::FieldTable settings;//queue policy settings - settings.setInt("qpid.max_count", opts.queueMaxCount); - settings.setInt("qpid.max_size", opts.queueMaxSize); - for (size_t i = 0; i < opts.qt; ++i) { - ostringstream qname; - qname << opts.baseName << i; - queueInit(qname.str(), opts.durable || opts.queueDurable, settings); - } - } - } -}; - -void expect(string actual, string expect) { - if (expect != actual) - throw Exception("Expecting "+expect+" but received "+actual); - -} - -double secs(Duration d) { return double(d)/TIME_SEC; } -double secs(AbsTime start, AbsTime finish) { - return secs(Duration(start,finish)); -} - - -// Collect rates & print stats. -class Stats { - vector<double> values; - double sum; - - public: - Stats() : sum(0) {} - - // Functor to collect rates. - void operator()(const string& data) { - try { - double d=lexical_cast<double>(data); - values.push_back(d); - sum += d; - } catch (const std::exception&) { - throw Exception("Bad report: "+data); - } - } - - double mean() const { - return sum/values.size(); - } - - double stdev() const { - if (values.size() <= 1) return 0; - double avg = mean(); - double ssq = 0; - for (vector<double>::const_iterator i = values.begin(); - i != values.end(); ++i) { - double x=*i; - x -= avg; - ssq += x*x; - } - return sqrt(ssq/(values.size()-1)); - } - - ostream& print(ostream& out) { - ostream_iterator<double> o(out, "\n"); - copy(values.begin(), values.end(), o); - out << "Average: " << mean(); - if (values.size() > 1) - out << " (std.dev. " << stdev() << ")"; - return out << endl; - } -}; - - -// Manage control queues, collect and print reports. -struct Controller : public Client { - - SubscriptionManager subs; - - Controller() : subs(session) {} - - /** Process messages from queue by applying a functor. */ - void process(size_t n, string queue, - boost::function<void (const string&)> msgFn) - { - if (!opts.summary) - cout << "Processing " << n << " messages from " - << queue << " " << flush; - LocalQueue lq; - subs.setFlowControl(n, SubscriptionManager::UNLIMITED, false); - subs.subscribe(lq, queue); - for (size_t i = 0; i < n; ++i) { - if (!opts.summary) cout << "." << flush; - msgFn(lq.pop().getData()); - } - if (!opts.summary) cout << " done." << endl; - } - - void process(size_t n, LocalQueue lq, string queue, - boost::function<void (const string&)> msgFn) - { - session.messageFlow(queue, 0, n); - if (!opts.summary) - cout << "Processing " << n << " messages from " - << queue << " " << flush; - for (size_t i = 0; i < n; ++i) { - if (!opts.summary) cout << "." << flush; - msgFn(lq.pop().getData()); - } - if (!opts.summary) cout << " done." << endl; - } - - void send(size_t n, string queue, string data) { - if (!opts.summary) - cout << "Sending " << data << " " << n << " times to " << queue - << endl; - Message msg(data, queue); - for (size_t i = 0; i < n; ++i) - session.messageTransfer(arg::content=msg, arg::acceptMode=1); - } - - void run() { // Controller - try { - // Wait for subscribers to be ready. - process(opts.totalSubs, fqn("sub_ready"), bind(expect, _1, "ready")); - - LocalQueue pubDone; - LocalQueue subDone; - subs.setFlowControl(0, SubscriptionManager::UNLIMITED, false); - subs.subscribe(pubDone, fqn("pub_done")); - subs.subscribe(subDone, fqn("sub_done")); - - double txrateTotal(0); - double mbytesTotal(0); - double pubRateTotal(0); - double subRateTotal(0); - - for (size_t j = 0; j < opts.iterations; ++j) { - AbsTime start=now(); - send(opts.totalPubs, fqn("pub_start"), "start"); // Start publishers - if (j) { - send(opts.totalPubs, fqn("sub_iteration"), "next"); // Start subscribers on next iteration - } - - Stats pubRates; - Stats subRates; - - process(opts.totalPubs, pubDone, fqn("pub_done"), boost::ref(pubRates)); - process(opts.totalSubs, subDone, fqn("sub_done"), boost::ref(subRates)); - - AbsTime end=now(); - double time=secs(start, end); - if (time <= 0.0) { - throw Exception("ERROR: Test completed in zero seconds. Try again with a larger message count."); - } - double txrate=opts.transfers/time; - double mbytes=(txrate*opts.size)/(1024*1024); - - if (!opts.summary) { - cout << endl << "Total " << opts.transfers << " transfers of " - << opts.size << " bytes in " - << time << " seconds." << endl; - cout << endl << "Publish transfers/sec: " << endl; - pubRates.print(cout); - cout << endl << "Subscribe transfers/sec: " << endl; - subRates.print(cout); - cout << endl - << "Total transfers/sec: " << txrate << endl - << "Total Mbytes/sec: " << mbytes << endl; - } - else { - cout << pubRates.mean() << "\t" - << subRates.mean() << "\t" - << txrate << "\t" - << mbytes << endl; - } - - txrateTotal += txrate; - mbytesTotal += mbytes; - pubRateTotal += pubRates.mean(); - subRateTotal += subRates.mean(); - } - if (opts.iterations > 1) { - cout << "Averages: "<< endl - << (pubRateTotal / opts.iterations) << "\t" - << (subRateTotal / opts.iterations) << "\t" - << (txrateTotal / opts.iterations) << "\t" - << (mbytesTotal / opts.iterations) << endl; - } - } - catch (const std::exception& e) { - cout << "Controller exception: " << e.what() << endl; - } - } -}; - - -struct PublishThread : public Client { - string destination; - string routingKey; - - PublishThread() {}; - - PublishThread(string key, string dest=string()) { - destination=dest; - routingKey=key; - } - - void run() { // Publisher - try { - string data; - size_t offset(0); - if (opts.uniqueData) { - offset = 5; - data += "data:";//marker (requested for latency testing tool scripts) - data += string(sizeof(size_t), 'X');//space for seq no - data += session.getId().str(); - if (opts.size > data.size()) { - data += string(opts.size - data.size(), 'X'); - } else if(opts.size < data.size()) { - cout << "WARNING: Increased --size to " << data.size() - << " to honour --unique-data" << endl; - } - } else { - size_t msgSize=max(opts.size, sizeof(size_t)); - data = string(msgSize, 'X'); - } - - Message msg(data, routingKey); - if (opts.durable) - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - - - if (opts.txPub){ - session.txSelect(); - } - SubscriptionManager subs(session); - LocalQueue lq; - subs.setFlowControl(1, SubscriptionManager::UNLIMITED, true); - subs.subscribe(lq, fqn("pub_start")); - - for (size_t j = 0; j < opts.iterations; ++j) { - expect(lq.pop().getData(), "start"); - AbsTime start=now(); - for (size_t i=0; i<opts.count; i++) { - // Stamp the iteration into the message data, avoid - // any heap allocation. - const_cast<std::string&>(msg.getData()).replace(offset, sizeof(size_t), - reinterpret_cast<const char*>(&i), sizeof(size_t)); - if (opts.syncPub) { - sync(session).messageTransfer( - arg::destination=destination, - arg::content=msg, - arg::acceptMode=1); - } else { - session.messageTransfer( - arg::destination=destination, - arg::content=msg, - arg::acceptMode=1); - } - if (opts.txPub && ((i+1) % opts.txPub == 0)){ - if (opts.commitAsync){ - session.txCommit(); - } else { - sync(session).txCommit(); - } - } - if (opts.intervalPub) - qpid::sys::usleep(opts.intervalPub*1000); - } - if (opts.confirm) session.sync(); - AbsTime end=now(); - double time=secs(start,end); - if (time <= 0.0) { - throw Exception("ERROR: Test completed in zero seconds. Try again with a larger message count."); - } - - // Send result to controller. - Message report(lexical_cast<string>(opts.count/time), fqn("pub_done")); - session.messageTransfer(arg::content=report, arg::acceptMode=1); - if (opts.txPub){ - sync(session).txCommit(); - } - } - session.close(); - } - catch (const std::exception& e) { - cout << "PublishThread exception: " << e.what() << endl; - } - } -}; - -struct SubscribeThread : public Client { - - string queue; - - SubscribeThread() {} - - SubscribeThread(string q) { queue = q; } - - SubscribeThread(string key, string ex) { - queue=session.getId().str(); // Unique name. - session.queueDeclare(arg::queue=queue, - arg::exclusive=true, - arg::autoDelete=true, - arg::durable=opts.durable); - session.exchangeBind(arg::queue=queue, - arg::exchange=ex, - arg::bindingKey=key); - } - - void verify(bool cond, const char* test, uint32_t expect, uint32_t actual) { - if (!cond) { - Message error( - QPID_MSG("Sequence error: expected n" << test << expect << " but got " << actual), - "sub_done"); - session.messageTransfer(arg::content=error, arg::acceptMode=1); - throw Exception(error.getData()); - } - } - - void run() { // Subscribe - try { - if (opts.txSub) sync(session).txSelect(); - SubscriptionManager subs(session); - SubscriptionSettings settings; - settings.autoAck = opts.txSub ? opts.txSub : opts.ack; - settings.acceptMode = (opts.txSub || opts.ack ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE); - settings.flowControl = FlowControl::messageCredit(opts.subQuota); - LocalQueue lq; - Subscription subscription = subs.subscribe(lq, queue, settings); - // Notify controller we are ready. - session.messageTransfer(arg::content=Message("ready", fqn("sub_ready")), arg::acceptMode=1); - if (opts.txSub) { - if (opts.commitAsync) session.txCommit(); - else sync(session).txCommit(); - } - - LocalQueue iterationControl; - if (opts.iterations > 1) { - subs.subscribe(iterationControl, fqn("sub_iteration"), SubscriptionSettings(FlowControl::messageCredit(0))); - } - - for (size_t j = 0; j < opts.iterations; ++j) { - if (j > 0) { - //need to wait here until all subs are done - session.messageFlow(fqn("sub_iteration"), 0, 1); - iterationControl.pop(); - - //need to allocate some more credit for subscription - session.messageFlow(queue, 0, opts.subQuota); - } - Message msg; - AbsTime start=now(); - size_t expect=0; - for (size_t i = 0; i < opts.subQuota; ++i) { - msg=lq.pop(); - if (opts.txSub && ((i+1) % opts.txSub == 0)) { - if (opts.commitAsync) session.txCommit(); - else sync(session).txCommit(); - } - if (opts.intervalSub) - qpid::sys::usleep(opts.intervalSub*1000); - // TODO aconway 2007-11-23: check message order for. - // multiple publishers. Need an array of counters, - // one per publisher and a publisher ID in the - // message. Careful not to introduce a lot of overhead - // here, e.g. no std::map, std::string etc. - // - // For now verify order only for a single publisher. - size_t offset = opts.uniqueData ? 5 /*marker is 'data:'*/ : 0; - size_t n = *reinterpret_cast<const size_t*>(msg.getData().data() + offset); - if (opts.pubs == 1) { - if (opts.subs == 1 || opts.mode == FANOUT) verify(n==expect, "==", expect, n); - else verify(n>=expect, ">=", expect, n); - expect = n+1; - } - } - if (opts.txSub || opts.ack) - subscription.accept(subscription.getUnaccepted()); - if (opts.txSub) { - if (opts.commitAsync) session.txCommit(); - else sync(session).txCommit(); - } - AbsTime end=now(); - - // Report to publisher. - Message result(lexical_cast<string>(opts.subQuota/secs(start,end)), - fqn("sub_done")); - session.messageTransfer(arg::content=result, arg::acceptMode=1); - if (opts.txSub) sync(session).txCommit(); - } - session.close(); - } - catch (const std::exception& e) { - cout << "SubscribeThread exception: " << e.what() << endl; - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) { - int exitCode = 0; - boost::ptr_vector<Client> subs(opts.subs); - boost::ptr_vector<Client> pubs(opts.pubs); - - try { - opts.parse(argc, argv); - - string exchange; - switch (opts.mode) { - case FANOUT: exchange="amq.fanout"; break; - case TOPIC: exchange="amq.topic"; break; - case SHARED: break; - } - - bool singleProcess= - (!opts.setup && !opts.control && !opts.publish && !opts.subscribe); - if (singleProcess) - opts.setup = opts.control = opts.publish = opts.subscribe = true; - - if (opts.setup) Setup().run(); // Set up queues - - // Start pubs/subs for each queue/topic. - for (size_t i = 0; i < opts.qt; ++i) { - ostringstream key; - key << opts.baseName << i; // Queue or topic name. - if (opts.publish) { - size_t n = singleProcess ? opts.pubs : 1; - for (size_t j = 0; j < n; ++j) { - pubs.push_back(new PublishThread(key.str(), exchange)); - pubs.back().thread=Thread(pubs.back()); - } - } - if (opts.subscribe) { - size_t n = singleProcess ? opts.subs : 1; - for (size_t j = 0; j < n; ++j) { - if (opts.mode==SHARED) - subs.push_back(new SubscribeThread(key.str())); - else - subs.push_back(new SubscribeThread(key.str(),exchange)); - subs.back().thread=Thread(subs.back()); - } - } - } - - if (opts.control) Controller().run(); - } - catch (const std::exception& e) { - cout << endl << e.what() << endl; - exitCode = 1; - } - - // Wait for started threads. - if (opts.publish) { - for (boost::ptr_vector<Client>::iterator i=pubs.begin(); - i != pubs.end(); - ++i) - i->thread.join(); - } - - if (opts.subscribe) { - for (boost::ptr_vector<Client>::iterator i=subs.begin(); - i != subs.end(); - ++i) - i->thread.join(); - } - return exitCode; -} diff --git a/cpp/src/tests/qpid-ping.cpp b/cpp/src/tests/qpid-ping.cpp deleted file mode 100644 index 0cb4afa0ee..0000000000 --- a/cpp/src/tests/qpid-ping.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - - */ - -#include "TestOptions.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/client/Connection.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Monitor.h" -#include "qpid/framing/Uuid.h" -#include <string> -#include <iostream> - -using namespace std; -using namespace qpid::sys; -using namespace qpid::framing; -using namespace qpid::client; -using namespace qpid; - -struct PingOptions : public qpid::TestOptions { - int timeout; // Timeout in seconds. - bool quiet; // No output - PingOptions() : timeout(1), quiet(false) { - addOptions() - ("timeout,t", optValue(timeout, "SECONDS"), "Max time to wait.") - ("quiet,q", optValue(quiet), "Don't print anything to stderr/stdout."); - } -}; - -int main(int argc, char** argv) { - try { - PingOptions opts; - opts.parse(argc, argv); - opts.con.heartbeat = (opts.timeout+1)/2; - Connection connection; - opts.open(connection); - if (!opts.quiet) cout << "Opened connection." << endl; - AsyncSession s = connection.newSession(); - string qname(Uuid(true).str()); - s.queueDeclare(arg::queue=qname,arg::autoDelete=true,arg::exclusive=true); - s.messageTransfer(arg::content=Message("hello", qname)); - if (!opts.quiet) cout << "Sent message." << endl; - SubscriptionManager subs(s); - subs.get(qname); - if (!opts.quiet) cout << "Received message." << endl; - s.sync(); - s.close(); - connection.close(); - if (!opts.quiet) cout << "Success." << endl; - return 0; - } catch (const exception& e) { - cerr << "Error: " << e.what() << endl; - return 1; - } -} diff --git a/cpp/src/tests/qpid-receive.cpp b/cpp/src/tests/qpid-receive.cpp deleted file mode 100644 index 9c713e872a..0000000000 --- a/cpp/src/tests/qpid-receive.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/messaging/Address.h> -#include <qpid/messaging/Connection.h> -#include <qpid/messaging/Receiver.h> -#include <qpid/messaging/Sender.h> -#include <qpid/messaging/Session.h> -#include <qpid/messaging/Message.h> -#include <qpid/messaging/FailoverUpdates.h> -#include <qpid/Options.h> -#include <qpid/log/Logger.h> -#include <qpid/log/Options.h> -#include "qpid/sys/Time.h" -#include "TestOptions.h" -#include "Statistics.h" - -#include <iostream> -#include <memory> - -using namespace qpid::messaging; -using namespace qpid::types; -using namespace std; - -namespace qpid { -namespace tests { - -struct Options : public qpid::Options -{ - bool help; - std::string url; - std::string address; - std::string connectionOptions; - int64_t timeout; - bool forever; - uint messages; - bool ignoreDuplicates; - bool checkRedelivered; - uint capacity; - uint ackFrequency; - uint tx; - uint rollbackFrequency; - bool printContent; - bool printHeaders; - bool failoverUpdates; - qpid::log::Options log; - bool reportTotal; - uint reportEvery; - bool reportHeader; - string readyAddress; - uint receiveRate; - - Options(const std::string& argv0=std::string()) - : qpid::Options("Options"), - help(false), - url("amqp:tcp:127.0.0.1"), - timeout(0), - forever(false), - messages(0), - ignoreDuplicates(false), - checkRedelivered(false), - capacity(1000), - ackFrequency(100), - tx(0), - rollbackFrequency(0), - printContent(true), - printHeaders(false), - failoverUpdates(false), - log(argv0), - reportTotal(false), - reportEvery(0), - reportHeader(true), - receiveRate(0) - { - addOptions() - ("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to") - ("address,a", qpid::optValue(address, "ADDRESS"), "address to receive from") - ("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection") - ("timeout", qpid::optValue(timeout, "TIMEOUT"), "timeout in seconds to wait before exiting") - ("forever,f", qpid::optValue(forever), "ignore timeout and wait forever") - ("messages,m", qpid::optValue(messages, "N"), "Number of messages to receive; 0 means receive indefinitely") - ("ignore-duplicates", qpid::optValue(ignoreDuplicates), "Detect and ignore duplicates (by checking 'sn' header)") - ("check-redelivered", qpid::optValue(checkRedelivered), "Fails with exception if a duplicate is not marked as redelivered (only relevant when ignore-duplicates is selected)") - ("capacity", qpid::optValue(capacity, "N"), "Pre-fetch window (0 implies no pre-fetch)") - ("ack-frequency", qpid::optValue(ackFrequency, "N"), "Ack frequency (0 implies none of the messages will get accepted)") - ("tx", qpid::optValue(tx, "N"), "batch size for transactions (0 implies transaction are not used)") - ("rollback-frequency", qpid::optValue(rollbackFrequency, "N"), "rollback frequency (0 implies no transaction will be rolledback)") - ("print-content", qpid::optValue(printContent, "yes|no"), "print out message content") - ("print-headers", qpid::optValue(printHeaders, "yes|no"), "print out message headers") - ("failover-updates", qpid::optValue(failoverUpdates), "Listen for membership updates distributed via amq.failover") - ("report-total", qpid::optValue(reportTotal), "Report total throughput and latency statistics") - ("report-every", qpid::optValue(reportEvery,"N"), "Report throughput and latency statistics every N messages.") - ("report-header", qpid::optValue(reportHeader, "yes|no"), "Headers on report.") - ("ready-address", qpid::optValue(readyAddress, "ADDRESS"), "send a message to this address when ready to receive") - ("receive-rate", qpid::optValue(receiveRate,"N"), "Receive at rate of N messages/second. 0 means receive as fast as possible.") - ("help", qpid::optValue(help), "print this usage statement"); - add(log); - } - - Duration getTimeout() - { - if (forever) return Duration::FOREVER; - else return Duration::SECOND*timeout; - - } - bool parse(int argc, char** argv) - { - try { - qpid::Options::parse(argc, argv); - if (address.empty()) throw qpid::Exception("Address must be specified!"); - qpid::log::Logger::instance().configure(log); - if (help) { - std::ostringstream msg; - std::cout << msg << *this << std::endl << std::endl - << "Drains messages from the specified address" << std::endl; - return false; - } else { - return true; - } - } catch (const std::exception& e) { - std::cerr << *this << std::endl << std::endl << e.what() << std::endl; - return false; - } - } -}; - -const string EOS("eos"); -const string SN("sn"); - -class SequenceTracker -{ - uint lastSn; - public: - SequenceTracker() : lastSn(0) {} - - bool isDuplicate(Message& message) - { - uint sn = message.getProperties()[SN]; - if (lastSn < sn) { - lastSn = sn; - return false; - } else { - return true; - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - Connection connection; - try { - Options opts; - if (opts.parse(argc, argv)) { - connection = Connection(opts.url, opts.connectionOptions); - connection.open(); - std::auto_ptr<FailoverUpdates> updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0); - Session session = opts.tx ? connection.createTransactionalSession() : connection.createSession(); - Receiver receiver = session.createReceiver(opts.address); - receiver.setCapacity(opts.capacity); - Message msg; - uint count = 0; - uint txCount = 0; - SequenceTracker sequenceTracker; - Duration timeout = opts.getTimeout(); - bool done = false; - Reporter<ThroughputAndLatency> reporter(std::cout, opts.reportEvery, opts.reportHeader); - if (!opts.readyAddress.empty()) - session.createSender(opts.readyAddress).send(msg); - - // For receive rate calculation - qpid::sys::AbsTime start = qpid::sys::now(); - int64_t interval = 0; - if (opts.receiveRate) interval = qpid::sys::TIME_SEC/opts.receiveRate; - - std::map<std::string,Sender> replyTo; - - while (!done && receiver.fetch(msg, timeout)) { - reporter.message(msg); - if (!opts.ignoreDuplicates || !sequenceTracker.isDuplicate(msg)) { - if (msg.getContent() == EOS) { - done = true; - } else { - ++count; - if (opts.printHeaders) { - if (msg.getSubject().size()) std::cout << "Subject: " << msg.getSubject() << std::endl; - if (msg.getReplyTo()) std::cout << "ReplyTo: " << msg.getReplyTo() << std::endl; - if (msg.getCorrelationId().size()) std::cout << "CorrelationId: " << msg.getCorrelationId() << std::endl; - if (msg.getUserId().size()) std::cout << "UserId: " << msg.getUserId() << std::endl; - if (msg.getTtl().getMilliseconds()) std::cout << "TTL: " << msg.getTtl().getMilliseconds() << std::endl; - if (msg.getPriority()) std::cout << "Priority: " << msg.getPriority() << std::endl; - if (msg.getDurable()) std::cout << "Durable: true" << std::endl; - if (msg.getRedelivered()) std::cout << "Redelivered: true" << std::endl; - std::cout << "Properties: " << msg.getProperties() << std::endl; - std::cout << std::endl; - } - if (opts.printContent) - std::cout << msg.getContent() << std::endl;//TODO: handle map or list messages - if (opts.messages && count >= opts.messages) done = true; - } - } else if (opts.checkRedelivered && !msg.getRedelivered()) { - throw qpid::Exception("duplicate sequence number received, message not marked as redelivered!"); - } - if (opts.tx && (count % opts.tx == 0)) { - if (opts.rollbackFrequency && (++txCount % opts.rollbackFrequency == 0)) { - session.rollback(); - } else { - session.commit(); - } - } else if (opts.ackFrequency && (count % opts.ackFrequency == 0)) { - session.acknowledge(); - } - if (msg.getReplyTo()) { // Echo message back to reply-to address. - Sender& s = replyTo[msg.getReplyTo().str()]; - if (s.isNull()) { - s = session.createSender(msg.getReplyTo()); - s.setCapacity(opts.capacity); - } - s.send(msg); - } - if (opts.receiveRate) { - qpid::sys::AbsTime waitTill(start, count*interval); - int64_t delay = qpid::sys::Duration(qpid::sys::now(), waitTill); - if (delay > 0) qpid::sys::usleep(delay/qpid::sys::TIME_USEC); - } - // Clear out message properties & content for next iteration. - msg = Message(); // TODO aconway 2010-12-01: should be done by fetch - } - if (opts.reportTotal) reporter.report(); - if (opts.tx) { - if (opts.rollbackFrequency && (++txCount % opts.rollbackFrequency == 0)) { - session.rollback(); - } else { - session.commit(); - } - } else { - session.acknowledge(); - } - session.close(); - connection.close(); - return 0; - } - } catch(const std::exception& error) { - std::cerr << "qpid-receive: " << error.what() << std::endl; - connection.close(); - return 1; - } -} diff --git a/cpp/src/tests/qpid-send.cpp b/cpp/src/tests/qpid-send.cpp deleted file mode 100644 index ef5e98e2a0..0000000000 --- a/cpp/src/tests/qpid-send.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/messaging/Address.h> -#include <qpid/messaging/Connection.h> -#include <qpid/messaging/Message.h> -#include <qpid/messaging/Sender.h> -#include <qpid/messaging/Receiver.h> -#include <qpid/messaging/Session.h> -#include <qpid/messaging/FailoverUpdates.h> -#include <qpid/sys/Time.h> -#include <qpid/sys/Monitor.h> -#include "TestOptions.h" -#include "Statistics.h" - -#include <fstream> -#include <iostream> -#include <memory> - -using namespace std; -using namespace qpid::messaging; -using namespace qpid::types; - -typedef std::vector<std::string> string_vector; - -namespace qpid { -namespace tests { - -struct Options : public qpid::Options -{ - bool help; - std::string url; - std::string connectionOptions; - std::string address; - uint messages; - std::string id; - std::string replyto; - uint sendEos; - bool durable; - uint ttl; - uint priority; - std::string userid; - std::string correlationid; - string_vector properties; - string_vector entries; - std::string contentString; - uint contentSize; - bool contentStdin; - uint tx; - uint rollbackFrequency; - uint capacity; - bool failoverUpdates; - qpid::log::Options log; - bool reportTotal; - uint reportEvery; - bool reportHeader; - uint sendRate; - uint flowControl; - bool sequence; - bool timestamp; - - Options(const std::string& argv0=std::string()) - : qpid::Options("Options"), - help(false), - url("amqp:tcp:127.0.0.1"), - messages(1), - sendEos(0), - durable(false), - ttl(0), - priority(0), - contentString(), - contentSize(0), - contentStdin(false), - tx(0), - rollbackFrequency(0), - capacity(1000), - failoverUpdates(false), - log(argv0), - reportTotal(false), - reportEvery(0), - reportHeader(true), - sendRate(0), - flowControl(0), - sequence(true), - timestamp(true) - { - addOptions() - ("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to") - ("address,a", qpid::optValue(address, "ADDRESS"), "address to send to") - ("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection") - ("messages,m", qpid::optValue(messages, "N"), "stop after N messages have been sent, 0 means no limit") - ("id,i", qpid::optValue(id, "ID"), "use the supplied id instead of generating one") - ("reply-to", qpid::optValue(replyto, "REPLY-TO"), "specify reply-to address") - ("send-eos", qpid::optValue(sendEos, "N"), "Send N EOS messages to mark end of input") - ("durable", qpid::optValue(durable, "yes|no"), "Mark messages as durable.") - ("ttl", qpid::optValue(ttl, "msecs"), "Time-to-live for messages, in milliseconds") - ("priority", qpid::optValue(priority, "PRIORITY"), "Priority for messages (higher value implies higher priority)") - ("property,P", qpid::optValue(properties, "NAME=VALUE"), "specify message property") - ("correlation-id", qpid::optValue(correlationid, "ID"), "correlation-id for message") - ("user-id", qpid::optValue(userid, "USERID"), "userid for message") - ("content-string", qpid::optValue(contentString, "CONTENT"), "use CONTENT as message content") - ("content-size", qpid::optValue(contentSize, "N"), "create an N-byte message content") - ("content-map,M", qpid::optValue(entries, "NAME=VALUE"), "specify entry for map content") - ("content-stdin", qpid::optValue(contentStdin), "read message content from stdin, one line per message") - ("capacity", qpid::optValue(capacity, "N"), "size of the senders outgoing message queue") - ("tx", qpid::optValue(tx, "N"), "batch size for transactions (0 implies transaction are not used)") - ("rollback-frequency", qpid::optValue(rollbackFrequency, "N"), "rollback frequency (0 implies no transaction will be rolledback)") - ("failover-updates", qpid::optValue(failoverUpdates), "Listen for membership updates distributed via amq.failover") - ("report-total", qpid::optValue(reportTotal), "Report total throughput statistics") - ("report-every", qpid::optValue(reportEvery,"N"), "Report throughput statistics every N messages") - ("report-header", qpid::optValue(reportHeader, "yes|no"), "Headers on report.") - ("send-rate", qpid::optValue(sendRate,"N"), "Send at rate of N messages/second. 0 means send as fast as possible.") - ("flow-control", qpid::optValue(flowControl,"N"), "Do end to end flow control to limit queue depth to 2*N. 0 means no flow control.") - ("sequence", qpid::optValue(sequence, "yes|no"), "Add a sequence number messages property (required for duplicate/lost message detection)") - ("timestamp", qpid::optValue(timestamp, "yes|no"), "Add a time stamp messages property (required for latency measurement)") - ("help", qpid::optValue(help), "print this usage statement"); - add(log); - } - - bool parse(int argc, char** argv) - { - try { - qpid::Options::parse(argc, argv); - if (address.empty()) throw qpid::Exception("Address must be specified!"); - qpid::log::Logger::instance().configure(log); - if (help) { - std::ostringstream msg; - std::cout << msg << *this << std::endl << std::endl - << "Drains messages from the specified address" << std::endl; - return false; - } else { - return true; - } - } catch (const std::exception& e) { - std::cerr << *this << std::endl << std::endl << e.what() << std::endl; - return false; - } - } - - static bool nameval(const std::string& in, std::string& name, std::string& value) - { - std::string::size_type i = in.find("="); - if (i == std::string::npos) { - name = in; - return false; - } else { - name = in.substr(0, i); - if (i+1 < in.size()) { - value = in.substr(i+1); - return true; - } else { - return false; - } - } - } - - static void setProperty(Message& message, const std::string& property) - { - std::string name; - std::string value; - if (nameval(property, name, value)) { - message.getProperties()[name] = value; - } else { - message.getProperties()[name] = Variant(); - } - } - - void setProperties(Message& message) const - { - for (string_vector::const_iterator i = properties.begin(); i != properties.end(); ++i) { - setProperty(message, *i); - } - } - - void setEntries(Variant::Map& content) const - { - for (string_vector::const_iterator i = entries.begin(); i != entries.end(); ++i) { - std::string name; - std::string value; - if (nameval(*i, name, value)) { - content[name] = value; - } else { - content[name] = Variant(); - } - } - } -}; - -const string EOS("eos"); -const string SN("sn"); -const string TS("ts"); - -}} // namespace qpid::tests - -using namespace qpid::tests; - -class ContentGenerator { - public: - virtual ~ContentGenerator() {} - virtual bool setContent(Message& msg) = 0; -}; - -class GetlineContentGenerator : public ContentGenerator { - public: - virtual bool setContent(Message& msg) { - string content; - bool got = getline(std::cin, content); - if (got) msg.setContent(content); - return got; - } -}; - -class FixedContentGenerator : public ContentGenerator { - public: - FixedContentGenerator(const string& s) : content(s) {} - virtual bool setContent(Message& msg) { - msg.setContent(content); - return true; - } - private: - std::string content; -}; - -class MapContentGenerator : public ContentGenerator { - public: - MapContentGenerator(const Options& opt) : opts(opt) {} - virtual bool setContent(Message& msg) { - Variant::Map map; - opts.setEntries(map); - encode(map, msg); - return true; - } - private: - const Options& opts; -}; - -int main(int argc, char ** argv) -{ - Connection connection; - Options opts; - try { - if (opts.parse(argc, argv)) { - connection = Connection(opts.url, opts.connectionOptions); - connection.open(); - std::auto_ptr<FailoverUpdates> updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0); - Session session = opts.tx ? connection.createTransactionalSession() : connection.createSession(); - Sender sender = session.createSender(opts.address); - if (opts.capacity) sender.setCapacity(opts.capacity); - Message msg; - msg.setDurable(opts.durable); - if (opts.ttl) { - msg.setTtl(Duration(opts.ttl)); - } - if (opts.priority) { - msg.setPriority(opts.priority); - } - if (!opts.replyto.empty()) { - if (opts.flowControl) - throw Exception("Can't use reply-to and flow-control together"); - msg.setReplyTo(Address(opts.replyto)); - } - if (!opts.userid.empty()) msg.setUserId(opts.userid); - if (!opts.correlationid.empty()) msg.setCorrelationId(opts.correlationid); - opts.setProperties(msg); - uint sent = 0; - uint txCount = 0; - Reporter<Throughput> reporter(std::cout, opts.reportEvery, opts.reportHeader); - - std::auto_ptr<ContentGenerator> contentGen; - if (opts.contentStdin) { - opts.messages = 0; // Don't limit # messages sent. - contentGen.reset(new GetlineContentGenerator); - } - else if (opts.entries.size() > 0) - contentGen.reset(new MapContentGenerator(opts)); - else if (opts.contentSize > 0) - contentGen.reset(new FixedContentGenerator(string(opts.contentSize, 'X'))); - else - contentGen.reset(new FixedContentGenerator(opts.contentString)); - - qpid::sys::AbsTime start = qpid::sys::now(); - int64_t interval = 0; - if (opts.sendRate) interval = qpid::sys::TIME_SEC/opts.sendRate; - - Receiver flowControlReceiver; - Address flowControlAddress("flow-"+Uuid(true).str()+";{create:always,delete:always}"); - uint flowSent = 0; - if (opts.flowControl) { - flowControlReceiver = session.createReceiver(flowControlAddress); - flowControlReceiver.setCapacity(2); - } - - while (contentGen->setContent(msg)) { - ++sent; - if (opts.sequence) - msg.getProperties()[SN] = sent; - if (opts.timestamp) - msg.getProperties()[TS] = int64_t( - qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now())); - if (opts.flowControl) { - if ((sent % opts.flowControl) == 0) { - msg.setReplyTo(flowControlAddress); - ++flowSent; - } - else - msg.setReplyTo(Address()); // Clear the reply address. - } - sender.send(msg); - reporter.message(msg); - - if (opts.tx && (sent % opts.tx == 0)) { - if (opts.rollbackFrequency && - (++txCount % opts.rollbackFrequency == 0)) - session.rollback(); - else - session.commit(); - } - if (opts.messages && sent >= opts.messages) break; - - if (opts.flowControl && flowSent == 2) { - flowControlReceiver.get(Duration::SECOND); - --flowSent; - } - - if (opts.sendRate) { - qpid::sys::AbsTime waitTill(start, sent*interval); - int64_t delay = qpid::sys::Duration(qpid::sys::now(), waitTill); - if (delay > 0) qpid::sys::usleep(delay/qpid::sys::TIME_USEC); - } - } - for ( ; flowSent>0; --flowSent) - flowControlReceiver.get(Duration::SECOND); - if (opts.reportTotal) reporter.report(); - for (uint i = opts.sendEos; i > 0; --i) { - if (opts.sequence) - msg.getProperties()[SN] = ++sent; - msg.setContent(EOS); //TODO: add in ability to send digest or similar - sender.send(msg); - } - if (opts.tx) { - if (opts.rollbackFrequency && (++txCount % opts.rollbackFrequency == 0)) { - session.rollback(); - } else { - session.commit(); - } - } - session.sync(); - session.close(); - connection.close(); - return 0; - } - } catch(const std::exception& error) { - std::cerr << "qpid-send: " << error.what() << std::endl; - connection.close(); - return 1; - } -} diff --git a/cpp/src/tests/qpid-src-rinstall b/cpp/src/tests/qpid-src-rinstall deleted file mode 100755 index 5e69e0ade1..0000000000 --- a/cpp/src/tests/qpid-src-rinstall +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under onemake -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Copy the source tree and run "make install" on each of $HOSTS -# Must be run in a configured qpid build directory. - -absdir() { echo `cd $1 && pwd`; } - -test -f config.status || { echo "Not in a configured build directory."; } -CONFIGURE=`./config.status -V | grep '^configured by' | sed 's/^configured by \([^,]*\),.*$/\1/'` -CONFIG_OPTIONS=`./config.status -V | grep 'with options' | sed 's/^.*with options "\([^"]*\)".*$/\1/'` -set -ex -rsynchosts `absdir $(dirname $CONFIGURE)/..` # Copy cpp srcdir and siblings. -allhosts -bo rbuild.log "mkdir -p $PWD && cd $PWD && { test -f config.status || $CONFIGURE $CONFIG_OPTIONS; } && make && make -j1 install" diff --git a/cpp/src/tests/qpid-stream.cpp b/cpp/src/tests/qpid-stream.cpp deleted file mode 100644 index f02a484750..0000000000 --- a/cpp/src/tests/qpid-stream.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/messaging/Connection.h> -#include <qpid/messaging/Message.h> -#include <qpid/messaging/Receiver.h> -#include <qpid/messaging/Sender.h> -#include <qpid/messaging/Session.h> -#include <qpid/sys/Runnable.h> -#include <qpid/sys/Thread.h> -#include <qpid/sys/Time.h> -#include <qpid/Options.h> -#include <iostream> -#include <string> - -using namespace qpid::messaging; -using namespace qpid::types; - -namespace qpid { -namespace tests { - -struct Args : public qpid::Options -{ - std::string url; - std::string address; - uint size; - uint rate; - bool durable; - uint receiverCapacity; - uint senderCapacity; - uint ackFrequency; - - Args() : - url("amqp:tcp:127.0.0.1:5672"), - address("test-queue"), - size(512), - rate(1000), - durable(false), - receiverCapacity(0), - senderCapacity(0), - ackFrequency(1) - { - addOptions() - ("url", qpid::optValue(url, "URL"), "Url to connect to.") - ("address", qpid::optValue(address, "ADDRESS"), "Address to stream messages through.") - ("size", qpid::optValue(size, "bytes"), "Message size in bytes (content only, not headers).") - ("rate", qpid::optValue(rate, "msgs/sec"), "Rate at which to stream messages.") - ("durable", qpid::optValue(durable, "true|false"), "Mark messages as durable.") - ("sender-capacity", qpid::optValue(senderCapacity, "N"), "Credit window (0 implies infinite window)") - ("receiver-capacity", qpid::optValue(receiverCapacity, "N"), "Credit window (0 implies infinite window)") - ("ack-frequency", qpid::optValue(ackFrequency, "N"), - "Ack frequency (0 implies none of the messages will get accepted)"); - } -}; - -Args opts; - -const std::string TS = "ts"; - -uint64_t timestamp(const qpid::sys::AbsTime& time) -{ - qpid::sys::Duration t(qpid::sys::EPOCH, time); - return t; -} - -struct Client : qpid::sys::Runnable -{ - virtual ~Client() {} - virtual void doWork(Session&) = 0; - - void run() - { - Connection connection(opts.url); - try { - connection.open(); - Session session = connection.createSession(); - doWork(session); - session.close(); - connection.close(); - } catch(const std::exception& error) { - std::cout << error.what() << std::endl; - connection.close(); - } - } - - qpid::sys::Thread thread; - - void start() { thread = qpid::sys::Thread(this); } - void join() { thread.join(); } -}; - -struct Publish : Client -{ - void doWork(Session& session) - { - Sender sender = session.createSender(opts.address); - if (opts.senderCapacity) sender.setCapacity(opts.senderCapacity); - Message msg(std::string(opts.size, 'X')); - uint64_t interval = qpid::sys::TIME_SEC / opts.rate; - uint64_t sent = 0, missedRate = 0; - qpid::sys::AbsTime start = qpid::sys::now(); - while (true) { - qpid::sys::AbsTime sentAt = qpid::sys::now(); - msg.getProperties()[TS] = timestamp(sentAt); - sender.send(msg); - ++sent; - qpid::sys::AbsTime waitTill(start, sent*interval); - qpid::sys::Duration delay(sentAt, waitTill); - if (delay < 0) { - ++missedRate; - } else { - qpid::sys::usleep(delay / qpid::sys::TIME_USEC); - } - } - } -}; - -struct Consume : Client -{ - void doWork(Session& session) - { - Message msg; - uint64_t received = 0; - double minLatency = std::numeric_limits<double>::max(); - double maxLatency = 0; - double totalLatency = 0; - Receiver receiver = session.createReceiver(opts.address); - if (opts.receiverCapacity) receiver.setCapacity(opts.receiverCapacity); - while (receiver.fetch(msg)) { - ++received; - if (opts.ackFrequency && (received % opts.ackFrequency == 0)) { - session.acknowledge(); - } - //calculate latency - uint64_t receivedAt = timestamp(qpid::sys::now()); - uint64_t sentAt = msg.getProperties()[TS].asUint64(); - double latency = ((double) (receivedAt - sentAt)) / qpid::sys::TIME_MSEC; - - //update avg, min & max - minLatency = std::min(minLatency, latency); - maxLatency = std::max(maxLatency, latency); - totalLatency += latency; - - if (received % opts.rate == 0) { - std::cout << "count=" << received - << ", avg=" << (totalLatency/received) - << ", min=" << minLatency - << ", max=" << maxLatency << std::endl; - } - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - Publish publish; - Consume consume; - publish.start(); - consume.start(); - consume.join(); - publish.join(); - return 0; - } catch(const std::exception& error) { - std::cout << error.what() << std::endl; - } - return 1; -} - - diff --git a/cpp/src/tests/qpid-test-cluster b/cpp/src/tests/qpid-test-cluster deleted file mode 100755 index 9887406ef9..0000000000 --- a/cpp/src/tests/qpid-test-cluster +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -usage() { - echo "Usage: `basename $0` [options] start|stop|restart|check [hosts] -Start/stop/restart a cluster on specified hosts or on \$HOSTS via ssh. - -Options: - -l USER Run qpidd and copy files as USER. - -e SCRIPT Source SCRIPT for environment settings. Copies SCRIPT to each host. - Default is $DEFAULT_ENV. - -c CONFIG Use CONFIG as qpidd config file. Copies CONFIG to each host. - Default is $DEFAULT_CONF - -d Delete data-dir and log file before starting broker. -" - exit 1 -} - -DEFAULT_CONF=~/qpid-test-qpidd.conf -DEFAULT_ENV=~/qpid-test-env.sh - -test -f $DEFAULT_CONF && CONF_FILE=$DEFAULT_CONF -test -f $DEFAULT_ENV && ENV_FILE=$DEFAULT_ENV - -while getopts "l:e:c:d" opt; do - case $opt in - l) SSHOPTS="-l$OPTARG $SSHOPTS" ; RSYNC_USER="$OPTARG@" ;; - e) ENV_FILE=$OPTARG ;; - c) CONF_FILE=$OPTARG ;; - d) DO_DELETE=1 ;; - *) usage;; - esac -done -shift `expr $OPTIND - 1` -test "$*" || usage -CMD=$1; shift -HOSTS=${*:-$HOSTS} - -conf_value() { test -f "$CONF_FILE" && awk -F= "/^$1=/ {print \$2}" $CONF_FILE; } - -if test -n "$CONF_FILE"; then - test -f "$CONF_FILE" || { echo Config file not found: $CONF_FILE; exit 1; } - RSYNCFILES="$RSYNCFILES $CONF_FILE" - QPIDD_ARGS="$QPIDD_ARGS --config $CONF_FILE" - CONF_PORT=`conf_value port` - CONF_DATA_DIR=`conf_value data-dir` - CONF_LOG_FILE=`conf_value log-to-file` -fi - -if test -n "$ENV_FILE"; then - test -f "$ENV_FILE" || { echo Environment file not found: $ENV_FILE; exit 1; } - RSYNCFILES="$RSYNCFILES $ENV_FILE" - SOURCE_ENV="source $ENV_FILE ; " -fi - -test -n "$RSYNCFILES" && rsynchosts $RSYNCFILES # Copy conf/env files to all hosts - -do_start() { - for h in $HOSTS; do - COMMAND="qpidd -d $QPIDD_ARGS" - id -nG | grep '\<ais\>' >/dev/null && COMMAND="sg ais -c '$COMMAND'" - if test "$DO_DELETE"; then COMMAND="rm -rf $CONF_DATA_DIR $CONF_LOG_FILE; $COMMAND"; fi - ssh $h "$SOURCE_ENV $COMMAND" || { echo "Failed to start on $h"; exit 1; } - done -} - -do_stop() { - for h in $HOSTS; do - ssh $h "$SOURCE_ENV qpidd -q --no-module-dir --no-data-dir $QPIDD_ARGS" - done -} - -do_status() { - for h in $HOSTS; do - if ssh $h "$SOURCE_ENV qpidd -c --no-module-dir --no-data-dir $QPIDD_ARGS > /dev/null"; then - echo "$h ok" - else - echo "$h not running" - STATUS=1 - fi - done -} - -case $CMD in - start) do_start ;; - stop) do_stop ;; - restart) do_stop ; do_start ;; - status) do_status ;; - *) usage;; -esac - -exit $STATUS diff --git a/cpp/src/tests/qpid-topic-listener.cpp b/cpp/src/tests/qpid-topic-listener.cpp deleted file mode 100644 index c42e76d760..0000000000 --- a/cpp/src/tests/qpid-topic-listener.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * This file provides one half of a test and example of a pub-sub - * style of interaction. See qpid-topic-publisher.cpp for the other half, - * in which the logic for publishing is defined. - * - * This file contains the listener logic. A listener will subscribe to - * a logical 'topic'. It will count the number of messages it receives - * and the time elapsed between the first one and the last one. It - * recognises two types of 'special' message that tell it to (a) send - * a report containing this information, (b) shutdown (i.e. stop - * listening). - */ - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/Session.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/Time.h" -#include "qpid/framing/FieldValue.h" -#include <iostream> -#include <sstream> - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using namespace qpid::framing; -using namespace std; - -namespace qpid { -namespace tests { - -/** - * A message listener implementation in which the runtime logic is - * defined. - */ -class Listener : public MessageListener{ - Session session; - SubscriptionManager& mgr; - const string responseQueue; - const bool transactional; - bool init; - int count; - AbsTime start; - - void shutdown(); - void report(); -public: - Listener(const Session& session, SubscriptionManager& mgr, const string& reponseQueue, bool tx); - virtual void received(Message& msg); - Subscription subscription; -}; - -/** - * A utility class for managing the options passed in. - */ -struct Args : public qpid::TestOptions { - int ack; - bool transactional; - bool durable; - int prefetch; - string statusqueue; - - Args() : ack(0), transactional(false), durable(false), prefetch(0) { - addOptions() - ("ack", optValue(ack, "MODE"), "Ack frequency in messages (defaults to half the prefetch value)") - ("transactional", optValue(transactional), "Use transactions") - ("durable", optValue(durable), "subscribers should use durable queues") - ("prefetch", optValue(prefetch, "N"), "prefetch count (0 implies no flow control, and no acking)") - ("status-queue", optValue(statusqueue, "QUEUE-NAME"), "Message queue to put status messages on"); - } -}; - -Listener::Listener(const Session& s, SubscriptionManager& m, const string& _responseq, bool tx) : - session(s), mgr(m), responseQueue(_responseq), transactional(tx), init(false), count(0){} - -void Listener::received(Message& message){ - if(!init){ - start = now(); - count = 0; - init = true; - cout << "Batch started." << endl; - } - string type = message.getHeaders().getAsString("TYPE"); - - if(string("TERMINATION_REQUEST") == type){ - shutdown(); - }else if(string("REPORT_REQUEST") == type){ - subscription.accept(subscription.getUnaccepted()); // Accept everything upto this point - cout <<"Batch ended, sending report." << endl; - //send a report: - report(); - init = false; - }else if (++count % 1000 == 0){ - cout <<"Received " << count << " messages." << endl; - } -} - -void Listener::shutdown(){ - mgr.stop(); -} - -void Listener::report(){ - AbsTime finish = now(); - Duration time(start, finish); - stringstream reportstr; - reportstr << "Received " << count << " messages in " - << time/TIME_MSEC << " ms."; - Message msg(reportstr.str(), responseQueue); - msg.getHeaders().setString("TYPE", "REPORT"); - session.messageTransfer(arg::destination="amq.direct", arg::content=msg, arg::acceptMode=1); - if(transactional){ - sync(session).txCommit(); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -/** - * The main routine creates a Listener instance and sets it up to - * consume from a private queue bound to the exchange with the - * appropriate topic name. - */ -int main(int argc, char** argv){ - try{ - Args args; - args.parse(argc, argv); - if(args.help) - cout << args << endl; - else { - Connection connection; - args.open(connection); - AsyncSession session = connection.newSession(); - - //declare exchange, queue and bind them: - session.queueDeclare(arg::queue="response"); - std::string control = "control_" + session.getId().str(); - if (args.durable) { - session.queueDeclare(arg::queue=control, arg::durable=true); - } else { - session.queueDeclare(arg::queue=control, arg::exclusive=true, arg::autoDelete=true); - } - session.exchangeBind(arg::exchange="amq.topic", arg::queue=control, arg::bindingKey="topic_control"); - - //set up listener - SubscriptionManager mgr(session); - Listener listener(session, mgr, "response", args.transactional); - SubscriptionSettings settings; - if (args.prefetch) { - settings.autoAck = (args.ack ? args.ack : (args.prefetch / 2)); - settings.flowControl = FlowControl::messageCredit(args.prefetch); - } else { - settings.acceptMode = ACCEPT_MODE_NONE; - settings.flowControl = FlowControl::unlimited(); - } - listener.subscription = mgr.subscribe(listener, control, settings); - session.sync(); - - if( args.statusqueue.length() > 0 ) { - stringstream msg_str; - msg_str << "qpid-topic-listener: " << qpid::sys::SystemInfo::getProcessId(); - session.messageTransfer(arg::content=Message(msg_str.str(), args.statusqueue)); - cout << "Ready status put on queue '" << args.statusqueue << "'" << endl; - } - - if (args.transactional) { - session.txSelect(); - } - - cout << "qpid-topic-listener: listening..." << endl; - mgr.run(); - if (args.durable) { - session.queueDelete(arg::queue=control); - } - session.close(); - cout << "closing connection" << endl; - connection.close(); - } - return 0; - } catch (const std::exception& error) { - cout << "qpid-topic-listener: " << error.what() << endl; - } - return 1; -} diff --git a/cpp/src/tests/qpid-topic-publisher.cpp b/cpp/src/tests/qpid-topic-publisher.cpp deleted file mode 100644 index f9107b90d0..0000000000 --- a/cpp/src/tests/qpid-topic-publisher.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/** - * This file provides one half of a test and example of a pub-sub - * style of interaction. See qpid-topic-listener.cpp for the other half, in - * which the logic for subscribers is defined. - * - * This file contains the publisher logic. The publisher will send a - * number of messages to the exchange with the appropriate routing key - * for the logical 'topic'. Once it has done this it will then send a - * request that each subscriber report back with the number of message - * it has received and the time that elapsed between receiving the - * first one and receiving the report request. Once the expected - * number of reports are received, it sends out a request that each - * subscriber shutdown. - */ - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/MessageListener.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Time.h" -#include <cstdlib> -#include <iostream> - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using namespace std; - -namespace qpid { -namespace tests { - -/** - * The publishing logic is defined in this class. It implements - * message listener and can therfore be used to receive messages sent - * back by the subscribers. - */ -class Publisher { - AsyncSession session; - SubscriptionManager mgr; - LocalQueue queue; - const string controlTopic; - const bool transactional; - const bool durable; - - string generateData(int size); - -public: - Publisher(const AsyncSession& session, const string& controlTopic, bool tx, bool durable); - int64_t publish(int msgs, int listeners, int size); - void terminate(); -}; - -/** - * A utility class for managing the options passed in to the test - */ -struct Args : public TestOptions { - int messages; - int subscribers; - bool transactional; - bool durable; - int batches; - int delay; - int size; - string statusqueue; - - Args() : messages(1000), subscribers(1), - transactional(false), durable(false), - batches(1), delay(0), size(256) - { - addOptions() - ("messages", optValue(messages, "N"), "how many messages to send") - ("subscribers", optValue(subscribers, "N"), "how many subscribers to expect reports from") - ("transactional", optValue(transactional), "client should use transactions") - ("durable", optValue(durable), "messages should be durable") - ("batches", optValue(batches, "N"), "how many batches to run") - ("delay", optValue(delay, "SECONDS"), "Causes a delay between each batch") - ("size", optValue(size, "BYTES"), "size of the published messages") - ("status-queue", optValue(statusqueue, "QUEUE-NAME"), "Message queue to read status messages from"); - } -}; - -Publisher::Publisher(const AsyncSession& _session, const string& _controlTopic, bool tx, bool d) : - session(_session), mgr(session), controlTopic(_controlTopic), transactional(tx), durable(d) -{ - mgr.subscribe(queue, "response"); -} - -int64_t Publisher::publish(int msgs, int listeners, int size){ - Message msg(generateData(size), controlTopic); - if (durable) { - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - AbsTime start = now(); - - for(int i = 0; i < msgs; i++){ - session.messageTransfer(arg::content=msg, arg::destination="amq.topic", arg::acceptMode=1); - } - //send report request - Message reportRequest("", controlTopic); - reportRequest.getHeaders().setString("TYPE", "REPORT_REQUEST"); - session.messageTransfer(arg::content=reportRequest, arg::destination="amq.topic", arg::acceptMode=1); - if(transactional){ - sync(session).txCommit(); - } - //wait for a response from each listener (TODO, could log these) - for (int i = 0; i < listeners; i++) { - Message report = queue.pop(); - } - - if(transactional){ - sync(session).txCommit(); - } - - AbsTime finish = now(); - return Duration(start, finish); -} - -string Publisher::generateData(int size){ - string data; - for(int i = 0; i < size; i++){ - data += ('A' + (i / 26)); - } - return data; -} - -void Publisher::terminate(){ - //send termination request - Message terminationRequest("", controlTopic); - terminationRequest.getHeaders().setString("TYPE", "TERMINATION_REQUEST"); - session.messageTransfer(arg::content=terminationRequest, arg::destination="amq.topic", arg::acceptMode=1); - if(transactional){ - session.txCommit(); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) { - try{ - Args args; - args.parse(argc, argv); - if(args.help) - cout << args << endl; - else { - Connection connection; - args.open(connection); - AsyncSession session = connection.newSession(); - - // If status-queue is defined, wait for all expected listeners to join in before we start - if( args.statusqueue.length() > 0 ) { - cout << "Waiting for " << args.subscribers << " listeners..." << endl; - SubscriptionManager statusSubs(session); - LocalQueue statusQ; - statusSubs.subscribe(statusQ, args.statusqueue); - for (int i = 0; i < args.subscribers; i++) { - Message m = statusQ.get(); - if( m.getData().find("topic_listener: ", 0) == 0 ) { - cout << "Listener " << (i+1) << " of " << args.subscribers - << " is ready (pid " << m.getData().substr(16, m.getData().length() - 16) - << ")" << endl; - } else { - throw Exception(QPID_MSG("Unexpected message received on status queue: " << m.getData())); - } - } - } - - if (args.transactional) { - session.txSelect(); - } - session.queueDeclare(arg::queue="response"); - session.exchangeBind(arg::exchange="amq.direct", arg::queue="response", arg::bindingKey="response"); - - Publisher publisher(session, "topic_control", args.transactional, args.durable); - - int batchSize(args.batches); - int64_t max(0); - int64_t min(0); - int64_t sum(0); - for(int i = 0; i < batchSize; i++){ - if(i > 0 && args.delay) qpid::sys::sleep(args.delay); - int64_t msecs = - publisher.publish(args.messages, - args.subscribers, - args.size) / TIME_MSEC; - if(!max || msecs > max) max = msecs; - if(!min || msecs < min) min = msecs; - sum += msecs; - cout << "Completed " << (i+1) << " of " << batchSize - << " in " << msecs << "ms" << endl; - } - publisher.terminate(); - int64_t avg = sum / batchSize; - if(batchSize > 1){ - cout << batchSize << " batches completed. avg=" << avg << - ", max=" << max << ", min=" << min << endl; - } - session.close(); - connection.close(); - } - return 0; - }catch(exception& error) { - cout << error.what() << endl; - } - return 1; -} diff --git a/cpp/src/tests/qpid-txtest.cpp b/cpp/src/tests/qpid-txtest.cpp deleted file mode 100644 index d0ba2f1245..0000000000 --- a/cpp/src/tests/qpid-txtest.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <algorithm> -#include <iomanip> -#include <iostream> -#include <memory> -#include <sstream> -#include <vector> - -#include "TestOptions.h" -#include "qpid/client/Connection.h" -#include "qpid/client/Message.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/framing/Array.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/Thread.h" - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::sys; -using std::string; - -namespace qpid { -namespace tests { - -typedef std::vector<std::string> StringSet; - -struct Args : public qpid::TestOptions { - bool init, transfer, check;//actions - uint size; - bool durable; - uint queues; - string base; - uint msgsPerTx; - uint txCount; - uint totalMsgCount; - bool dtx; - bool quiet; - - Args() : init(true), transfer(true), check(true), - size(256), durable(true), queues(2), - base("tx-test"), msgsPerTx(1), txCount(1), totalMsgCount(10), - dtx(false), quiet(false) - { - addOptions() - - ("init", optValue(init, "yes|no"), "Declare queues and populate one with the initial set of messages.") - ("transfer", optValue(transfer, "yes|no"), "'Move' messages from one queue to another using transactions to ensure no message loss.") - ("check", optValue(check, "yes|no"), "Check that the initial messages are all still available.") - ("size", optValue(size, "N"), "message size") - ("durable", optValue(durable, "yes|no"), "use durable messages") - ("queues", optValue(queues, "N"), "number of queues") - ("queue-base-name", optValue(base, "<name>"), "base name for queues") - ("messages-per-tx", optValue(msgsPerTx, "N"), "number of messages transferred per transaction") - ("tx-count", optValue(txCount, "N"), "number of transactions per 'agent'") - ("total-messages", optValue(totalMsgCount, "N"), "total number of messages in 'circulation'") - ("dtx", optValue(dtx, "yes|no"), "use distributed transactions") - ("quiet", optValue(quiet), "reduce output from test"); - } -}; - -const std::string chars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); - -std::string generateData(uint size) -{ - if (size < chars.length()) { - return chars.substr(0, size); - } - std::string data; - for (uint i = 0; i < (size / chars.length()); i++) { - data += chars; - } - data += chars.substr(0, size % chars.length()); - return data; -} - -void generateSet(const std::string& base, uint count, StringSet& collection) -{ - for (uint i = 0; i < count; i++) { - std::ostringstream out; - out << base << "-" << (i+1); - collection.push_back(out.str()); - } -} - -Args opts; - -struct Client -{ - Connection connection; - AsyncSession session; - - Client() - { - opts.open(connection); - session = connection.newSession(); - } - - ~Client() - { - try{ - session.close(); - connection.close(); - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - } - } -}; - -struct Transfer : public Client, public Runnable -{ - std::string src; - std::string dest; - Thread thread; - framing::Xid xid; - - Transfer(const std::string& to, const std::string& from) : src(to), dest(from), xid(0x4c414e47, "", from) {} - - void run() - { - try { - - if (opts.dtx) session.dtxSelect(); - else session.txSelect(); - SubscriptionManager subs(session); - - LocalQueue lq; - SubscriptionSettings settings(FlowControl::messageWindow(opts.msgsPerTx)); - settings.autoAck = 0; // Disabled - Subscription sub = subs.subscribe(lq, src, settings); - - for (uint t = 0; t < opts.txCount; t++) { - Message in; - Message out("", dest); - if (opts.dtx) { - setNewXid(xid); - session.dtxStart(arg::xid=xid); - } - for (uint m = 0; m < opts.msgsPerTx; m++) { - in = lq.pop(); - std::string& data = in.getData(); - if (data.size() != opts.size) { - std::ostringstream oss; - oss << "Message size incorrect: size=" << in.getData().size() << "; expected " << opts.size; - throw std::runtime_error(oss.str()); - } - out.setData(data); - out.getMessageProperties().setCorrelationId(in.getMessageProperties().getCorrelationId()); - out.getDeliveryProperties().setDeliveryMode(in.getDeliveryProperties().getDeliveryMode()); - session.messageTransfer(arg::content=out, arg::acceptMode=1); - } - sub.accept(sub.getUnaccepted()); - if (opts.dtx) { - session.dtxEnd(arg::xid=xid); - session.dtxPrepare(arg::xid=xid); - session.dtxCommit(arg::xid=xid); - } else { - session.txCommit(); - } - } - } catch(const std::exception& e) { - std::cout << "Transfer interrupted: " << e.what() << std::endl; - } - } - - void setNewXid(framing::Xid& xid) { - framing::Uuid uuid(true); - xid.setGlobalId(uuid.str()); - } -}; - -struct Controller : public Client -{ - StringSet ids; - StringSet queues; - - Controller() - { - generateSet(opts.base, opts.queues, queues); - generateSet("msg", opts.totalMsgCount, ids); - } - - void init() - { - //declare queues - for (StringSet::iterator i = queues.begin(); i != queues.end(); i++) { - session.queueDeclare(arg::queue=*i, arg::durable=opts.durable); - session.sync(); - } - - Message msg(generateData(opts.size), *queues.begin()); - if (opts.durable) { - msg.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - - //publish messages - for (StringSet::iterator i = ids.begin(); i != ids.end(); i++) { - msg.getMessageProperties().setCorrelationId(*i); - session.messageTransfer(arg::content=msg, arg::acceptMode=1); - } - } - - void transfer() - { - boost::ptr_vector<Transfer> agents(opts.queues); - //launch transfer agents - for (StringSet::iterator i = queues.begin(); i != queues.end(); i++) { - StringSet::iterator next = i + 1; - if (next == queues.end()) next = queues.begin(); - - if (!opts.quiet) std::cout << "Transfering from " << *i << " to " << *next << std::endl; - agents.push_back(new Transfer(*i, *next)); - agents.back().thread = Thread(agents.back()); - } - - for (boost::ptr_vector<Transfer>::iterator i = agents.begin(); i != agents.end(); i++) { - i->thread.join(); - } - } - - int check() - { - SubscriptionManager subs(session); - - // Recover DTX transactions (if any) - if (opts.dtx) { - std::vector<std::string> inDoubtXids; - framing::DtxRecoverResult dtxRes = session.dtxRecover().get(); - const framing::Array& xidArr = dtxRes.getInDoubt(); - xidArr.collect(inDoubtXids); - - if (inDoubtXids.size()) { - if (!opts.quiet) std::cout << "Recovering DTX in-doubt transaction(s):" << std::endl; - framing::StructHelper decoder; - framing::Xid xid; - // abort even, commit odd transactions - for (unsigned i = 0; i < inDoubtXids.size(); i++) { - decoder.decode(xid, inDoubtXids[i]); - if (!opts.quiet) std::cout << (i%2 ? " * aborting " : " * committing "); - xid.print(std::cout); - std::cout << std::endl; - if (i%2) { - session.dtxRollback(arg::xid=xid); - } else { - session.dtxCommit(arg::xid=xid); - } - } - } - } - - StringSet drained; - //drain each queue and verify the correct set of messages are available - for (StringSet::iterator i = queues.begin(); i != queues.end(); i++) { - //subscribe, allocate credit and flushn - LocalQueue lq; - SubscriptionSettings settings(FlowControl::unlimited(), ACCEPT_MODE_NONE); - subs.subscribe(lq, *i, settings); - session.messageFlush(arg::destination=*i); - session.sync(); - - uint count(0); - while (!lq.empty()) { - Message m = lq.pop(); - //add correlation ids of received messages to drained - drained.push_back(m.getMessageProperties().getCorrelationId()); - ++count; - } - if (!opts.quiet) std::cout << "Drained " << count << " messages from " << *i << std::endl; - } - - sort(ids.begin(), ids.end()); - sort(drained.begin(), drained.end()); - - //check that drained == ids - StringSet missing; - set_difference(ids.begin(), ids.end(), drained.begin(), drained.end(), back_inserter(missing)); - - StringSet extra; - set_difference(drained.begin(), drained.end(), ids.begin(), ids.end(), back_inserter(extra)); - - if (missing.empty() && extra.empty()) { - std::cout << "All expected messages were retrieved." << std::endl; - return 0; - } else { - if (!missing.empty()) { - std::cout << "The following ids were missing:" << std::endl; - for (StringSet::iterator i = missing.begin(); i != missing.end(); i++) { - std::cout << " '" << *i << "'" << std::endl; - } - } - if (!extra.empty()) { - std::cout << "The following extra ids were encountered:" << std::endl; - for (StringSet::iterator i = extra.begin(); i != extra.end(); i++) { - std::cout << " '" << *i << "'" << std::endl; - } - } - return 1; - } - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - try { - opts.parse(argc, argv); - Controller controller; - if (opts.init) controller.init(); - if (opts.transfer) controller.transfer(); - if (opts.check) return controller.check(); - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - } - return 2; -} diff --git a/cpp/src/tests/queue_flow_limit_tests.py b/cpp/src/tests/queue_flow_limit_tests.py deleted file mode 100644 index dec7cfb3af..0000000000 --- a/cpp/src/tests/queue_flow_limit_tests.py +++ /dev/null @@ -1,371 +0,0 @@ -#!/usr/bin/env python -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import sys -from qpid.testlib import TestBase010 -from qpid import datatypes, messaging -from qpid.messaging import Message, Empty -from threading import Thread, Lock -from logging import getLogger -from time import sleep, time -from os import environ, popen - -class QueueFlowLimitTests(TestBase010): - - def __getattr__(self, name): - if name == "assertGreater": - return lambda a, b: self.failUnless(a > b) - else: - raise AttributeError - - def _create_queue(self, name, - stop_count=None, resume_count=None, - stop_size=None, resume_size=None, - max_size=None, max_count=None): - """ Create a queue with the given flow settings via the queue.declare - command. - """ - args={} - if (stop_count is not None): - args["qpid.flow_stop_count"] = stop_count; - if (resume_count is not None): - args["qpid.flow_resume_count"] = resume_count; - if (stop_size is not None): - args["qpid.flow_stop_size"] = stop_size; - if (resume_size is not None): - args["qpid.flow_resume_size"] = resume_size; - if (max_size is not None): - args["qpid.max_size"] = max_size; - if (max_count is not None): - args["qpid.max_count"] = max_count; - - - self.session.queue_declare(queue=name, arguments=args) - - qs = self.qmf.getObjects(_class="queue") - for i in qs: - if i.name == name: - # verify flow settings - if (stop_count is not None): - self.assertEqual(i.arguments.get("qpid.flow_stop_count"), stop_count) - if (resume_count is not None): - self.assertEqual(i.arguments.get("qpid.flow_resume_count"), resume_count) - if (stop_size is not None): - self.assertEqual(i.arguments.get("qpid.flow_stop_size"), stop_size) - if (resume_size is not None): - self.assertEqual(i.arguments.get("qpid.flow_resume_size"), resume_size) - if (max_size is not None): - self.assertEqual(i.arguments.get("qpid.max_size"), max_size) - if (max_count is not None): - self.assertEqual(i.arguments.get("qpid.max_count"), max_count) - self.failIf(i.flowStopped) - return i.getObjectId() - self.fail("Unable to create queue '%s'" % name) - return None - - - def _delete_queue(self, name): - """ Delete a named queue - """ - self.session.queue_delete(queue=name) - - - def _start_qpid_send(self, queue, count, content="X", capacity=100): - """ Use the qpid-send client to generate traffic to a queue. - """ - command = "qpid-send" + \ - " -b" + " %s:%s" % (self.broker.host, self.broker.port) \ - + " -a " + str(queue) \ - + " --messages " + str(count) \ - + " --content-string " + str(content) \ - + " --capacity " + str(capacity) - return popen(command) - - def _start_qpid_receive(self, queue, count, timeout=5): - """ Use the qpid-receive client to consume from a queue. - Note well: prints one line of text to stdout for each consumed msg. - """ - command = "qpid-receive" + \ - " -b " + "%s:%s" % (self.broker.host, self.broker.port) \ - + " -a " + str(queue) \ - + " --messages " + str(count) \ - + " --timeout " + str(timeout) \ - + " --print-content yes" - return popen(command) - - def test_qpid_config_cmd(self): - """ Test the qpid-config command's ability to configure a queue's flow - control thresholds. - """ - tool = environ.get("QPID_CONFIG_EXEC") - if tool: - command = tool + \ - " --broker-addr=%s:%s " % (self.broker.host, self.broker.port) \ - + "add queue test01 --flow-stop-count=999" \ - + " --flow-resume-count=55 --flow-stop-size=5000000" \ - + " --flow-resume-size=100000" - cmd = popen(command) - rc = cmd.close() - self.assertEqual(rc, None) - - # now verify the settings - self.startQmf(); - qs = self.qmf.getObjects(_class="queue") - for i in qs: - if i.name == "test01": - self.assertEqual(i.arguments.get("qpid.flow_stop_count"), 999) - self.assertEqual(i.arguments.get("qpid.flow_resume_count"), 55) - self.assertEqual(i.arguments.get("qpid.flow_stop_size"), 5000000) - self.assertEqual(i.arguments.get("qpid.flow_resume_size"), 100000) - self.failIf(i.flowStopped) - break; - self.assertEqual(i.name, "test01") - self._delete_queue("test01") - - - def test_flow_count(self): - """ Create a queue with count-based flow limit. Spawn several - producers which will exceed the limit. Verify limit exceeded. Consume - all messages. Verify flow control released. - """ - self.startQmf(); - oid = self._create_queue("test-q", stop_count=373, resume_count=229) - self.assertEqual(self.qmf.getObjects(_objectId=oid)[0].flowStoppedCount, 0) - - sndr1 = self._start_qpid_send("test-q", count=1213, content="XXX", capacity=50); - sndr2 = self._start_qpid_send("test-q", count=797, content="Y", capacity=13); - sndr3 = self._start_qpid_send("test-q", count=331, content="ZZZZZ", capacity=149); - totalMsgs = 1213 + 797 + 331 - - # wait until flow control is active - deadline = time() + 10 - while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \ - time() < deadline: - pass - self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStopped) - depth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - self.assertGreater(depth, 373) - - # now wait until the enqueues stop happening - ensure that - # not all msgs have been sent (senders are blocked) - sleep(1) - newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - while depth != newDepth: - depth = newDepth; - sleep(1) - newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - self.assertGreater(totalMsgs, depth) - - # drain the queue - rcvr = self._start_qpid_receive("test-q", - count=totalMsgs) - count = 0; - x = rcvr.readline() # prints a line for each received msg - while x: - count += 1; - x = rcvr.readline() - - sndr1.close(); - sndr2.close(); - sndr3.close(); - rcvr.close(); - - self.assertEqual(count, totalMsgs) - self.failIf(self.qmf.getObjects(_objectId=oid)[0].flowStopped) - self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStoppedCount) - - self._delete_queue("test-q") - - - def test_flow_size(self): - """ Create a queue with size-based flow limit. Spawn several - producers which will exceed the limit. Verify limit exceeded. Consume - all messages. Verify flow control released. - """ - self.startQmf(); - oid = self._create_queue("test-q", stop_size=351133, resume_size=251143) - - sndr1 = self._start_qpid_send("test-q", count=1699, content="X"*439, capacity=53); - sndr2 = self._start_qpid_send("test-q", count=1129, content="Y"*631, capacity=13); - sndr3 = self._start_qpid_send("test-q", count=881, content="Z"*823, capacity=149); - totalMsgs = 1699 + 1129 + 881 - - # wait until flow control is active - deadline = time() + 10 - while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \ - time() < deadline: - pass - self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStopped) - self.assertGreater(self.qmf.getObjects(_objectId=oid)[0].byteDepth, 351133) - - # now wait until the enqueues stop happening - ensure that - # not all msgs have been sent (senders are blocked) - depth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - sleep(1) - newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - while depth != newDepth: - depth = newDepth; - sleep(1) - newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth - self.assertGreater(totalMsgs, depth) - - # drain the queue - rcvr = self._start_qpid_receive("test-q", - count=totalMsgs) - count = 0; - x = rcvr.readline() # prints a line for each received msg - while x: - count += 1; - x = rcvr.readline() - - sndr1.close(); - sndr2.close(); - sndr3.close(); - rcvr.close(); - - self.assertEqual(count, totalMsgs) - self.failIf(self.qmf.getObjects(_objectId=oid)[0].flowStopped) - - self._delete_queue("test-q") - - - def verify_limit(self, testq): - """ run a limit check against the testq object - """ - - testq.mgmt = self.qmf.getObjects(_objectId=testq.oid)[0] - - # fill up the queue, waiting until flow control is active - sndr1 = self._start_qpid_send(testq.mgmt.name, count=testq.sendCount, content=testq.content) - deadline = time() + 10 - while (not testq.mgmt.flowStopped) and time() < deadline: - testq.mgmt.update() - - self.failUnless(testq.verifyStopped()) - - # now consume enough messages to drop below the flow resume point, and - # verify flow control is released. - rcvr = self._start_qpid_receive(testq.mgmt.name, count=testq.consumeCount) - rcvr.readlines() # prints a line for each received msg - rcvr.close(); - - # we should now be below the resume threshold - self.failUnless(testq.verifyResumed()) - - self._delete_queue(testq.mgmt.name) - sndr1.close(); - - - def test_default_flow_count(self): - """ Create a queue with count-based size limit, and verify the computed - thresholds using the broker's default ratios. - """ - class TestQ: - def __init__(self, oid): - # Use the broker-wide default flow thresholds of 80%/70% (see - # run_queue_flow_limit_tests) to base the thresholds off the - # queue's max_count configuration parameter - # max_count == 1000 -> stop == 800, resume == 700 - self.oid = oid - self.sendCount = 1000 - self.consumeCount = 301 # (send - resume) + 1 to reenable flow - self.content = "X" - def verifyStopped(self): - self.mgmt.update() - return self.mgmt.flowStopped and (self.mgmt.msgDepth > 800) - def verifyResumed(self): - self.mgmt.update() - return (not self.mgmt.flowStopped) and (self.mgmt.msgDepth < 700) - - self.startQmf(); - oid = self._create_queue("test-X", max_count=1000) - self.verify_limit(TestQ(oid)) - - - def test_default_flow_size(self): - """ Create a queue with byte-based size limit, and verify the computed - thresholds using the broker's default ratios. - """ - class TestQ: - def __init__(self, oid): - # Use the broker-wide default flow thresholds of 80%/70% (see - # run_queue_flow_limit_tests) to base the thresholds off the - # queue's max_count configuration parameter - # max_size == 10000 -> stop == 8000 bytes, resume == 7000 bytes - self.oid = oid - self.sendCount = 2000 - self.consumeCount = 601 # (send - resume) + 1 to reenable flow - self.content = "XXXXX" # 5 bytes per message sent. - def verifyStopped(self): - self.mgmt.update() - return self.mgmt.flowStopped and (self.mgmt.byteDepth > 8000) - def verifyResumed(self): - self.mgmt.update() - return (not self.mgmt.flowStopped) and (self.mgmt.byteDepth < 7000) - - self.startQmf(); - oid = self._create_queue("test-Y", max_size=10000) - self.verify_limit(TestQ(oid)) - - - def test_blocked_queue_delete(self): - """ Verify that blocked senders are unblocked when a queue that is flow - controlled is deleted. - """ - - class BlockedSender(Thread): - def __init__(self, tester, queue, count, capacity=10): - self.tester = tester - self.queue = queue - self.count = count - self.capacity = capacity - Thread.__init__(self) - self.done = False - self.start() - def run(self): - # spawn qpid-send - p = self.tester._start_qpid_send(self.queue, - self.count, - self.capacity) - p.close() # waits for qpid-send to complete - self.done = True - - self.startQmf(); - oid = self._create_queue("kill-q", stop_size=10, resume_size=2) - q = self.qmf.getObjects(_objectId=oid)[0] - self.failIf(q.flowStopped) - - sender = BlockedSender(self, "kill-q", count=100) - # wait for flow control - deadline = time() + 10 - while (not q.flowStopped) and time() < deadline: - q.update() - - self.failUnless(q.flowStopped) - self.failIf(sender.done) # sender blocked - - self._delete_queue("kill-q") - sender.join(5) - self.failIf(sender.isAlive()) - self.failUnless(sender.done) - - - - diff --git a/cpp/src/tests/quick_perftest b/cpp/src/tests/quick_perftest deleted file mode 100755 index 362f9ee96a..0000000000 --- a/cpp/src/tests/quick_perftest +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -exec `dirname $0`/run_test ./qpid-perftest --summary --count 100 diff --git a/cpp/src/tests/quick_topictest b/cpp/src/tests/quick_topictest deleted file mode 100755 index 0a6b29b33f..0000000000 --- a/cpp/src/tests/quick_topictest +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -# Quick and quiet topic test for make check. -test -z "$srcdir" && srcdir=`dirname $0` -$srcdir/topictest -s2 -m2 -b1 > topictest.log 2>&1 || { - echo $0 FAILED: - cat topictest.log - exit 1 -} -rm topictest.log diff --git a/cpp/src/tests/quick_topictest.ps1 b/cpp/src/tests/quick_topictest.ps1 deleted file mode 100644 index 8f5b2caff7..0000000000 --- a/cpp/src/tests/quick_topictest.ps1 +++ /dev/null @@ -1,30 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Quick and quiet topic test for make check. -[string]$me = $myInvocation.InvocationName -$srcdir = Split-Path $me -Invoke-Expression "$srcdir\topictest.ps1 -subscribers 2 -messages 2 -batches 1" > topictest.log 2>&1 -if (!$?) { - "$me FAILED:" - cat topictest.log - exit 1 -} -Remove-Item topictest.log -exit 0 diff --git a/cpp/src/tests/quick_txtest b/cpp/src/tests/quick_txtest deleted file mode 100755 index c872fcec12..0000000000 --- a/cpp/src/tests/quick_txtest +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -exec `dirname $0`/run_test ./qpid-txtest --queues 4 --tx-count 10 --quiet diff --git a/cpp/src/tests/receiver.cpp b/cpp/src/tests/receiver.cpp deleted file mode 100644 index f1b462d6e4..0000000000 --- a/cpp/src/tests/receiver.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/client/FailoverManager.h> -#include <qpid/client/Session.h> -#include <qpid/client/Message.h> -#include <qpid/client/SubscriptionManager.h> -#include <qpid/client/SubscriptionSettings.h> -#include "TestOptions.h" - -#include <iostream> -#include <fstream> - - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; - -using namespace std; - -namespace qpid { -namespace tests { - -struct Args : public qpid::TestOptions -{ - string queue; - uint messages; - bool ignoreDuplicates; - uint creditWindow; - uint ackFrequency; - bool browse; - - Args() : queue("test-queue"), messages(0), ignoreDuplicates(false), creditWindow(0), ackFrequency(1), browse(false) - { - addOptions() - ("queue", qpid::optValue(queue, "QUEUE NAME"), "Queue from which to request messages") - ("messages", qpid::optValue(messages, "N"), "Number of messages to receive; 0 means receive indefinitely") - ("ignore-duplicates", qpid::optValue(ignoreDuplicates), "Detect and ignore duplicates (by checking 'sn' header)") - ("credit-window", qpid::optValue(creditWindow, "N"), "Credit window (0 implies infinite window)") - ("ack-frequency", qpid::optValue(ackFrequency, "N"), "Ack frequency (0 implies none of the messages will get accepted)") - ("browse", qpid::optValue(browse), "Browse rather than consuming"); - } -}; - -const string EOS("eos"); -const string SN("sn"); - -class Receiver : public MessageListener, public FailoverManager::Command -{ - public: - Receiver(const string& queue, uint messages, bool ignoreDuplicates, uint creditWindow, uint ackFrequency, bool browse); - void received(Message& message); - void execute(AsyncSession& session, bool isRetry); - private: - const string queue; - const uint count; - const bool skipDups; - SubscriptionSettings settings; - Subscription subscription; - uint processed; - uint lastSn; - - bool isDuplicate(Message& message); -}; - -Receiver::Receiver(const string& q, uint messages, bool ignoreDuplicates, uint creditWindow, uint ackFrequency, bool browse) : - queue(q), count(messages), skipDups(ignoreDuplicates), processed(0), lastSn(0) -{ - if (browse) settings.acquireMode = ACQUIRE_MODE_NOT_ACQUIRED; - if (creditWindow) settings.flowControl = FlowControl::messageWindow(creditWindow); - settings.autoAck = ackFrequency; -} - -void Receiver::received(Message& message) -{ - if (!(skipDups && isDuplicate(message))) { - bool eos = message.getData() == EOS; - if (!eos) std::cout << message.getData() << std::endl; - if (eos || ++processed == count) subscription.cancel(); - } -} - -bool Receiver::isDuplicate(Message& message) -{ - uint sn = message.getHeaders().getAsInt(SN); - if (lastSn < sn) { - lastSn = sn; - return false; - } else { - return true; - } -} - -void Receiver::execute(AsyncSession& session, bool /*isRetry*/) -{ - SubscriptionManager subs(session); - subscription = subs.subscribe(*this, queue, settings); - subs.run(); - if (settings.autoAck) { - subscription.accept(subscription.getUnaccepted()); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - Args opts; - try { - opts.parse(argc, argv); - FailoverManager connection(opts.con); - Receiver receiver(opts.queue, opts.messages, opts.ignoreDuplicates, opts.creditWindow, opts.ackFrequency, opts.browse); - connection.execute(receiver); - connection.close(); - return 0; - } catch(const std::exception& error) { - std::cerr << "Failure: " << error.what() << std::endl; - } - return 1; -} diff --git a/cpp/src/tests/reliable_replication_test b/cpp/src/tests/reliable_replication_test deleted file mode 100755 index f57d11a263..0000000000 --- a/cpp/src/tests/reliable_replication_test +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Test reliability of the replication feature in the face of link -# failures: - -source ./test_env.sh - -trap stop_brokers EXIT - -stop_brokers() { - if [[ $BROKER_A ]] ; then - $QPIDD_EXEC --no-module-dir -q --port $BROKER_A - unset BROKER_A - fi - if [[ $BROKER_B ]] ; then - $QPIDD_EXEC --no-module-dir -q --port $BROKER_B - unset BROKER_B - fi -} - -setup() { - rm -f replication-source.log replication-dest.log - $QPIDD_EXEC --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module $REPLICATING_LISTENER_LIB --replication-queue replication --create-replication-queue true --log-enable trace+ --log-to-file replication-source.log --log-to-stderr 0 > qpidd-repl.port - BROKER_A=`cat qpidd-repl.port` - - $QPIDD_EXEC --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module $REPLICATION_EXCHANGE_LIB --log-enable info+ --log-to-file replication-dest.log --log-to-stderr 0 > qpidd-repl.port - BROKER_B=`cat qpidd-repl.port` - - echo "Testing replication from port $BROKER_A to port $BROKER_B" - - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication - $PYTHON_COMMANDS/qpid-route --ack 500 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication - - #create test queue (only replicate enqueues for this test): - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-a --generate-queue-events 1 - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-a -} - -send() { - ./sender --port $BROKER_A --routing-key queue-a --send-eos 1 < replicated.expected -} - -receive() { - rm -f replicated.actual - ./receiver --port $BROKER_B --queue queue-a > replicated.actual -} - -bounce_link() { - echo "Destroying link..." - $PYTHON_COMMANDS/qpid-route link del "localhost:$BROKER_B" "localhost:$BROKER_A" - echo "Link destroyed; recreating route..." - sleep 2 - $PYTHON_COMMANDS/qpid-route --ack 500 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication - echo "Route re-established" -} - -if test -d ${PYTHON_DIR} && test -e $REPLICATING_LISTENER_LIB && test -e $REPLICATION_EXCHANGE_LIB ; then - setup - for i in `seq 1 100000`; do echo Message $i; done > replicated.expected - send & - receive & - for i in `seq 1 5`; do sleep 10; bounce_link; done; - wait - #check that received list is identical to sent list - diff replicated.actual replicated.expected || FAIL=1 - if [[ $FAIL ]]; then - echo reliable replication test failed: expectations not met! - exit 1 - else - echo replication reliable in the face of link failures - rm -f replication.actual replication.expected replication-source.log replication-dest.log qpidd-repl.port - fi -fi - diff --git a/cpp/src/tests/replaying_sender.cpp b/cpp/src/tests/replaying_sender.cpp deleted file mode 100644 index a5549bfdf2..0000000000 --- a/cpp/src/tests/replaying_sender.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/client/FailoverManager.h> -#include <qpid/client/Session.h> -#include <qpid/client/AsyncSession.h> -#include <qpid/client/Message.h> -#include <qpid/client/MessageReplayTracker.h> -#include <qpid/Exception.h> - -#include <iostream> -#include <sstream> - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; - -using namespace std; - -namespace qpid { -namespace tests { - -class Sender : public FailoverManager::Command -{ - public: - Sender(const std::string& queue, uint count, uint reportFreq); - void execute(AsyncSession& session, bool isRetry); - uint getSent(); - - void setVerbosity ( int v ) { verbosity = v; } - void setPersistence ( int p ) { persistence = p; } - - private: - MessageReplayTracker sender; - const uint count; - uint sent; - const uint reportFrequency; - Message message; - int verbosity; - int persistence; - string queueName; -}; - -Sender::Sender(const std::string& queue, uint count_, uint reportFreq ) - : sender(10), - count(count_), - sent(0), - reportFrequency(reportFreq), - verbosity(0), - persistence(0), - queueName ( queue ) -{ - message.getDeliveryProperties().setRoutingKey(queueName.c_str()); -} - -const string SN("sn"); - -void Sender::execute(AsyncSession& session, bool isRetry) -{ - if (verbosity > 0) - std::cout << "replaying_sender " << (isRetry ? "first " : "re-") << "connect." << endl; - if (isRetry) sender.replay(session); - else sender.init(session); - while (sent < count) { - stringstream message_data; - message_data << ++sent; - message.setData(message_data.str()); - message.getHeaders().setInt(SN, sent); - if ( persistence ) - message.getDeliveryProperties().setDeliveryMode(PERSISTENT); - - sender.send(message); - if (count > reportFrequency && !(sent % reportFrequency)) { - if ( verbosity > 0 ) - std::cout << "Sender sent " - << sent - << " of " - << count - << " on queue " - << queueName - << std::endl; - } - } - message.setData("That's all, folks!"); - sender.send(message); - - if ( verbosity > 0 ) - std::cout << "SENDER COMPLETED\n"; -} - -uint Sender::getSent() -{ - return sent; -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - ConnectionSettings settings; - - if ( argc != 8 ) - { - std::cerr << "Usage: replaying_sender host port n_messages report_frequency verbosity persistence queue_name\n"; - return 1; - } - - settings.host = argv[1]; - settings.port = atoi(argv[2]); - int n_messages = atoi(argv[3]); - int reportFrequency = atoi(argv[4]); - int verbosity = atoi(argv[5]); - int persistence = atoi(argv[6]); - char * queue_name = argv[7]; - - FailoverManager connection(settings); - Sender sender(queue_name, n_messages, reportFrequency ); - sender.setVerbosity ( verbosity ); - sender.setPersistence ( persistence ); - try { - connection.execute ( sender ); - if ( verbosity > 0 ) - { - std::cout << "Sender finished. Sent " - << sender.getSent() - << " messages on queue " - << queue_name - << endl; - } - connection.close(); - return 0; - } - catch(const std::exception& error) - { - cerr << "Sender (host: " - << settings.host - << " port: " - << settings.port - << " ) " - << " Failed: " - << error.what() - << std::endl; - } - return 1; -} diff --git a/cpp/src/tests/replication_test b/cpp/src/tests/replication_test deleted file mode 100755 index 8c37568875..0000000000 --- a/cpp/src/tests/replication_test +++ /dev/null @@ -1,182 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run a test of the replication feature - -source ./test_env.sh - -trap stop_brokers INT TERM QUIT - -stop_brokers() { - if [ x$BROKER_A != x ]; then - $QPIDD_EXEC --no-module-dir -q --port $BROKER_A - unset BROKER_A - fi - if [ x$BROKER_B != x ]; then - $QPIDD_EXEC --no-module-dir -q --port $BROKER_B - unset BROKER_B - fi -} - -if test -d ${PYTHON_DIR} && test -f "$REPLICATING_LISTENER_LIB" && test -f "$REPLICATION_EXCHANGE_LIB"; then - rm -f queue-*.repl replication-*.log #cleanup from any earlier runs - - $QPIDD_EXEC --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module $REPLICATING_LISTENER_LIB --replication-queue replication --create-replication-queue true --log-enable info+ --log-to-file replication-source.log --log-to-stderr 0 > qpidd.port - BROKER_A=`cat qpidd.port` - - $QPIDD_EXEC --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module $REPLICATION_EXCHANGE_LIB --log-enable info+ --log-to-file replication-dest.log --log-to-stderr 0 > qpidd.port - BROKER_B=`cat qpidd.port` - echo "Running replication test between localhost:$BROKER_A and localhost:$BROKER_B" - - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication - $PYTHON_COMMANDS/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication - - #create test queues - - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-a --generate-queue-events 2 - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-b --generate-queue-events 2 - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-c --generate-queue-events 1 - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-d --generate-queue-events 2 - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-e --generate-queue-events 1 - - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-a - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-b - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-c - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-e - #queue-d deliberately not declared on DR; this error case should be handled - - #publish and consume from test queues on broker A: - i=1 - while [ $i -le 10 ]; do - echo Message $i for A >> queue-a-input.repl - i=`expr $i + 1` - done - i=1 - while [ $i -le 20 ]; do - echo Message $i for B >> queue-b-input.repl - i=`expr $i + 1` - done - i=1 - while [ $i -le 15 ]; do - echo Message $i for C >> queue-c-input.repl - i=`expr $i + 1` - done - - ./sender --port $BROKER_A --routing-key queue-a --send-eos 1 < queue-a-input.repl - ./sender --port $BROKER_A --routing-key queue-b --send-eos 1 < queue-b-input.repl - ./sender --port $BROKER_A --routing-key queue-c --send-eos 1 < queue-c-input.repl - echo dummy | ./sender --port $BROKER_A --routing-key queue-d --send-eos 1 - - ./receiver --port $BROKER_A --queue queue-a --messages 5 > /dev/null - ./receiver --port $BROKER_A --queue queue-b --messages 10 > /dev/null - ./receiver --port $BROKER_A --queue queue-c --messages 10 > /dev/null - ./receiver --port $BROKER_A --queue queue-d > /dev/null - - - # What we are doing is putting a message on the end of repliaction queue & waiting for it on remote side - # making sure all the messages have been flushed from the replication queue. - echo dummy | ./sender --port $BROKER_A --routing-key queue-e --send-eos 1 - ./receiver --port $BROKER_B --queue queue-e --messages 1 > /dev/null - - #shutdown broker A then check that broker Bs versions of the queues are as expected - $QPIDD_EXEC --no-module-dir -q --port $BROKER_A - unset BROKER_A - - #validate replicated queues: - ./receiver --port $BROKER_B --queue queue-a > queue-a-backup.repl - ./receiver --port $BROKER_B --queue queue-b > queue-b-backup.repl - ./receiver --port $BROKER_B --queue queue-c > queue-c-backup.repl - - - tail -5 queue-a-input.repl > queue-a-expected.repl - tail -10 queue-b-input.repl > queue-b-expected.repl - diff queue-a-backup.repl queue-a-expected.repl || FAIL=1 - diff queue-b-backup.repl queue-b-expected.repl || FAIL=1 - diff queue-c-backup.repl queue-c-input.repl || FAIL=1 - - grep 'queue-d does not exist' replication-dest.log > /dev/null || echo "WARNING: Expected error to be logged!" - - stop_brokers - - # now check offsets working (enqueue based on position being set, not queue abs position) - - $QPIDD_EXEC --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module $REPLICATING_LISTENER_LIB --replication-queue replication --create-replication-queue true --log-enable info+ --log-to-file replication-source.log --log-to-stderr 0 > qpidd.port - BROKER_A=`cat qpidd.port` - - $QPIDD_EXEC --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module $REPLICATION_EXCHANGE_LIB --log-enable info+ --log-to-file replication-dest.log --log-to-stderr 0 > qpidd.port - BROKER_B=`cat qpidd.port` - - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication - $PYTHON_COMMANDS/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication - - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-e --generate-queue-events 2 - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-e - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_A" add queue queue-d --generate-queue-events 1 - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-d - - i=1 - while [ $i -le 10 ]; do - echo Message $i for A >> queue-e-input.repl - i=`expr $i + 1` - done - - ./sender --port $BROKER_A --routing-key queue-e --send-eos 1 < queue-e-input.repl - ./receiver --port $BROKER_A --queue queue-e --messages 10 > /dev/null - - # What we are doing is putting a message on the end of repliaction queue & waiting for it on remote side - # making sure all the messages have been flushed from the replication queue. - echo dummy | ./sender --port $BROKER_A --routing-key queue-d --send-eos 1 - ./receiver --port $BROKER_B --queue queue-d --messages 1 > /dev/null - - # now check offsets working - $QPIDD_EXEC --no-module-dir -q --port $BROKER_B - unset BROKER_B - $QPIDD_EXEC --daemon --port 0 --no-data-dir --no-module-dir --auth no --load-module $REPLICATION_EXCHANGE_LIB --log-enable info+ --log-to-file replication-dest.log --log-to-stderr 0 > qpidd.port - BROKER_B=`cat qpidd.port` - - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add queue queue-e - $PYTHON_COMMANDS/qpid-config -a "localhost:$BROKER_B" add exchange replication replication - $PYTHON_COMMANDS/qpid-route --ack 5 queue add "localhost:$BROKER_B" "localhost:$BROKER_A" replication replication - # now send another 15 - i=11 - while [ $i -le 15 ]; do - echo Message $i for A >> queue-e1-input.repl - i=`expr $i + 1` - done - ./sender --port $BROKER_A --routing-key queue-e --send-eos 1 < queue-e1-input.repl - - ./receiver --port $BROKER_B --queue queue-e > queue-e-backup.repl - diff queue-e-backup.repl queue-e1-input.repl || FAIL=1 - - stop_brokers - - if [ x$FAIL != x ]; then - echo replication test failed: expectations not met! - exit 1 - else - echo queue state replicated as expected - rm -f queue-*.repl replication-*.log - fi - -else - echo "Skipping replication test, plugins not built or python utils not located" -fi - diff --git a/cpp/src/tests/restart_cluster b/cpp/src/tests/restart_cluster deleted file mode 100755 index 6a6abc8042..0000000000 --- a/cpp/src/tests/restart_cluster +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Re-start a cluster on the local host. - -srcdir=`dirname $0` -$srcdir/stop_cluster -exec $srcdir/start_cluster "$@" -#!/bin/sh -# Re-start a cluster on the local host. - -srcdir=`dirname $0` -$srcdir/stop_cluster -exec $srcdir/start_cluster "$@" -#!/bin/sh -# Re-start a cluster on the local host. - -srcdir=`dirname $0` -$srcdir/stop_cluster -exec $srcdir/start_cluster "$@" diff --git a/cpp/src/tests/resuming_receiver.cpp b/cpp/src/tests/resuming_receiver.cpp deleted file mode 100644 index 2e22a7c572..0000000000 --- a/cpp/src/tests/resuming_receiver.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/client/FailoverManager.h> -#include <qpid/client/Session.h> -#include <qpid/client/Message.h> -#include <qpid/client/SubscriptionManager.h> - -#include <iostream> -#include <fstream> - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; - -using namespace std; - - - -namespace qpid { -namespace tests { - -class Listener : public MessageListener, - public FailoverManager::Command, - public FailoverManager::ReconnectionStrategy -{ - public: - Listener ( int report_frequency = 1000, - int verbosity = 0, - char const * queue_name = "message_queue" ); - void received(Message& message); - void execute(AsyncSession& session, bool isRetry); - void check(); - void editUrlList(vector<Url>& urls); - private: - Subscription subscription; - uint count; - vector<int> received_twice; - uint lastSn; - bool gaps; - uint reportFrequency; - int verbosity; - bool done; - string queueName; -}; - - -Listener::Listener ( int freq, int verbosity, char const * name ) - : count(0), - lastSn(0), - gaps(false), - reportFrequency(freq), - verbosity(verbosity), - done(false), - queueName ( name ) -{} - -const std::string SN("sn"); - -void Listener::received(Message & message) -{ - if (message.getData() == "That's all, folks!") - { - done = true; - if(verbosity > 0 ) - { - cout << "Shutting down listener for " - << message.getDestination() << endl; - - cout << "Listener received " - << count - << " messages (" - << received_twice.size() - << " received_twice)" - << endl; - - } - subscription.cancel(); - if ( verbosity > 0 ) - cout << "LISTENER COMPLETED\n"; - - if ( ! gaps ) { - cout << "no gaps were detected\n"; - cout << received_twice.size() << " messages were received twice.\n"; - } - else { - cout << "gaps detected\n"; - for ( unsigned int i = 0; i < received_twice.size(); ++ i ) - cout << "received_twice " - << received_twice[i] - << endl; - } - } else { - uint sn = message.getHeaders().getAsInt(SN); - if (lastSn < sn) { - if (sn - lastSn > 1) { - cerr << "Error: gap in sequence between " << lastSn << " and " << sn << endl; - gaps = true; - } - lastSn = sn; - ++count; - if ( ! ( count % reportFrequency ) ) { - if ( verbosity > 0 ) - cout << "Listener has received " - << count - << " messages on queue " - << queueName - << endl; - } - } else { - received_twice.push_back ( sn ); - } - } -} - -void Listener::check() -{ - if (gaps) throw Exception("Detected gaps in sequence; messages appear to have been lost."); -} - -void Listener::execute(AsyncSession& session, bool isRetry) { - if (verbosity > 0) - cout << "resuming_receiver " << (isRetry ? "first " : "re-") << "connect." << endl; - if (!done) { - SubscriptionManager subs(session); - subscription = subs.subscribe(*this, queueName); - subs.run(); - } -} - -void Listener::editUrlList(vector<Url>& urls) -{ - /** - * A more realistic algorithm would be to search through the list - * for prefered hosts and ensure they come first in the list. - */ - if (urls.size() > 1) rotate(urls.begin(), urls.begin() + 1, urls.end()); -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - ConnectionSettings settings; - - if ( argc != 6 ) - { - cerr << "Usage: resuming_receiver host port report_frequency verbosity queue_name\n"; - return 1; - } - - settings.host = argv[1]; - settings.port = atoi(argv[2]); - int reportFrequency = atoi(argv[3]); - int verbosity = atoi(argv[4]); - char * queue_name = argv[5]; - - Listener listener ( reportFrequency, verbosity, queue_name ); - FailoverManager connection(settings, &listener); - - try { - connection.execute(listener); - connection.close(); - listener.check(); - return 0; - } catch(const exception& error) { - cerr << "Receiver failed: " << error.what() << endl; - } - return 1; -} - - - diff --git a/cpp/src/tests/ring_queue_test b/cpp/src/tests/ring_queue_test deleted file mode 100755 index 553746eb49..0000000000 --- a/cpp/src/tests/ring_queue_test +++ /dev/null @@ -1,174 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Test script for validating the behaviour of a ring queue - -QUEUE_NAME=ring-queue -LIMIT=100 -DURABLE=0 -MESSAGES=10000 -SENDERS=1 -RECEIVERS=1 -CONCURRENT=0 -BROKER_URL="-a ${QPID_BROKER:-localhost}:${QPID_PORT:-5672}" - -setup() { - if [[ $DURABLE -gt 0 ]]; then - EXTRA_ARGS=" --durable" - fi - qpid-config $BROKER_URL add queue $QUEUE_NAME --max-queue-count $LIMIT --limit-policy ring $EXTRA_ARGS -} - -send() { - datagen --count $MESSAGES | tee sender_${QUEUE_NAME}_${1} | sender --durable $DURABLE --routing-key $QUEUE_NAME -} - -receive() { - #TODO: allow a variety of receiver options to be passed in (ack-frequency, credit-window etc) - receiver --queue $QUEUE_NAME > receiver_${QUEUE_NAME}_${1} -} - -cleanup() { - rm -f sender_${QUEUE_NAME}_* receiver_${QUEUE_NAME}_* - qpid-config $BROKER_URL del queue $QUEUE_NAME --force -} - -log() { - echo $1 -} - -fail() { - echo $1 - FAILED=1 -} - -validate() { - if [[ $RECEIVERS -eq 0 ]]; then - #queue should have $LIMIT messages on it, but need to send an eos also - sender --routing-key $QUEUE_NAME --send-eos 1 < /dev/null - received=$(receiver --queue $QUEUE_NAME --browse | wc -l) - if [[ received -eq $(( $LIMIT - 1)) ]]; then - log "queue contains $LIMIT messages as expected" - else - fail "queue does not contain the expected $LIMIT messages (received $received)" - fi - elif [[ $CONCURRENT -eq 0 ]]; then - #sum of length of all output files should be equal to $LIMIT - $RECEIVERS (1 eos message each) - received=$(cat receiver_${QUEUE_NAME}_* | wc -l) - expected=$(( $LIMIT - $RECEIVERS )) - if [[ $received -eq $expected ]]; then - log "received $LIMIT messages as expected" - else - fail "received $received messages, expected $expected" - fi - #if there were only a single sender and receiver (executed serially) we can check the - #actual received contents - if [[ $RECEIVERS -eq 1 ]] && [[ $SENDERS -eq 1 ]]; then - tail -n $(($LIMIT - 1)) sender_${QUEUE_NAME}_1 | diff - receiver_${QUEUE_NAME}_1 || FAILED=1 - if [[ $FAILED -eq 1 ]]; then - fail "did not receive expected messages" - else - log "received messages matched expectations" - fi - fi - else - #multiple receivers, concurrent with senders; ring queue functionality cannot be validated in this case - if [[ $(cat receiver_${QUEUE_NAME}_* | wc -l) -le $(cat sender_${QUEUE_NAME}_* | wc -l) ]]; then - log "sent at least as many messages as were received" - else - #Note: if any receiver was browsing, this would be valid (would need to add 'sort | uniq') - # to pipeline above - fail "received more messages than were sent" - fi - fi - - if [[ $FAILED ]]; then - echo $(basename $0): FAILED - exit 1 - else - cleanup - fi -} - -run_test() { - if [[ $CONCURRENT -eq 0 ]]; then - echo "Starting $SENDERS senders followed by $RECEIVERS receivers " - else - echo "Starting $SENDERS senders concurrently with $RECEIVERS receivers" - fi - for ((i=1; i <= $SENDERS; i++)); do - send $i & - sender_pids[$i]=$! - done - if [[ $CONCURRENT -eq 0 ]] && [[ $RECEIVERS -gt 0 ]]; then - wait - sender --routing-key $QUEUE_NAME --send-eos $RECEIVERS < /dev/null - fi - for ((i=1; i <= $RECEIVERS; i++)); do - receive $i & - done - if [[ $CONCURRENT -gt 0 ]]; then - for ((i=1; i <= $SENDERS; i++)); do - wait ${sender_pids[$i]} - done - sender --routing-key $QUEUE_NAME --send-eos $RECEIVERS < /dev/null - fi - wait -} - -usage() { - cat <<EOF -$(basename $0): Test script for validating the behaviour of a ring queue - -Options: - -q <queue> the name of the queue to use - -s <senders> the number of senders to start - -r <receivers> the number of receivers to start - -l <limit> the limit for the ring queue - -m <messages> the number of messages to send - -c if specified, receivers will run concurrently with senders - -d if specified the queue and messages will be durable -EOF - exit 1 -} - -while getopts "s:r:m:u:dch" opt ; do - case $opt in - q) QUEUE_NAME=$OPTARG ;; - l) LIMIT=$OPTARG ;; - s) SENDERS=$OPTARG ;; - r) RECEIVERS=$OPTARG ;; - m) MESSAGES=$OPTARG ;; - d) DURABLE=1 ;; - c) CONCURRENT=1 ;; - h) usage;; - ?) usage;; - esac -done - -if [[ $SENDERS -gt 0 ]]; then - setup - run_test - validate -else - echo "Nothing can be done if there are no senders" -fi - diff --git a/cpp/src/tests/rsynchosts b/cpp/src/tests/rsynchosts deleted file mode 100755 index 56ee57e898..0000000000 --- a/cpp/src/tests/rsynchosts +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under onemake -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -absdir() { echo `cd $1 && pwd`; } - -abspath() { - if test -d "$1"; then absdir "$1"; - else echo $(absdir $(dirname "$1"))/$(basename "$1") - fi -} - -usage() { - echo "Usage: $(basename $0) file [file...] -Synchronize the contents of each file or directory to the same absolute path on -each host in \$HOSTS. -" - exit 1 -} - -test "$*" || usage - -for f in $*; do FILES="$FILES $(abspath $f)" || exit 1; done - -OK_FILE=`mktemp` # Will be deleted if anything goes wrong. -trap "rm -f $OK_FILE" EXIT - -for h in $HOSTS; do - rsync -aRO --delete $FILES $h:/ || { echo "rsync to $h failed"; rm -f $OK_FILE; } & -done -wait -test -f $OK_FILE - diff --git a/cpp/src/tests/run-unit-tests b/cpp/src/tests/run-unit-tests deleted file mode 100755 index 862a76c4f5..0000000000 --- a/cpp/src/tests/run-unit-tests +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# -# Library names (without path or .so) and CppUnit test paths can be -# specified on the command line or in env var UNIT_TESTS. For example: -# -# Selected test classes: -# ./run-unit-tests ValueTest ClientChannelTest -# -# Individual test method -# ./run-unit-tests ValueTest :ValueTest::testStringValueEquals -# -# Build and run selected tests: -# make check TESTS=run-unit-tests UNIT_TESTS=ClientChannelTest -# - -for u in $* $UNIT_TESTS ; do - case $u in - :*) TEST_ARGS="$TEST_ARGS $u" ;; # A test path. - *) TEST_ARGS="$TEST_ARGS .libs/$u.so" ;; # A test library. - esac -done -test -z "$TEST_ARGS" && TEST_ARGS=".libs/*Test.so" - -test -z "$srcdir" && srcdir=. - -# libdlclose_noop prevents unloading symbols needed for valgrind output. -export LD_PRELOAD=.libs/libdlclose_noop.so -source $srcdir/run_test DllPlugInTester -c -b $TEST_ARGS diff --git a/cpp/src/tests/run_acl_tests b/cpp/src/tests/run_acl_tests deleted file mode 100755 index 41f41e20e1..0000000000 --- a/cpp/src/tests/run_acl_tests +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the acl tests. $srcdir is set by the Makefile. -source ./test_env.sh -DATA_DIR=`pwd`/data_dir - -trap stop_brokers INT TERM QUIT - -start_brokers() { - ../qpidd --daemon --port 0 --no-module-dir --data-dir $DATA_DIR --load-module $ACL_LIB --acl-file policy.acl --auth no > qpidd.port - LOCAL_PORT=`cat qpidd.port` -} - -stop_brokers() { - $QPIDD_EXEC --no-module-dir -q --port $LOCAL_PORT -} - -test_loading_acl_from_absolute_path(){ - POLICY_FILE=$srcdir/policy.acl - rm -f temp.log - PORT=`../qpidd --daemon --port 0 --no-module-dir --no-data-dir --auth no --load-module $ACL_LIB --acl-file $POLICY_FILE -t --log-to-file temp.log 2>/dev/null` - ACL_FILE=`grep "notice Read ACL file" temp.log | sed 's/^.*Read ACL file //'` - $QPIDD_EXEC --no-module-dir -q --port $PORT - if test "$ACL_FILE" != "\"$POLICY_FILE\""; then - echo "unable to load policy file from an absolute path"; - return 1; - fi - rm temp.log -} - -if test -d ${PYTHON_DIR} ; then - rm -rf $DATA_DIR - mkdir -p $DATA_DIR - cp $srcdir/policy.acl $DATA_DIR - start_brokers - echo "Running acl tests using brokers on ports $LOCAL_PORT" - $QPID_PYTHON_TEST -b localhost:$LOCAL_PORT -m acl || EXITCODE=1 - stop_brokers || EXITCODE=1 - test_loading_acl_from_absolute_path || EXITCODE=1 - rm -rf $DATA_DIR - exit $EXITCODE -fi - diff --git a/cpp/src/tests/run_acl_tests.ps1 b/cpp/src/tests/run_acl_tests.ps1 deleted file mode 100644 index a1848779c7..0000000000 --- a/cpp/src/tests/run_acl_tests.ps1 +++ /dev/null @@ -1,102 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the acl tests. - -$srcdir = Split-Path $myInvocation.InvocationName -$PYTHON_DIR = "$srcdir\..\..\..\python" -if (!(Test-Path $PYTHON_DIR -pathType Container)) { - "Skipping acl tests as python libs not found" - exit 1 -} - -$PYTHON_TEST_DIR = "$srcdir\..\..\..\tests\src\py" -$QMF_LIB = "$srcdir\..\..\..\extras\qmf\src\py" -$env:PYTHONPATH="$PYTHON_DIR;$srcdir;$PYTHON_TEST_DIR;$QMF_LIB" -$Global:BROKER_EXE = "" - -Function start_broker($acl_options) -{ - # Test runs from the tests directory but the broker executable is one level - # up, and most likely in a subdirectory from there based on what build type. - # Look around for it before trying to start it. - . $srcdir\find_prog.ps1 ..\qpidd.exe - if (!(Test-Path $prog)) { - "Cannot locate qpidd.exe" - exit 1 - } - $Global:BROKER_EXE = $prog - if (Test-Path qpidd.port) { - Remove-Item qpidd.port - } - $cmdline = "$prog --auth=no --no-module-dir --port=0 --log-to-file qpidd.log $acl_options | foreach { set-content qpidd.port `$_ }" - $cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline) - . $srcdir\background.ps1 $cmdblock - # Wait for the broker to start - $wait_time = 0 - while (!(Test-Path qpidd.port) -and ($wait_time -lt 10)) { - Start-Sleep 2 - $wait_time += 2 - } - if (!(Test-Path qpidd.port)) { - "Timeout waiting for broker to start" - exit 1 - } - set-item -path env:BROKER_PORT -value (get-content -path qpidd.port -totalcount 1) -} - -Function stop_broker -{ - "Stopping $Global:BROKER_EXE" - Invoke-Expression "$Global:BROKER_EXE --no-module-dir -q --port $env:BROKER_PORT" | Write-Output - Remove-Item qpidd.port -} - -$DATA_DIR = [IO.Directory]::GetCurrentDirectory() + "\data_dir" -Remove-Item $DATA_DIR -recurse -New-Item $DATA_DIR -type directory -Copy-Item $srcdir\policy.acl $DATA_DIR -start_broker("--data-dir $DATA_DIR --acl-file policy.acl") -"Running acl tests using broker on port $env:BROKER_PORT" -Invoke-Expression "python $PYTHON_DIR/qpid-python-test -m acl -b localhost:$env:BROKER_PORT" | Out-Default -$RETCODE=$LASTEXITCODE -stop_broker - -# Now try reading the acl file from an absolute path. -Remove-Item qpidd.log -$policy_full_path = "$srcdir\policy.acl" -start_broker("--no-data-dir --acl-file $policy_full_path") -#test_loading_acl_from_absolute_path(){ -# POLICY_FILE=$srcdir/policy.acl -# rm -f temp.log -# PORT=`../qpidd --daemon --port 0 --no-module-dir --no-data-dir --auth no --load-module $ACL_LIB --acl-file $POLICY_FILE -t --log-to-file temp.log 2>/dev/null` -# ACL_FILE=`grep "notice Read ACL file" temp.log | sed 's/^.*Read ACL file //'` -# $QPIDD_EXEC --no-module-dir -q --port $PORT -# if test "$ACL_FILE" != "\"$POLICY_FILE\""; then -# echo "unable to load policy file from an absolute path"; -# return 1; -# fi -# rm temp.log -#} -# -# test_loading_acl_from_absolute_path || EXITCODE=1 -# rm -rf $DATA_DIR -# exit $EXITCODE -stop_broker -exit $RETCODE diff --git a/cpp/src/tests/run_cli_tests b/cpp/src/tests/run_cli_tests deleted file mode 100755 index ec5c71b646..0000000000 --- a/cpp/src/tests/run_cli_tests +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the cli-utility tests. - -source ./test_env.sh -CLI_DIR=$PYTHON_COMMANDS - -trap stop_brokers INT TERM QUIT - -# helper function to create test.xquery in the current directory, so -# that the python test program can find it. yes, it leaves a turd. -create_test_xquery() { - cat <<EOF > ./test.xquery - let \$w := ./weather - return \$w/station = 'Raleigh-Durham International Airport (KRDU)' - and \$w/temperature_f > 50 - and \$w/temperature_f - \$w/dewpoint > 5 - and \$w/wind_speed_mph > 7 - and \$w/wind_speed_mph < 20 -EOF -} - -start_brokers() { - # if the xml lib is present, use it. if not, disable any tests which - # look like they're xml related. - # if we start supporting xml on windows, it will need something similar - # here - if [ -f ../.libs/xml.so ] ; then - xargs="--load-module ../.libs/xml.so" - if [ ! -f test.xquery ] ; then - create_test_xquery - fi - targs="" - else - echo "Ignoring XML tests" - xargs="" - targs="--ignore=*xml*" - fi - - ../qpidd --daemon --port 0 --no-data-dir --no-module-dir --auth no $xargs > qpidd.port - LOCAL_PORT=`cat qpidd.port` - ../qpidd --daemon --port 0 --no-data-dir --no-module-dir --auth no $xargs > qpidd.port - REMOTE_PORT=`cat qpidd.port` -} - -stop_brokers() { - $QPIDD_EXEC --no-module-dir -q --port $LOCAL_PORT - $QPIDD_EXEC --no-module-dir -q --port $REMOTE_PORT -} - -if test -d ${PYTHON_DIR} ; then - start_brokers - echo "Running CLI tests using brokers on ports $LOCAL_PORT $REMOTE_PORT" - PYTHON_TESTS=${PYTHON_TESTS:-$*} - $QPID_PYTHON_TEST -m cli_tests -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dcli-dir=$CLI_DIR $targs $PYTHON_TESTS $@ - RETCODE=$? - stop_brokers - if test x$RETCODE != x0; then - echo "FAIL CLI tests"; exit 1; - fi -fi - diff --git a/cpp/src/tests/run_cluster_authentication_soak b/cpp/src/tests/run_cluster_authentication_soak deleted file mode 100755 index 7bc406c4ca..0000000000 --- a/cpp/src/tests/run_cluster_authentication_soak +++ /dev/null @@ -1,26 +0,0 @@ -#! /bin/bash -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - - -source ./test_env.sh -source $srcdir/ais_check -source sasl_test_setup.sh - -with_ais_group ./cluster_authentication_soak 500 - diff --git a/cpp/src/tests/run_cluster_authentication_test b/cpp/src/tests/run_cluster_authentication_test deleted file mode 100755 index 647200b869..0000000000 --- a/cpp/src/tests/run_cluster_authentication_test +++ /dev/null @@ -1,26 +0,0 @@ -#! /bin/bash -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - - -source ./test_env.sh -source $srcdir/ais_check -source sasl_test_setup.sh - -with_ais_group ./cluster_authentication_soak - diff --git a/cpp/src/tests/run_cluster_test b/cpp/src/tests/run_cluster_test deleted file mode 100755 index c022eea1fe..0000000000 --- a/cpp/src/tests/run_cluster_test +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -# Run the tests -srcdir=`dirname $0` -. $srcdir/ais_check -with_ais_group $srcdir/run_test ./cluster_test diff --git a/cpp/src/tests/run_cluster_tests b/cpp/src/tests/run_cluster_tests deleted file mode 100755 index e136d3810a..0000000000 --- a/cpp/src/tests/run_cluster_tests +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -source ./test_env.sh -source $srcdir/ais_check - -test -x $QPID_PYTHON_TEST || { echo Skipping test, $QPID_PYTHON_TEST not found; exit 0; } - -# Delete old cluster test data -OUTDIR=${OUTDIR:-brokertest.tmp} -rm -rf $OUTDIR -mkdir -p $OUTDIR - -# Ignore tests requiring a store by default. -CLUSTER_TESTS_IGNORE=${CLUSTER_TESTS_IGNORE:--i cluster_tests.StoreTests.* -I $srcdir/cluster_tests.fail} -CLUSTER_TESTS=${CLUSTER_TESTS:-$*} - -with_ais_group $QPID_PYTHON_TEST -DOUTDIR=$OUTDIR -m cluster_tests $CLUSTER_TESTS_IGNORE $CLUSTER_TESTS || exit 1 -rm -rf $OUTDIR diff --git a/cpp/src/tests/run_failover_soak b/cpp/src/tests/run_failover_soak deleted file mode 100755 index cce8b07a26..0000000000 --- a/cpp/src/tests/run_failover_soak +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -source ./test_env.sh -. $srcdir/ais_check - -host=127.0.0.1 - -unset QPID_NO_MODULE_DIR # failover_soak uses --module-dir, dont want clash -MODULES=${MODULES:-$moduledir} -MESSAGES=${MESSAGES:-500000} -REPORT_FREQUENCY=${REPORT_FREQUENCY:-20000} -VERBOSITY=${VERBOSITY:-0} -DURABILITY=${DURABILITY:-0} -N_QUEUES=${N_QUEUES:-1} -N_BROKERS=${N_BROKERS:-4} - -rm -f soak-*.log -exec ./failover_soak $MODULES ./declare_queues ./replaying_sender ./resuming_receiver $MESSAGES $REPORT_FREQUENCY $VERBOSITY $DURABILITY $N_QUEUES $N_BROKERS - diff --git a/cpp/src/tests/run_federation_tests b/cpp/src/tests/run_federation_tests deleted file mode 100755 index 590f74746e..0000000000 --- a/cpp/src/tests/run_federation_tests +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the federation tests. - -source ./test_env.sh - -trap stop_brokers INT TERM QUIT - -if [ -f ../.libs/xml.so ] ; then - MODULES="--load-module xml" # Load the XML exchange and run XML exchange federation tests - SKIPTESTS="" -else - MODULES="--no-module-dir" - SKIPTESTS="-i *xml" -fi - -start_brokers() { - ../qpidd --daemon --port 0 --no-data-dir $MODULES --auth no > qpidd.port - LOCAL_PORT=`cat qpidd.port` - ../qpidd --daemon --port 0 --no-data-dir $MODULES --auth no > qpidd.port - REMOTE_PORT=`cat qpidd.port` - - ../qpidd --daemon --port 0 --no-data-dir $MODULES --auth no > qpidd.port - REMOTE_B1=`cat qpidd.port` - ../qpidd --daemon --port 0 --no-data-dir $MODULES --auth no > qpidd.port - REMOTE_B2=`cat qpidd.port` -} - -stop_brokers() { - $QPIDD_EXEC $MODULES -q --port $LOCAL_PORT - $QPIDD_EXEC $MODULES -q --port $REMOTE_PORT - $QPIDD_EXEC $MODULES -q --port $REMOTE_B1 - $QPIDD_EXEC $MODULES -q --port $REMOTE_B2 -} - -if test -d ${PYTHON_DIR} ; then - start_brokers - echo "Running federation tests using brokers on ports $LOCAL_PORT $REMOTE_PORT $REMOTE_B1 $REMOTE_B2" - $QPID_PYTHON_TEST -m federation $SKIPTESTS -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dextra-brokers="$REMOTE_B1 $REMOTE_B2" $@ - RETCODE=$? - stop_brokers - if test x$RETCODE != x0; then - echo "FAIL federation tests"; exit 1; - fi -fi diff --git a/cpp/src/tests/run_federation_tests.ps1 b/cpp/src/tests/run_federation_tests.ps1 deleted file mode 100644 index 35353a870f..0000000000 --- a/cpp/src/tests/run_federation_tests.ps1 +++ /dev/null @@ -1,84 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the federation tests. - -$srcdir = Split-Path $myInvocation.InvocationName -$PYTHON_DIR = "$srcdir\..\..\..\python" -if (!(Test-Path $PYTHON_DIR -pathType Container)) { - "Skipping federation tests as python libs not found" - exit 1 -} - -$PYTHON_TEST_DIR = "$srcdir\..\..\..\tests\src\py" -$QMF_LIB = "$srcdir\..\..\..\extras\qmf\src\py" - -# Test runs from the tests directory but the broker executable is one level -# up, and most likely in a subdirectory from there based on what build type. -# Look around for it before trying to start it. -$subs = "Debug","Release","MinSizeRel","RelWithDebInfo" -foreach ($sub in $subs) { - $prog = "..\$sub\qpidd.exe" - if (Test-Path $prog) { - break - } -} -if (!(Test-Path $prog)) { - "Cannot locate qpidd.exe" - exit 1 -} -$cmdline = "$prog --auth=no --no-module-dir --no-data-dir --port=0 --ssl-port=0 --log-to-file qpidd.log $args | foreach { set-content qpidd.port `$_ }" -$cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline) - -function start_brokers { - # Start 2 brokers, saving the port numbers in LOCAL_PORT, REMOTE_PORT. - . $srcdir\background.ps1 $cmdblock - while (!(Test-Path qpidd.port)) { - Start-Sleep 2 - } - set-item -path env:LOCAL_PORT -value (get-content -path qpidd.port -totalcount 1) - Remove-Item qpidd.port - . $srcdir\background.ps1 $cmdblock - while (!(Test-Path qpidd.port)) { - Start-Sleep 2 - } - set-item -path env:REMOTE_PORT -value (get-content -path qpidd.port -totalcount 1) -} - -function stop_brokers { - Invoke-Expression "$prog -q --port $env:LOCAL_PORT" | Out-Default - Invoke-Expression "$prog -q --port $env:REMOTE_PORT" | Out-Default -} - -trap { - &stop_brokers - break -} - -&start_brokers -"Running federation tests using brokers on ports $env:LOCAL_PORT $env:REMOTE_PORT" -$env:PYTHONPATH="$srcdir;$PYTHON_DIR;$PYTHON_TEST_DIR;$env:PYTHONPATH;$QMF_LIB" -$tests = "*" -Invoke-Expression "python $PYTHON_DIR/qpid-python-test -m federation -b localhost:$env:LOCAL_PORT -Dremote-port=$env:REMOTE_PORT $tests" | Out-Default -$RETCODE=$LASTEXITCODE -&stop_brokers -if ($RETCODE -ne 0) { - "FAIL federation tests" - exit 1 -} diff --git a/cpp/src/tests/run_header_test b/cpp/src/tests/run_header_test deleted file mode 100755 index 34008132cc..0000000000 --- a/cpp/src/tests/run_header_test +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Simple test of encode/decode of a double in application headers -# TODO: this should be expanded to cover a wider set of types and go -# in both directions - -srcdir=`dirname $0` -source ./test_env.sh - -test -f qpidd.port && QPID_PORT=`cat qpidd.port` - -if test -d ${PYTHON_DIR} ; then - ./header_test -p $QPID_PORT - $srcdir/header_test.py "localhost" $QPID_PORT -else - echo "Skipping header test as python libs not found" -fi - diff --git a/cpp/src/tests/run_header_test.ps1 b/cpp/src/tests/run_header_test.ps1 deleted file mode 100644 index 7d3e43a30f..0000000000 --- a/cpp/src/tests/run_header_test.ps1 +++ /dev/null @@ -1,47 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Simple test of encode/decode of a double in application headers -# TODO: this should be expanded to cover a wider set of types and go -# in both directions - -$srcdir = Split-Path $myInvocation.InvocationName -$PYTHON_DIR = "$srcdir\..\..\..\python" -if (!(Test-Path $PYTHON_DIR -pathType Container)) { - "Skipping header test as python libs not found" - exit 0 -} - -if (Test-Path qpidd.port) { - set-item -path env:QPID_PORT -value (get-content -path qpidd.port -totalcount 1) -} - -# Test runs from the tests directory but the test executables are in a -# subdirectory based on the build type. Look around for it before trying -# to start it. -. $srcdir\find_prog.ps1 .\header_test.exe -if (!(Test-Path $prog)) { - "Cannot locate header_test.exe" - exit 1 -} - -Invoke-Expression "$prog -p $env:QPID_PORT" | Write-Output -$env:PYTHONPATH="$PYTHON_DIR;$env:PYTHONPATH" -Invoke-Expression "python $srcdir/header_test.py localhost $env:QPID_PORT" | Write-Output -exit $LASTEXITCODE diff --git a/cpp/src/tests/run_headers_federation_tests b/cpp/src/tests/run_headers_federation_tests deleted file mode 100644 index a4584e6884..0000000000 --- a/cpp/src/tests/run_headers_federation_tests +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the federation tests for the Headers Exchange. - -source ./test_env.sh - -trap stop_brokers INT TERM QUIT - -start_brokers() { - ../qpidd --daemon --port 0 --no-data-dir --no-module-dir --auth no > qpidd.port - LOCAL_PORT=`cat qpidd.port` - ../qpidd --daemon --port 0 --no-data-dir --no-module-dir --auth no > qpidd.port - REMOTE_PORT=`cat qpidd.port` -} - -stop_brokers() { - $QPIDD_EXEC --no-module-dir -q --port $LOCAL_PORT - $QPIDD_EXEC --no-module-dir -q --port $REMOTE_PORT -} - -if test -d ${PYTHON_DIR} ; then - start_brokers - echo "Running HeadersExchange federation tests using brokers on ports $LOCAL_PORT $REMOTE_PORT" - $QPID_PYTHON_TEST -m headers_federation -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT $@ - RETCODE=$? - stop_brokers - if test x$RETCODE != x0; then - echo "FAIL federation tests"; exit 1; - fi -fi diff --git a/cpp/src/tests/run_long_cluster_tests b/cpp/src/tests/run_long_cluster_tests deleted file mode 100755 index 5dce0be585..0000000000 --- a/cpp/src/tests/run_long_cluster_tests +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -srcdir=`dirname $0` -$srcdir/run_cluster_tests 'cluster_tests.LongTests.*' -DDURATION=4 - diff --git a/cpp/src/tests/run_perftest b/cpp/src/tests/run_perftest deleted file mode 100755 index 5ad7c1ff4f..0000000000 --- a/cpp/src/tests/run_perftest +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Args: count [qpid-perftest options...] -# Run a qpid-perftest with count multiplied. -# -MULTIPLIER=3 -COUNT=`expr $1 \* $MULTIPLIER` -shift -exec `dirname $0`/run_test ./qpid-perftest --summary --count $COUNT "$@" diff --git a/cpp/src/tests/run_queue_flow_limit_tests b/cpp/src/tests/run_queue_flow_limit_tests deleted file mode 100755 index f921cf5e7e..0000000000 --- a/cpp/src/tests/run_queue_flow_limit_tests +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run tests against Queue producer flow control. - -source ./test_env.sh -test -d $PYTHON_DIR || { echo "Skipping queue flow control tests, no python dir."; exit 0; } - -LOG_FILE=queue_flow_limit_test.log -PORT="" - -trap stop_broker INT TERM QUIT - -error() { - echo $* - exit 1; -} - -start_broker() { - # Note: if you change the DEFAULT_THRESHOLDS, you will need to update queue_flow_limit_tests.py - DEFAULT_THRESHOLDS="--default-flow-stop-threshold=80 --default-flow-resume-threshold=70" - rm -rf $LOG_FILE - PORT=$($QPIDD_EXEC $DEFAULT_THRESHOLDS --auth=no --no-module-dir --daemon --port=0 -t --log-to-file $LOG_FILE) || error "Could not start broker" -} - -stop_broker() { - test -n "$PORT" && $QPIDD_EXEC --no-module-dir --quit --port $PORT -} - -start_broker -echo "Running Queue flow limit tests using broker on port $PORT" -$QPID_PYTHON_TEST -m queue_flow_limit_tests $SKIPTESTS -b localhost:$PORT $@ -RETCODE=$? -stop_broker -if test x$RETCODE != x0; then - echo "FAIL queue flow limit tests"; exit 1; -fi -rm -rf $LOG_FILE - diff --git a/cpp/src/tests/run_ring_queue_test b/cpp/src/tests/run_ring_queue_test deleted file mode 100755 index 7ca870841e..0000000000 --- a/cpp/src/tests/run_ring_queue_test +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -#script to run a sequence of ring queue tests via make - -#setup path to find qpid-config and sender/receiver test progs -source ./test_env.sh - -export PATH=$PWD:$srcdir:$PYTHON_COMMANDS:$PATH - -#set port to connect to via env var -test -s qpidd.port && QPID_PORT=`cat qpidd.port` -export QPID_PORT - -ring_queue_test -c -s 4 -r 4 -ring_queue_test -s 4 -r 0 -ring_queue_test -s 1 -r 1 - - diff --git a/cpp/src/tests/run_store_tests.ps1 b/cpp/src/tests/run_store_tests.ps1 deleted file mode 100644 index 76b46737f0..0000000000 --- a/cpp/src/tests/run_store_tests.ps1 +++ /dev/null @@ -1,133 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the store tests. -# There are two sets of tests: -# 1. A subset of the normal broker python tests, dtx and persistence, but -# run again with the desired store loaded. -# 2. store.py, which tests recovering things across broker restarts. - -$test_store = $args[0] -if ($test_store -ne "MSSQL" -and $test_store -ne "MSSQL-CLFS") { - "Invalid store test type $test_store - must be MSSQL or MSSQL-CLFS" - exit 1 -} - -$srcdir = Split-Path $myInvocation.InvocationName -$PYTHON_DIR = "$srcdir\..\..\..\python" -if (!(Test-Path $PYTHON_DIR -pathType Container)) { - "Skipping store tests as python libs not found" - exit 1 -} - -$QMF_LIB = "$srcdir\..\..\..\extras\qmf\src\py" - -# Test runs from the tests directory but the broker executable is one level -# up, and most likely in a subdirectory from there based on what build type. -# Look around for it before trying to start it. -$subs = "Debug","Release","MinSizeRel","RelWithDebInfo" -foreach ($sub in $subs) { - $prog = "..\$sub\qpidd.exe" - if (Test-Path $prog) { - break - } -} -if (!(Test-Path $prog)) { - "Cannot locate qpidd.exe" - exit 1 -} - -# The store to test is the same build type as the broker. -$store_dir = "..\qpid\store\$sub" -if (!([string]::Compare($sub, "Debug", $True))) { - $suffix = "d" -} - -$stamp = Get-Date -format %dMMMyyyy_HHmmss -$env:STORE_LIB="$store_dir\store$suffix.dll" -if ($test_store -eq "MSSQL") { - $test_store_module="$store_dir\mssql_store$suffix.dll" - $env:STORE_SQL_LIB=$test_store_module - $env:STORE_CATALOG="store_recovery_sql_test_$stamp" - $cat1="store_sql_test_$stamp" - $out = "sql_store_test_$stamp" -} -else { - $test_store_module="$store_dir\msclfs_store$suffix.dll" - $env:STORE_SQL_CLFS_LIB=$test_store_module - $env:STORE_CATALOG="store_recovery_clfs_test_$stamp" - $cat1="store_clfs_test_$stamp" - $out = "clfs_store_test_$stamp" -} - -$FAILCODE = 0 - -# Test 1... re-run some of the regular python broker tests against a broker -# with the store module loaded. -$cmdline = "$prog --auth=no --port=0 --log-to-file qpidd-store.log --no-module-dir --load-module $env:STORE_LIB --load-module $test_store_module --catalog $cat1 | foreach { set-content qpidd-store.port `$_ }" -$cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline) -. $srcdir\background.ps1 $cmdblock - -$wait_time = 0 -while (!(Test-Path qpidd-store.port) -and ($wait_time -lt 90)) { - Start-Sleep 2 - $wait_time += 2 -} -if (!(Test-Path qpidd-store.port)) { - "Time out waiting for broker to start" - exit 1 -} -set-item -path env:QPID_PORT -value (get-content -path qpidd-store.port -totalcount 1) -Remove-Item qpidd-store.port - -$PYTHON_TEST_DIR = "$srcdir\..\..\..\tests\src\py\qpid_tests\broker_0_10" -$env:PYTHONPATH="$PYTHON_DIR;$PYTHON_TEST_DIR;$env:PYTHONPATH;$QMF_LIB" -python $PYTHON_DIR/qpid-python-test -m dtx -m persistence -b localhost:$env:QPID_PORT $fails $tests -$RETCODE=$LASTEXITCODE -if ($RETCODE -ne 0) { - $FAILCODE = 1 -} - -# Piping the output makes the script wait for qpidd to finish. -Invoke-Expression "$prog --quit --port $env:QPID_PORT" | Write-Output - - -# Test 2... store.py starts/stops/restarts its own brokers - -$tests = "*" -$env:PYTHONPATH="$PYTHON_DIR;$srcdir" -$env:QPIDD_EXEC="$prog" -$env:STORE_LIB="$store_dir\store$suffix.dll" -if ($test_store -eq "MSSQL") { - $env:STORE_SQL_LIB="$store_dir\mssql_store$suffix.dll" - $env:STORE_CATALOG="store_recovery_sql_test_$stamp" - $out = "sql_store_test_$stamp" -} -else { - $env:STORE_SQL_CLFS_LIB="$store_dir\msclfs_store$suffix.dll" - $env:STORE_CATALOG="store_recovery_clfs_test_$stamp" - $out = "clfs_store_test_$stamp" -} -Invoke-Expression "python $PYTHON_DIR/qpid-python-test -m store -D OUTDIR=$out $tests" | Out-Default -$RETCODE=$LASTEXITCODE -if ($RETCODE -ne 0) { - "FAIL $test_store store tests" - $FAILCODE = 1 -} -exit $FAILCODE diff --git a/cpp/src/tests/run_test b/cpp/src/tests/run_test deleted file mode 100755 index 6ec1fd892b..0000000000 --- a/cpp/src/tests/run_test +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# -# Set up environment and run a test executable or script. -# -# Output nothing if test passes, show the output if it fails and -# leave output in <test>.log for examination. -# -# If qpidd.port exists and is not empty run test with QPID_PORT=`cat qpidd.port` -# -# If $VALGRIND if is set run under valgrind. If there are valgrind -# erros show valgrind output, also leave it in <test>.valgrind for -# examination. -# - -srcdir=`dirname $0` -source ./test_env.sh -source $srcdir/vg_check - -# Export variables from makefile. -export srcdir - -# Set QPID_PORT if qpidd.port exists. -test -s qpidd.port && QPID_PORT=`cat qpidd.port` -export QPID_PORT - -# Avoid silly libtool error messages if these are not defined -test -z "$LC_ALL" && LC_ALL= -test -z "$LC_CTYPE" && LC_CTYPE= -test -z "$LC_COLLATE" && LC_COLLATE= -test -z "$LC_MESSAGES" && LC_MESSAGES= -export LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES - -VG_LOG="`basename $1`.vglog" -rm -f $VG_LOG* - -# Use VALGRIND_OPTS="--gen-suppressions=all" to generated suppressions -VALGRIND_OPTS="$VALGRIND_OPTS ---leak-check=full ---demangle=yes ---suppressions=$srcdir/.valgrind.supp ---num-callers=25 ---log-file=$VG_LOG -- -" -ERROR=0 -if grep -l "^# Generated by .*libtool" "$1" >/dev/null 2>&1; then - # This is a libtool "executable". Valgrind it if VALGRIND specified. - test -n "$VALGRIND" && VALGRIND="$VALGRIND $VALGRIND_OPTS" - # Hide output unless there's an error. - $LIBTOOL --mode=execute $VALGRIND "$@" 2>&1 || ERROR=1 - test -n "$VALGRIND" && { vg_check $VG_LOG* || ERROR=1 ; } -elif file $1 | grep -q text; then - # This is a non-libtool shell script, just execute it. - exec "$@" -else - # This is a real executable, valgrind it. - test -n "$VALGRIND" && VALGRIND="$VALGRIND $VALGRIND_OPTS" - # Hide output unless there's an error. - $VALGRIND "$@" 2>&1 || ERROR=1 - test -n "$VALGRIND" && { vg_check $VG_LOG* || ERROR=1 ; } -fi - -exit $ERROR - diff --git a/cpp/src/tests/run_test.ps1 b/cpp/src/tests/run_test.ps1 deleted file mode 100644 index ca990bc057..0000000000 --- a/cpp/src/tests/run_test.ps1 +++ /dev/null @@ -1,69 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -$srcdir = Split-Path $myInvocation.InvocationName - -# Set up environment and run a test executable or script. -$env:QPID_DATA_DIR = "" -$env:BOOST_TEST_SHOW_PROGRESS = "yes" - -# The test exe is probably not in the current binary dir - it's usually -# placed in a subdirectory based on the configuration built in Visual Studio. -# So check around to see where it is - when located, set the QPID_LIB_DIR -# and PATH to look in the corresponding configuration off the src directory, -# one level up. -$prog = $args[0] -$is_script = $prog -match ".ps1$" -if (!$is_script) { - . $srcdir\find_prog.ps1 $prog - $args[0] = $prog - $env:QPID_LIB_DIR = "..\$sub" - $env:PATH += ";$dir\$sub;..\$sub" -} - -# If qpidd.port exists and is not empty run test with QPID_PORT set. -if (Test-Path qpidd.port) { - set-item -path env:QPID_PORT -value (get-content -path qpidd.port -totalcount 1) -} - -$si = new-object System.Diagnostics.ProcessStartInfo -$si.WorkingDirectory = $pwd -$si.UseShellExecute = $false -$si.CreateNoWindow = $true -$si.RedirectStandardOutput = $true -if ($is_script) { - $si.FileName = (get-command powershell.exe).Definition - $si.Arguments = $args -} -else { - $si.FileName = $args[0] - if ($args.length -gt 1) { - $si.Arguments = $args[1..($args.length-1)] - } -} -$p = [System.Diagnostics.Process]::Start($si) -$line = "" -while (($line = $p.StandardOutput.ReadLine()) -ne $null) { - $line -} -# ReadToEnd() works, but doesn't show any output until the program exits. -#$p.StandardOutput.ReadToEnd() -$p.WaitForExit() -$status = $p.ExitCode -exit $status diff --git a/cpp/src/tests/sasl.mk b/cpp/src/tests/sasl.mk deleted file mode 100644 index 20eaa7c7a5..0000000000 --- a/cpp/src/tests/sasl.mk +++ /dev/null @@ -1,49 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Test that are only relevant if SASL is enabled. -if HAVE_SASL - -check_PROGRAMS+=cluster_authentication_soak -cluster_authentication_soak_INCLUDES=$(PUBLIC_INCLUDES) -cluster_authentication_soak_SOURCES=cluster_authentication_soak.cpp ForkedBroker.h ForkedBroker.cpp -cluster_authentication_soak_LDADD=$(lib_client) $(lib_broker) - -# Note: sasl_version is not a test -- it is a tool used by tests. -check_PROGRAMS+=sasl_version -sasl_version_SOURCES=sasl_version.cpp -sasl_version_LDADD=$(lib_client) - -TESTS += run_cluster_authentication_test sasl_fed sasl_fed_ex_dynamic sasl_fed_ex_link sasl_fed_ex_queue sasl_fed_ex_route sasl_fed_ex_route_cluster sasl_fed_ex_link_cluster sasl_fed_ex_queue_cluster sasl_fed_ex_dynamic_cluster -LONG_TESTS += run_cluster_authentication_soak -EXTRA_DIST += run_cluster_authentication_test \ - sasl_fed \ - sasl_fed_ex \ - run_cluster_authentication_soak \ - sasl_fed_ex_dynamic \ - sasl_fed_ex_link \ - sasl_fed_ex_queue \ - sasl_fed_ex_route \ - sasl_fed_ex_dynamic_cluster \ - sasl_fed_ex_link_cluster \ - sasl_fed_ex_queue_cluster \ - sasl_fed_ex_route_cluster - - -endif # HAVE_SASL diff --git a/cpp/src/tests/sasl_fed b/cpp/src/tests/sasl_fed deleted file mode 100755 index 884c44177c..0000000000 --- a/cpp/src/tests/sasl_fed +++ /dev/null @@ -1,166 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -source ./test_env.sh - -# This minimum value corresponds to sasl version 2.1.22 -minimum_sasl_version=131350 - -sasl_version=`$QPID_TEST_EXEC_DIR/sasl_version` - -# This test is necessary becasue this sasl version is the first one that permits -# redirection of the sasl config file path. -if [ "$sasl_version" -lt "$minimum_sasl_version" ]; then - echo "sasl_fed: must have sasl version 2.1.22 or greater. ( Integer value: $minimum_sasl_version ) Version is: $sasl_version" - exit 0 -fi - -# In a distribution, the python tools will be absent. -if [ ! -f $QPID_CONFIG_EXEC ] || [ ! -f $QPID_ROUTE_EXEC ] ; then - echo "python tools absent - skipping sasl_fed." - exit 0 -fi - - -sasl_config_file=$builddir/sasl_config - -my_random_number=$RANDOM -tmp_root=/tmp/sasl_fed_$my_random_number -mkdir -p $tmp_root - - -#-------------------------------------------------- -#echo " Starting broker 1" -#-------------------------------------------------- -$QPIDD_EXEC \ - -p 0 \ - --data-dir $tmp_root/data_1 \ - --auth=yes \ - --mgmt-enable=yes \ - --log-enable info+ \ - --log-source yes \ - --log-to-file $tmp_root/qpidd_1.log \ - --sasl-config=$sasl_config_file \ - -d > $tmp_root/broker_1_port - -broker_1_port=`cat $tmp_root/broker_1_port` - - -#-------------------------------------------------- -#echo " Starting broker 2" -#-------------------------------------------------- -$QPIDD_EXEC \ - -p 0 \ - --data-dir $tmp_root/data_2 \ - --auth=yes \ - --mgmt-enable=yes \ - --log-enable info+ \ - --log-source yes \ - --log-to-file $tmp_root/qpidd_2.log \ - --sasl-config=$sasl_config_file \ - -d > $tmp_root/broker_2_port - -broker_2_port=`cat $tmp_root/broker_2_port` - -sleep 2 - -# I am not randomizing these names, because the test creates its own brokers. -QUEUE_NAME=sasl_fed_queue -ROUTING_KEY=sasl_fed_queue -EXCHANGE_NAME=sasl_fedex - -#-------------------------------------------------- -#echo " add exchanges" -#-------------------------------------------------- -$QPID_CONFIG_EXEC -a localhost:$broker_1_port add exchange direct $EXCHANGE_NAME -$QPID_CONFIG_EXEC -a localhost:$broker_2_port add exchange direct $EXCHANGE_NAME - - -#-------------------------------------------------- -#echo " add queues" -#-------------------------------------------------- -$QPID_CONFIG_EXEC -a localhost:$broker_1_port add queue $QUEUE_NAME -$QPID_CONFIG_EXEC -a localhost:$broker_2_port add queue $QUEUE_NAME - -sleep 5 - -#-------------------------------------------------- -#echo " create bindings" -#-------------------------------------------------- -$QPID_CONFIG_EXEC -a localhost:$broker_1_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY -$QPID_CONFIG_EXEC -a localhost:$broker_2_port bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY - -sleep 5 - - -#-------------------------------------------------- -#echo " qpid-route route add" -#-------------------------------------------------- -$QPID_ROUTE_EXEC route add zag/zag@localhost:$broker_2_port zag/zag@localhost:$broker_1_port $EXCHANGE_NAME $ROUTING_KEY "" "" DIGEST-MD5 - -sleep 5 - - -n_messages=100 -#-------------------------------------------------- -#echo " Sending 100 messages to $broker_1_port " -#-------------------------------------------------- -$builddir/datagen --count $n_messages | $SENDER_EXEC --mechanism DIGEST-MD5 --username zag --password zag --exchange $EXCHANGE_NAME --routing-key $ROUTING_KEY --port $broker_1_port - -sleep 5 - -#-------------------------------------------------- -#echo " Examine Broker $broker_1_port" -#-------------------------------------------------- -broker_1_message_count=`$PYTHON_COMMANDS/qpid-stat -q localhost:$broker_1_port | grep sasl_fed_queue | awk '{print $2}'` -#echo " " - -#-------------------------------------------------- -#echo " Examine Broker $broker_2_port" -#-------------------------------------------------- -broker_2_message_count=`$PYTHON_COMMANDS/qpid-stat -q localhost:$broker_2_port | grep sasl_fed_queue | awk '{print $2}'` -#echo " " - -#-------------------------------------------------- -#echo " Asking brokers to quit." -#-------------------------------------------------- -$QPIDD_EXEC --port $broker_1_port --quit -$QPIDD_EXEC --port $broker_2_port --quit - - -#-------------------------------------------------- -#echo "Removing temporary directory $tmp_root" -#-------------------------------------------------- -rm -rf $tmp_root - -if [ "$broker_2_message_count" -eq "$n_messages" ]; then - # echo "good: |$broker_2_message_count| == |$n_messages|" - exit 0 -else - # echo "not ideal: |$broker_1_message_count| != |$n_messages|" - exit 1 -fi - - - - - - diff --git a/cpp/src/tests/sasl_fed_ex b/cpp/src/tests/sasl_fed_ex deleted file mode 100755 index 716a806874..0000000000 --- a/cpp/src/tests/sasl_fed_ex +++ /dev/null @@ -1,361 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -#=============================================================================== -# These tests create federated links between two brokers using SASL security. -# The SASL mechanism used is EXTERNAL, which is satisfied by SSL -# transport-layer security. -#=============================================================================== - -source ./test_env.sh - -script_name=`basename $0` - -if [ $# -lt 1 ] || [ $# -gt 2 ] -then - echo - # These are the four different ways of creating links ( or routes+links ) - # that the qpid-route command provides. - echo "Usage: ${script_name} dynamic|link|queue|route [cluster]" - echo - exit 1 -fi - -# Has the user told us to do clustering ? ----------- -clustering_flag= -if [ $# -eq "2" ] && [ "$2" == "cluster" ]; then - clustering_flag=true -fi - -qpid_route_method=$1 - -# Debugging print. -------------------------- -debug= -function print { - if [ "$debug" ]; then - echo "${script_name}: $1" - fi -} - -print "=========== start sasl_fed_ex $* ============" - - - -# This minimum value corresponds to sasl version 2.1.22 -minimum_sasl_version=131350 - -sasl_version=`$QPID_TEST_EXEC_DIR/sasl_version` - -# This test is necessary because this sasl version is the first one that permits -# redirection of the sasl config file path. -if [ "$sasl_version" -lt "$minimum_sasl_version" ]; then - echo "sasl_fed: must have sasl version 2.1.22 or greater. ( Integer value: $minimum_sasl_version ) Version is: $sasl_version" - exit 0 -fi - -# In a distribution, the python tools will be absent. -if [ ! -f $QPID_CONFIG_EXEC ] || [ ! -f $QPID_ROUTE_EXEC ] ; then - echo "python tools absent - skipping sasl_fed_ex." - exit 0 -fi - -CERT_DIR=`pwd`/test_cert_db -CERT_PW_FILE=`pwd`/cert.password -TEST_HOSTNAME=127.0.0.1 - -create_certs() { - #create certificate and key databases with single, simple, self-signed certificate in it - mkdir ${CERT_DIR} - certutil -N -d ${CERT_DIR} -f ${CERT_PW_FILE} - certutil -S -d ${CERT_DIR} -n ${TEST_HOSTNAME} -s "CN=${TEST_HOSTNAME}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil 2> /dev/null -} - -delete_certs() { - if [[ -e ${CERT_DIR} ]] ; then - print "removing cert dir ${CERT_DIR}" - rm -rf ${CERT_DIR} - fi -} - - -CERTUTIL=$(type -p certutil) -if [[ !(-x $CERTUTIL) ]] ; then - echo "No certutil, skipping ssl test"; - exit 0; -fi - -delete_certs -create_certs 2> /dev/null -if [ ! $? ]; then - error "Could not create test certificate" - exit 1 -fi - -sasl_config_dir=$builddir/sasl_config - -tmp_root=${builddir}/sasl_fed_ex_temp -print "results dir is ${tmp_root}" -rm -rf ${tmp_root} -mkdir -p $tmp_root - -SRC_SSL_PORT=6667 -DST_SSL_PORT=6666 - -SRC_SSL_PORT_2=6668 -DST_SSL_PORT_2=6669 - -SRC_TCP_PORT=5801 -DST_TCP_PORT=5807 - -SRC_TCP_PORT_2=5802 -DST_TCP_PORT_2=5803 - -CLUSTER_NAME_SUFFIX=`hostname | tr '.' ' ' | awk '{print $1}'` -CLUSTER_1_NAME=sasl_fed_ex_cluster_1_${CLUSTER_NAME_SUFFIX} -CLUSTER_2_NAME=sasl_fed_ex_cluster_2_${CLUSTER_NAME_SUFFIX} - -print "CLUSTER_1_NAME == ${CLUSTER_1_NAME}" -print "CLUSTER_2_NAME == ${CLUSTER_2_NAME}" - -SSL_LIB=${moduledir}/ssl.so -CLUSTER_LIB=${moduledir}/cluster.so - -export QPID_SSL_CERT_NAME=${TEST_HOSTNAME} - -export QPID_NO_MODULE_DIR=1 -export QPID_LOAD_MODULE=$SSLCONNECTOR_LIB -export QPID_SSL_CERT_DB=${CERT_DIR} -export QPID_SSL_CERT_PASSWORD_FILE=${CERT_PW_FILE} -export QPID_SSL_CERT_NAME=${TEST_HOSTNAME} - - - -####################################### -# Understanding this Plumbing -####################################### -# 1. when you establish the route with qpid-route, -# here is the best termiology to use: -# -# qpid-route route add DST SRC -# -# 2. DST will connect to SRC through the ssl port of SRC. -# -# 3. sender client connects to the tcp port of SRC. -# -# 4. sender specifies mechanism ANONYMOUS. -# -# 5. DST pulls messages off the temp queue on SRC to itself. -# - -COMMON_BROKER_OPTIONS=" \ - --ssl-sasl-no-dict \ - --sasl-config=$sasl_config_dir \ - --ssl-require-client-authentication \ - --auth yes \ - --ssl-cert-db $CERT_DIR \ - --ssl-cert-password-file $CERT_PW_FILE \ - --ssl-cert-name $TEST_HOSTNAME \ - --no-data-dir \ - --no-module-dir \ - --load-module ${SSL_LIB} \ - --mgmt-enable=yes \ - --log-enable info+ \ - --log-source yes \ - --daemon " - - -function start_brokers { - if [ $1 ]; then - # clustered ---------------------------------------- - print "Starting SRC cluster" - - print " src broker 1" - $QPIDD_EXEC \ - --port=${SRC_TCP_PORT} \ - --ssl-port ${SRC_SSL_PORT} \ - ${COMMON_BROKER_OPTIONS} \ - --load-module ${CLUSTER_LIB} \ - --cluster-name ${CLUSTER_1_NAME} \ - --log-to-file $tmp_root/qpidd_src.log 2> /dev/null - - broker_ports[0]=${SRC_TCP_PORT} - - print " src broker 2" - $QPIDD_EXEC \ - --port=${SRC_TCP_PORT_2} \ - --ssl-port ${SRC_SSL_PORT_2} \ - ${COMMON_BROKER_OPTIONS} \ - --load-module ${CLUSTER_LIB} \ - --cluster-name ${CLUSTER_1_NAME} \ - --log-to-file $tmp_root/qpidd_src_2.log 2> /dev/null - - broker_ports[1]=${SRC_TCP_PORT_2} - - - print "Starting DST cluster" - - print " dst broker 1" - $QPIDD_EXEC \ - --port=${DST_TCP_PORT} \ - --ssl-port ${DST_SSL_PORT} \ - ${COMMON_BROKER_OPTIONS} \ - --load-module ${CLUSTER_LIB} \ - --cluster-name ${CLUSTER_2_NAME} \ - --log-to-file $tmp_root/qpidd_dst.log 2> /dev/null - - broker_ports[2]=${DST_TCP_PORT} - - print " dst broker 2" - $QPIDD_EXEC \ - --port=${DST_TCP_PORT_2} \ - --ssl-port ${DST_SSL_PORT_2} \ - ${COMMON_BROKER_OPTIONS} \ - --load-module ${CLUSTER_LIB} \ - --cluster-name ${CLUSTER_2_NAME} \ - --log-to-file $tmp_root/qpidd_dst_2.log 2> /dev/null - - broker_ports[3]=${DST_TCP_PORT_2} - - else - # vanilla brokers -------------------------------- - print "Starting SRC broker" - $QPIDD_EXEC \ - --port=${SRC_TCP_PORT} \ - --ssl-port ${SRC_SSL_PORT} \ - ${COMMON_BROKER_OPTIONS} \ - --log-to-file $tmp_root/qpidd_src.log 2> /dev/null - - broker_ports[0]=${SRC_TCP_PORT} - - print "Starting DST broker" - $QPIDD_EXEC \ - --port=${DST_TCP_PORT} \ - --ssl-port ${DST_SSL_PORT} \ - ${COMMON_BROKER_OPTIONS} \ - --log-to-file $tmp_root/qpidd_dst.log 2> /dev/null - - broker_ports[1]=${DST_TCP_PORT} - fi -} - - -function halt_brokers { - n_brokers=${#broker_ports[@]} - print "Halting ${n_brokers} brokers." - for i in $(seq 0 $((${n_brokers} - 1))) - do - halt_port=${broker_ports[$i]} - print "Halting broker $i on port ${halt_port}" - $QPIDD_EXEC --port ${halt_port} --quit - done - -} - - -start_brokers $clustering_flag - - -# I am not randomizing these names, because this test creates its own brokers. -QUEUE_NAME=sasl_fed_queue -ROUTING_KEY=sasl_fed_queue -EXCHANGE_NAME=sasl_fedex - - -print "add exchanges" -$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} add exchange direct $EXCHANGE_NAME -$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} add exchange direct $EXCHANGE_NAME - - -print "add queues" -$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} add queue $QUEUE_NAME -$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} add queue $QUEUE_NAME - - -print "create bindings" -$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY -$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY - - -# -# NOTE: The SRC broker *must* be referred to as $TEST_HOSTNAME, and not as "localhost". -# It must be referred to by the exact string given as the Common Name (CN) in the cert, -# which was created in the function create_certs, above. - - - -#---------------------------------------------------------------- -# Use qpid-route to create the link, or the link+route, depending -# on which of its several methods was requested. -#---------------------------------------------------------------- -if [ ${qpid_route_method} == "dynamic" ]; then - print "dynamic add" - $QPID_ROUTE_EXEC -t ssl dynamic add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME "" "" EXTERNAL -elif [ ${qpid_route_method} == "link" ]; then - print "link add" - $QPID_ROUTE_EXEC -t ssl link add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} EXTERNAL -elif [ ${qpid_route_method} == "queue" ]; then - print "queue add" - $QPID_ROUTE_EXEC -t ssl queue add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME $ROUTING_KEY EXTERNAL -elif [ ${qpid_route_method} == "route" ]; then - print "route add" - $QPID_ROUTE_EXEC -t ssl route add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME $ROUTING_KEY "" "" EXTERNAL -else - echo "unknown method: |${qpid_route_method}|" - echo " choices are: dynamic|link|queue|route " - halt_brokers - exit 1 -fi - - -# I don't know how to avoid this sleep yet. It has to come after route-creation -# to avoid false negatives. -sleep 5 - -# This should work the same whether or not we are running a clustered test. -# In the case of clustered tests, the status is not printed by qpid_route. -# So in either case, I will look only at the transport field, which should be "ssl". -print "check the link" -link_status=$($QPID_ROUTE_EXEC link list localhost:${DST_TCP_PORT} | tail -1 | awk '{print $3}') - -halt_brokers - -sleep 1 - -if [ ! ${link_status} ]; then - print "link_status is empty" - print "result: fail" - exit 2 -fi - -if [ ${link_status} == "ssl" ]; then - print "result: good" - # Only remove the tmp_root on success, to permit debugging. - print "Removing temporary directory $tmp_root" - rm -rf $tmp_root - exit 0 -fi - -print "link_status has a bad value: ${link_status}" -print "result: fail" -exit 3 - - - diff --git a/cpp/src/tests/sasl_fed_ex_dynamic b/cpp/src/tests/sasl_fed_ex_dynamic deleted file mode 100755 index c20b8d69a0..0000000000 --- a/cpp/src/tests/sasl_fed_ex_dynamic +++ /dev/null @@ -1,27 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -source ./test_env.sh - -${srcdir}/sasl_fed_ex dynamic - - diff --git a/cpp/src/tests/sasl_fed_ex_dynamic_cluster b/cpp/src/tests/sasl_fed_ex_dynamic_cluster deleted file mode 100755 index b0cceccecb..0000000000 --- a/cpp/src/tests/sasl_fed_ex_dynamic_cluster +++ /dev/null @@ -1,28 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -source ./test_env.sh -source $srcdir/ais_check - -with_ais_group ${srcdir}/sasl_fed_ex dynamic cluster - - diff --git a/cpp/src/tests/sasl_fed_ex_link b/cpp/src/tests/sasl_fed_ex_link deleted file mode 100755 index 7b232d4874..0000000000 --- a/cpp/src/tests/sasl_fed_ex_link +++ /dev/null @@ -1,27 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -source ./test_env.sh - -${srcdir}/sasl_fed_ex link - - diff --git a/cpp/src/tests/sasl_fed_ex_link_cluster b/cpp/src/tests/sasl_fed_ex_link_cluster deleted file mode 100755 index 4139300b12..0000000000 --- a/cpp/src/tests/sasl_fed_ex_link_cluster +++ /dev/null @@ -1,28 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -source ./test_env.sh -source $srcdir/ais_check - -with_ais_group ${srcdir}/sasl_fed_ex link cluster - - diff --git a/cpp/src/tests/sasl_fed_ex_queue b/cpp/src/tests/sasl_fed_ex_queue deleted file mode 100755 index be0c10cf63..0000000000 --- a/cpp/src/tests/sasl_fed_ex_queue +++ /dev/null @@ -1,27 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -source ./test_env.sh - -${srcdir}/sasl_fed_ex queue - - diff --git a/cpp/src/tests/sasl_fed_ex_queue_cluster b/cpp/src/tests/sasl_fed_ex_queue_cluster deleted file mode 100755 index f251420e08..0000000000 --- a/cpp/src/tests/sasl_fed_ex_queue_cluster +++ /dev/null @@ -1,28 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -source ./test_env.sh -source ${srcdir}/ais_check - -with_ais_group ${srcdir}/sasl_fed_ex queue cluster - - diff --git a/cpp/src/tests/sasl_fed_ex_route b/cpp/src/tests/sasl_fed_ex_route deleted file mode 100755 index dd5c4f3cac..0000000000 --- a/cpp/src/tests/sasl_fed_ex_route +++ /dev/null @@ -1,27 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -source ./test_env.sh - -${srcdir}/sasl_fed_ex route - - diff --git a/cpp/src/tests/sasl_fed_ex_route_cluster b/cpp/src/tests/sasl_fed_ex_route_cluster deleted file mode 100755 index a5d1542def..0000000000 --- a/cpp/src/tests/sasl_fed_ex_route_cluster +++ /dev/null @@ -1,28 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -source ./test_env.sh -source ${srcdir}/ais_check - -with_ais_group ${srcdir}/sasl_fed_ex route cluster - - diff --git a/cpp/src/tests/sasl_test_setup.sh b/cpp/src/tests/sasl_test_setup.sh deleted file mode 100755 index 6395ba6ec3..0000000000 --- a/cpp/src/tests/sasl_test_setup.sh +++ /dev/null @@ -1,41 +0,0 @@ -#! /bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -SASL_PW=/usr/sbin/saslpasswd2 -test -x $SASL_PW || { echo Skipping SASL test, saslpasswd2 not found; exit 0; } - -mkdir -p sasl_config - -# Create configuration file. -cat > sasl_config/qpidd.conf <<EOF -pwcheck_method: auxprop -auxprop_plugin: sasldb -sasldb_path: $PWD/sasl_config/qpidd.sasldb -sql_select: dummy select -EOF - -# Populate temporary sasl db. -SASLTEST_DB=./sasl_config/qpidd.sasldb -rm -f $SASLTEST_DB -echo guest | $SASL_PW -c -p -f $SASLTEST_DB -u QPID guest -echo zig | $SASL_PW -c -p -f $SASLTEST_DB -u QPID zig -echo zag | $SASL_PW -c -p -f $SASLTEST_DB -u QPID zag - diff --git a/cpp/src/tests/sasl_version.cpp b/cpp/src/tests/sasl_version.cpp deleted file mode 100644 index db3efe4181..0000000000 --- a/cpp/src/tests/sasl_version.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <iostream> - -#include "sasl/sasl.h" - - -/* - Some tests need to distinguish between different versions of - SASL. This encodes and outputs the version number as an integer - for easy use in testing scripts. -*/ - -int -main ( ) -{ - // I assume that these are 8-bit quantities.... - int sasl_version = (SASL_VERSION_MAJOR << 16) + - (SASL_VERSION_MINOR << 8) + - SASL_VERSION_STEP; - - std::cout << sasl_version << std::endl; - - return 0; -} - - - - diff --git a/cpp/src/tests/sender.cpp b/cpp/src/tests/sender.cpp deleted file mode 100644 index 063b5e87dc..0000000000 --- a/cpp/src/tests/sender.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/client/FailoverManager.h> -#include <qpid/client/Session.h> -#include <qpid/client/AsyncSession.h> -#include <qpid/client/Message.h> -#include <qpid/client/MessageReplayTracker.h> -#include <qpid/client/QueueOptions.h> -#include <qpid/Exception.h> -#include "TestOptions.h" - -#include "qpid/messaging/Message.h" // Only for Statistics -#include "Statistics.h" - -#include <fstream> -#include <iostream> - -using namespace qpid; -using namespace qpid::client; -using namespace qpid::framing; - -using namespace std; - -namespace qpid { -namespace tests { - -struct Args : public qpid::TestOptions -{ - string destination; - string key; - uint sendEos; - bool durable; - uint ttl; - string lvqMatchValue; - string lvqMatchFile; - bool reportTotal; - int reportEvery; - bool reportHeader; - - Args() : - key("test-queue"), sendEos(0), durable(false), ttl(0), - reportTotal(false), - reportEvery(0), - reportHeader(true) - { - addOptions() - ("exchange", qpid::optValue(destination, "EXCHANGE"), "Exchange to send messages to") - ("routing-key", qpid::optValue(key, "KEY"), "Routing key to add to messages") - ("send-eos", qpid::optValue(sendEos, "N"), "Send N EOS messages to mark end of input") - ("durable", qpid::optValue(durable, "true|false"), "Mark messages as durable.") - ("ttl", qpid::optValue(ttl, "msecs"), "Time-to-live for messages, in milliseconds") - ("lvq-match-value", qpid::optValue(lvqMatchValue, "KEY"), "The value to set for the LVQ match key property") - ("lvq-match-file", qpid::optValue(lvqMatchFile, "FILE"), "A file containing values to set for the LVQ match key property") - ("report-total", qpid::optValue(reportTotal), "Report total throughput statistics") - ("report-every", qpid::optValue(reportEvery,"N"), "Report throughput statistics every N messages") - ("report-header", qpid::optValue(reportHeader, "yes|no"), "Headers on report.") - ; - } -}; - -const string EOS("eos"); - -class Sender : public FailoverManager::Command -{ - public: - Sender(Reporter<Throughput>& reporter, const std::string& destination, const std::string& key, uint sendEos, bool durable, uint ttl, - const std::string& lvqMatchValue, const std::string& lvqMatchFile); - void execute(AsyncSession& session, bool isRetry); - - private: - Reporter<Throughput>& reporter; - messaging::Message dummyMessage; - const std::string destination; - MessageReplayTracker sender; - Message message; - const uint sendEos; - uint sent; - std::ifstream lvqMatchValues; -}; - -Sender::Sender(Reporter<Throughput>& rep, const std::string& dest, const std::string& key, uint eos, bool durable, uint ttl, const std::string& lvqMatchValue, const std::string& lvqMatchFile) : - reporter(rep), destination(dest), sender(10), message("", key), sendEos(eos), sent(0) , lvqMatchValues(lvqMatchFile.c_str()) -{ - if (durable){ - message.getDeliveryProperties().setDeliveryMode(framing::PERSISTENT); - } - - if (ttl) { - message.getDeliveryProperties().setTtl(ttl); - } - - if (!lvqMatchValue.empty()) { - message.getHeaders().setString(QueueOptions::strLVQMatchProperty, lvqMatchValue); - } -} - -void Sender::execute(AsyncSession& session, bool isRetry) -{ - if (isRetry) sender.replay(session); - else sender.init(session); - string data; - while (getline(std::cin, data)) { - message.setData(data); - //message.getHeaders().setInt("SN", ++sent); - string matchKey; - if (lvqMatchValues && getline(lvqMatchValues, matchKey)) { - message.getHeaders().setString(QueueOptions::strLVQMatchProperty, matchKey); - } - reporter.message(dummyMessage); // For statistics - sender.send(message, destination); - } - for (uint i = sendEos; i > 0; --i) { - message.setData(EOS); - sender.send(message, destination); - } -} - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char ** argv) -{ - Args opts; - try { - opts.parse(argc, argv); - Reporter<Throughput> reporter(std::cout, opts.reportEvery, opts.reportHeader); - FailoverManager connection(opts.con); - Sender sender(reporter, opts.destination, opts.key, opts.sendEos, opts.durable, opts.ttl, opts.lvqMatchValue, opts.lvqMatchFile); - connection.execute(sender); - connection.close(); - if (opts.reportTotal) reporter.report(); - return 0; - } catch(const std::exception& error) { - std::cout << "Failed: " << error.what() << std::endl; - } - return 1; -} diff --git a/cpp/src/tests/shared_perftest b/cpp/src/tests/shared_perftest deleted file mode 100755 index cc192d25bd..0000000000 --- a/cpp/src/tests/shared_perftest +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -exec `dirname $0`/run_perftest 100000 --mode shared --npubs 16 --nsubs 16 diff --git a/cpp/src/tests/shlibtest.cpp b/cpp/src/tests/shlibtest.cpp deleted file mode 100644 index 5655eb7e64..0000000000 --- a/cpp/src/tests/shlibtest.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -namespace qpid { -namespace tests { - -int* loaderData = 0; -extern "C" -#ifdef WIN32 -__declspec(dllexport) -#endif -void callMe(int *i) { loaderData=i; } - -struct OnUnload { ~OnUnload() { *loaderData=42; } }; -OnUnload unloader; // For destructor. - -}} // namespace qpid::tests diff --git a/cpp/src/tests/ssl.mk b/cpp/src/tests/ssl.mk deleted file mode 100644 index 435db0c55b..0000000000 --- a/cpp/src/tests/ssl.mk +++ /dev/null @@ -1,22 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -TESTS+=ssl_test -EXTRA_DIST+=ssl_test -CLEAN_LOCAL += test_cert_db cert.password diff --git a/cpp/src/tests/ssl_test b/cpp/src/tests/ssl_test deleted file mode 100755 index cbf75eb237..0000000000 --- a/cpp/src/tests/ssl_test +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run a simple test over SSL -source ./test_env.sh - -CONFIG=$(dirname $0)/config.null -CERT_DIR=`pwd`/test_cert_db -CERT_PW_FILE=`pwd`/cert.password -TEST_HOSTNAME=127.0.0.1 -TEST_CLIENT_CERT=rumplestiltskin -COUNT=10 - -trap cleanup EXIT - -error() { echo $*; exit 1; } - -create_certs() { - #create certificate and key databases with single, simple, self-signed certificate in it - mkdir ${CERT_DIR} - certutil -N -d ${CERT_DIR} -f ${CERT_PW_FILE} - certutil -S -d ${CERT_DIR} -n ${TEST_HOSTNAME} -s "CN=${TEST_HOSTNAME}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil - certutil -S -d ${CERT_DIR} -n ${TEST_CLIENT_CERT} -s "CN=${TEST_CLIENT_CERT}" -t "CT,," -x -f ${CERT_PW_FILE} -z /usr/bin/certutil -} - -delete_certs() { - if [[ -e ${CERT_DIR} ]] ; then - rm -rf ${CERT_DIR} - fi -} - -COMMON_OPTS="--daemon --no-data-dir --no-module-dir --auth no --config $CONFIG --load-module $SSL_LIB --ssl-cert-db $CERT_DIR --ssl-cert-password-file $CERT_PW_FILE --ssl-cert-name $TEST_HOSTNAME --require-encryption" -start_broker() { # $1 = extra opts - ../qpidd --transport ssl --port 0 --ssl-port 0 $COMMON_OPTS $1; -} - -stop_brokers() { - test -n "$PORT" && ../qpidd --no-module-dir -qp $PORT - test -n "$PORT2" && ../qpidd --no-module-dir -qp $PORT2 - PORT="" - PORT2="" -} - -cleanup() { - stop_brokers - delete_certs -} - -CERTUTIL=$(type -p certutil) -if [[ !(-x $CERTUTIL) ]] ; then - echo "No certutil, skipping ssl test"; - exit 0; -fi - -if [[ !(-e ${CERT_PW_FILE}) ]] ; then - echo password > ${CERT_PW_FILE} -fi -delete_certs -create_certs || error "Could not create test certificate" -PORT=`start_broker` || error "Could not start broker" -echo "Running SSL test on port $PORT" -export QPID_NO_MODULE_DIR=1 -export QPID_LOAD_MODULE=$SSLCONNECTOR_LIB -export QPID_SSL_CERT_DB=${CERT_DIR} -export QPID_SSL_CERT_PASSWORD_FILE=${CERT_PW_FILE} - -## Test connection via connection settings -./qpid-perftest --count ${COUNT} --port ${PORT} -P ssl -b $TEST_HOSTNAME --summary - -## Test connection with a URL -URL=amqp:ssl:$TEST_HOSTNAME:$PORT -./qpid-send -b $URL --content-string=hello -a "foo;{create:always}" -MSG=`./qpid-receive -b $URL -a "foo;{create:always}" --messages 1` -test "$MSG" = "hello" || { echo "receive failed '$MSG' != 'hello'"; exit 1; } - -#### Client Authentication tests - -PORT2=`start_broker --ssl-require-client-authentication` || error "Could not start broker" -echo "Running SSL client authentication test on port $PORT2" -URL=amqp:ssl:$TEST_HOSTNAME:$PORT2 - -## See if you can set the SSL cert-name for the connection -./qpid-send -b $URL --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }" --content-string=hello -a "bar;{create:always}" -MSG2=`./qpid-receive -b $URL --connection-options "{ssl-cert-name: $TEST_CLIENT_CERT }" -a "bar;{create:always}" --messages 1` -test "$MSG2" = "hello" || { echo "receive failed '$MSG2' != 'hello'"; exit 1; } - -## Make sure that connect fails with an invalid SSL cert-name -./qpid-send -b $URL --connection-options "{ssl-cert-name: pignose }" --content-string=hello -a "baz;{create:always}" 2>/dev/null 1>/dev/null -MSG3=`./qpid-receive -b $URL --connection-options "{ssl-cert-name: pignose }" -a "baz;{create:always}" --messages 1 2>/dev/null` -test "$MSG3" = "" || { echo "receive succeeded without valid ssl cert '$MSG3' != ''"; exit 1; } - -stop_brokers - -test -z $CLUSTER_LIB && exit 0 # Exit if cluster not supported. - -## Test failover in a cluster using SSL only -. $srcdir/ais_check # Will exit if clustering not enabled. - -pick_port() { - # We need a fixed port to set --cluster-url. Use qpidd to pick a free port. - PICK=`../qpidd --no-module-dir -dp0` - ../qpidd --no-module-dir -qp $PICK - echo $PICK -} -ssl_cluster_broker() { # $1 = port - ../qpidd $COMMON_OPTS --load-module $CLUSTER_LIB --cluster-name ssl_test.$HOSTNAME.$$ --cluster-url amqp:ssl:$TEST_HOSTNAME:$1 --port 0 --ssl-port $1 --transport ssl > /dev/null - # Wait for broker to be ready - qpid-ping -Pssl -b $TEST_HOSTNAME -qp $1 || { echo "Cannot connect to broker on $1"; exit 1; } - echo "Running SSL cluster broker on port $1" -} - -PORT1=`pick_port`; ssl_cluster_broker $PORT1 -PORT2=`pick_port`; ssl_cluster_broker $PORT2 - -# Pipe receive output to uniq to remove duplicates -./qpid-receive --connection-options "{reconnect:true, reconnect-timeout:5}" --failover-updates -b amqp:ssl:$TEST_HOSTNAME:$PORT1 -a "foo;{create:always}" -f | uniq > ssl_test_receive.tmp & -./qpid-send -b amqp:ssl:$TEST_HOSTNAME:$PORT2 --content-string=one -a "foo;{create:always}" -../qpidd --no-module-dir -qp $PORT1 # Kill broker 1 receiver should fail-over. -./qpid-send -b amqp:ssl:$TEST_HOSTNAME:$PORT2 --content-string=two -a "foo;{create:always}" --send-eos 1 -wait # Wait for qpid-receive -{ echo one; echo two; } > ssl_test_receive.cmp -diff ssl_test_receive.tmp ssl_test_receive.cmp || { echo "Failover failed"; exit 1; } -rm -f ssl_test_receive.* - diff --git a/cpp/src/tests/start_broker b/cpp/src/tests/start_broker deleted file mode 100755 index 093c44051a..0000000000 --- a/cpp/src/tests/start_broker +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Start a test broker. -srcdir=`dirname $0` -exec $srcdir/run_test ../qpidd --auth=no --no-module-dir --daemon --port=0 --log-to-file qpidd.log "$@" > qpidd.port diff --git a/cpp/src/tests/start_broker.ps1 b/cpp/src/tests/start_broker.ps1 deleted file mode 100644 index 9263262b9f..0000000000 --- a/cpp/src/tests/start_broker.ps1 +++ /dev/null @@ -1,60 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Get the directory where this script resides. -function Get-ScriptPath - { Split-Path $myInvocation.ScriptName } - -# Start a test broker and capture it's port (from stdout) to qpidd.port -# This script will exit immediately after spawning the broker process. To avoid -# running more tests before the broker is initialized, wait for the qpidd.port -# file to appear before exiting. -if (Test-Path qpidd.port) { - Remove-Item qpidd.port -} - -# Test runs from the tests directory but the broker executable is one level -# up, and most likely in a subdirectory from there based on what build type. -# Look around for it before trying to start it. -$subs = "Debug","Release","MinSizeRel","RelWithDebInfo" -foreach ($sub in $subs) { - $prog = "..\$sub\qpidd.exe" - if (Test-Path $prog) { - break - } -} -if (!(Test-Path $prog)) { - "Cannot locate qpidd.exe" - exit 1 -} -$cmdline = "$prog --auth=no --no-module-dir --port=0 --log-to-file qpidd.log $args | foreach { set-content qpidd.port `$_ }" -$cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline) -$srcdir = Get-ScriptPath -. $srcdir\background.ps1 $cmdblock - -$wait_time = 0 -while (!(Test-Path qpidd.port) -and ($wait_time -lt 10)) { - Start-Sleep 2 - $wait_time += 2 -} -if (Test-Path qpidd.port) { - exit 0 -} -"Time out waiting for broker to start" -exit 1 diff --git a/cpp/src/tests/start_cluster b/cpp/src/tests/start_cluster deleted file mode 100755 index bc35a2eddc..0000000000 --- a/cpp/src/tests/start_cluster +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Start a cluster of brokers on local host, put the list of ports for cluster members in cluster.ports -# - -# Execute command with the ais group set. -source ./test_env.sh -. `dirname $0`/ais_check - -rm -f cluster*.log cluster.ports qpidd.port - -SIZE=${1:-3}; shift -CLUSTER=$HOSTNAME.$$ -OPTS="-d --no-module-dir --load-module $CLUSTER_LIB --cluster-name=$CLUSTER --auth=no --log-enable notice+ --log-enable debug+:cluster $@" - -for (( i=0; i<SIZE; ++i )); do - DDIR=`mktemp -d /tmp/start_cluster.XXXXXXXXXX` - PORT=`with_ais_group ../qpidd -p0 --log-to-file=cluster$i.log $OPTS --data-dir=$DDIR` || exit 1 - echo $PORT >> cluster.ports -done - -head -n 1 cluster.ports > qpidd.port # First member's port for tests. - diff --git a/cpp/src/tests/start_cluster_hosts b/cpp/src/tests/start_cluster_hosts deleted file mode 100755 index 778b4248da..0000000000 --- a/cpp/src/tests/start_cluster_hosts +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# -# Start a cluster of brokers on local host, put the list of host port addresses -# in cluster.ports -# -# Arguments: [-k] [-p port] HOST [HOST...] -# -p port to start broker on, can be 0. Actual ports recorded in cluster.addr. -# -k kill any qpidd processes owned by this user before starting. -# -# Start a broker on each named host. Name a host twice to start multiple brokers. -# -# You must be able to ssh to each host and be in group ais. -# $QPIDD must be executable on each host. -# Logs go to syslog on each host, with a unique prefix per broker. -# - -QPIDD=${QPIDD:-$PWD/../qpidd} -LIBQPIDCLUSTER=${LIBQPIDCLUSTER:-$PWD/../.libs/cluster.so} -NAME=$USER # User name is default cluster name. -RESTART=NO - -while getopts "kp:n:q:r" ARG ; do - case $ARG in - k) KILL=yes ;; - p) PORT="$OPTARG" ;; - n) NAME=$OPTARG ;; - q) QPIDD=$OPTARG ;; - l) LIBQPIDCLUSTER=$OPTARG ;; - r) RESTART=yes ;; - *) echo "Error parsing options: $ARG"; exit 1 ;; - esac -done -shift `expr $OPTIND - 1` -test -n "$PORT" && PORTOPT="-p $PORT" -test "$KILL" = yes && KILL="$QPIDD --no-module-dir -q $PORTOPT ;" -CLUSTER=${*:-$CLUSTER} # Use args or env -test -z "$CLUSTER" && { echo Must specify at least one host; exit 1; } - - -OPTS="-d $PORTOPT --load-module $LIBQPIDCLUSTER --cluster-name=$NAME --no-data-dir --auth=no --log-to-syslog --log-enable=info+" - -num=0 -for h in $CLUSTER; do - num=`expr $num + 1` # Give a unique log prefix to each node. - cmd="$KILL $QPIDD $OPTS --log-prefix $num.$h" - out=`echo "$cmd" | ssh $h newgrp ais` || { echo == $h error: $out ; exit 1; } - if [ "$PORT" = 0 ] ; then p=$out; else p=$PORT; fi - echo "$h $p" -done - diff --git a/cpp/src/tests/stop_broker b/cpp/src/tests/stop_broker deleted file mode 100755 index 248fd1fc5c..0000000000 --- a/cpp/src/tests/stop_broker +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Stop the broker, check for errors. -# -QPID_PORT=`cat qpidd.port` -export QPID_PORT -rm -f qpidd.port - -../qpidd --no-module-dir --quit || ERROR=1 - -# Check qpidd.log. -egrep 'warning\|error\|critical' qpidd.log && { - echo "WARNING: Suspicious broker log entries in qpidd.log, above." -} - -# Check valgrind log. -if test -n "$VALGRIND"; then - . `dirname $0`/vg_check $VG_LOG* - vg_check qpidd.vglog* || ERROR=1 -fi - -exit $ERROR diff --git a/cpp/src/tests/stop_broker.ps1 b/cpp/src/tests/stop_broker.ps1 deleted file mode 100644 index 4fdeb26e2b..0000000000 --- a/cpp/src/tests/stop_broker.ps1 +++ /dev/null @@ -1,56 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Stop the broker, check for errors. -Get-Content -path qpidd.port -totalCount 1 | Set-Variable -name qpid_port -Remove-Item qpidd.port - -# Test runs from the tests directory but the broker executable is one level -# up, and most likely in a subdirectory from there based on what build type. -# Look around for it before trying to start it. -$subs = "Debug","Release","MinSizeRel","RelWithDebInfo" -foreach ($sub in $subs) { - $prog = "..\$sub\qpidd.exe" - if (Test-Path $prog) { - break - } -} -if (!(Test-Path $prog)) { - "Cannot locate qpidd.exe" - exit 1 -} - -# Piping the output makes the script wait for qpidd to finish. -Invoke-Expression "$prog --quit --port $qpid_port" | Write-Output -$stopped = $? - -# Check qpidd.log. -filter bad_stuff { - $_ -match "( warning | error | critical )" -} - -$qpidd_errors = $false -Get-Content -path qpidd.log | where { bad_stuff } | Out-Default | Set-Variable -name qpidd_errors -value $true -if ($qpidd_errors -eq $true) { - "WARNING: Suspicious broker log entries in qpidd.log, above." -} -if ($stopped -eq $true) { - exit 0 -} -exit 1 diff --git a/cpp/src/tests/stop_cluster b/cpp/src/tests/stop_cluster deleted file mode 100755 index d598a2255a..0000000000 --- a/cpp/src/tests/stop_cluster +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Stop brokers on ports listed in cluster.ports - -PORTS=`cat cluster.ports` -for PORT in $PORTS ; do - $QPIDD_EXEC --no-module-dir -qp $PORT || ERROR="$ERROR $PORT" -done -rm -f cluster.ports qpidd.port - -if [ -n "$ERROR" ]; then - echo "Errors stopping brokers on ports: $ERROR" - exit 1 -fi diff --git a/cpp/src/tests/store.py b/cpp/src/tests/store.py deleted file mode 100755 index 77e8a78e5d..0000000000 --- a/cpp/src/tests/store.py +++ /dev/null @@ -1,197 +0,0 @@ -#!/usr/bin/env python -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -import errno, os, time -from brokertest import * -from qpid import compat, session -from qpid.util import connect -from qpid.connection import Connection -from qpid.datatypes import Message, uuid4 -from qpid.queue import Empty - -class StoreTests(BrokerTest): - - XA_RBROLLBACK = 1 - XA_RBTIMEOUT = 2 - XA_OK = 0 - tx_counter = 0 - - def configure(self, config): - self.config = config - self.defines = self.config.defines - BrokerTest.configure(self, config) - - def setup_connection(self): - socket = connect(self._broker.host(), self._broker.port()) - return Connection(sock=socket) - - def setup_session(self): - self.conn.start() - return self.conn.session(str(uuid4())) - - def start_session(self): - self.conn = self.setup_connection() - self.ssn = self.setup_session() - - def setUp(self): - BrokerTest.setUp(self) - self._broker = self.broker() - self.start_session() - - def cycle_broker(self): - # tearDown resets working dir; change it back after. - d = os.getcwd() - BrokerTest.tearDown(self) - os.chdir(d) - self._broker = None - self._broker = self.broker() - self.conn = self.setup_connection() - self.ssn = self.setup_session() - - def xid(self, txid): - StoreTests.tx_counter += 1 - branchqual = "v%s" % StoreTests.tx_counter - return self.ssn.xid(format=0, global_id=txid, branch_id=branchqual) - - def testDurableExchange(self): - try: - self.ssn.exchange_delete(exchange="DE1") - except: - # restart the session busted from the exception - self.start_session() - - self.ssn.exchange_declare(exchange="DE1", type="direct", durable=True) - response = self.ssn.exchange_query(name="DE1") - self.assert_(response.durable) - self.assert_(not response.not_found) - - # Cycle the broker and make sure the exchange recovers - self.cycle_broker() - response = self.ssn.exchange_query(name="DE1") - self.assert_(response.durable) - self.assert_(not response.not_found) - - self.ssn.exchange_delete(exchange="DE1") - - def testDurableQueues(self): - try: - self.ssn.queue_delete(queue="DQ1") - except: - self.start_session() - - self.ssn.queue_declare(queue="DQ1", durable=True) - response = self.ssn.queue_query(queue="DQ1") - self.assertEqual("DQ1", response.queue) - self.assert_(response.durable) - - # Cycle the broker and make sure the queue recovers - self.cycle_broker() - response = self.ssn.queue_query(queue="DQ1") - self.assertEqual("DQ1", response.queue) - self.assert_(response.durable) - - self.ssn.queue_delete(queue="DQ1") - - def testDurableBindings(self): - try: - self.ssn.exchange_unbind(queue="DB_Q1", exchange="DB_E1", binding_key="K1") - except: - self.start_session() - try: - self.ssn.exchange_delete(exchange="DB_E1") - except: - self.start_session() - try: - self.ssn.queue_delete(queue="DB_Q1") - except: - self.start_session() - - self.ssn.queue_declare(queue="DB_Q1", durable=True) - self.ssn.exchange_declare(exchange="DB_E1", type="direct", durable=True) - self.ssn.exchange_bind(exchange="DB_E1", queue="DB_Q1", binding_key="K1") - - # Cycle the broker and make sure the binding recovers - self.cycle_broker() - response = self.ssn.exchange_bound(exchange="DB_E1", queue="DB_Q1", binding_key="K1") - self.assert_(not response.exchange_not_found) - self.assert_(not response.queue_not_found) - self.assert_(not response.queue_not_matched) - self.assert_(not response.key_not_matched) - - self.ssn.exchange_unbind(queue="DB_Q1", exchange="DB_E1", binding_key="K1") - self.ssn.exchange_delete(exchange="DB_E1") - self.ssn.queue_delete(queue="DB_Q1") - - def testDtxRecoverPrepared(self): - try: - self.ssn.exchange_unbind(queue="Dtx_Q", exchange="Dtx_E", binding_key="Dtx") - except: - self.start_session() - try: - self.ssn.exchange_delete(exchange="Dtx_E") - except: - self.start_session() - try: - self.ssn.queue_delete(queue="Dtx_Q") - except: - self.start_session() - - self.ssn.queue_declare(queue="Dtx_Q", auto_delete=False, durable=True) - self.ssn.exchange_declare(exchange="Dtx_E", type="direct", durable=True) - self.ssn.exchange_bind(exchange="Dtx_E", queue="Dtx_Q", binding_key="Dtx") - txid = self.xid("DtxRecoverPrepared") - self.ssn.dtx_select() - self.ssn.dtx_start(xid=txid) - # 2 = delivery_mode.persistent - dp = self.ssn.delivery_properties(routing_key="Dtx_Q", delivery_mode=2) - self.ssn.message_transfer(message=Message(dp, "transactional message")) - self.ssn.dtx_end(xid=txid) - self.assertEqual(self.XA_OK, self.ssn.dtx_prepare(xid=txid).status) - # Cycle the broker and make sure the xid is there, the message is not - # queued. - self.cycle_broker() - # The txid should be recovered and in doubt - xids = self.ssn.dtx_recover().in_doubt - xid_matched = False - for x in xids: - self.assertEqual(txid.format, x.format) - self.assertEqual(txid.global_id, x.global_id) - self.assertEqual(txid.branch_id, x.branch_id) - xid_matched = True - self.assert_(xid_matched) - self.ssn.message_subscribe(destination="dtx_msgs", queue="Dtx_Q", accept_mode=1, acquire_mode=0) - self.ssn.message_flow(unit = 1, value = 0xFFFFFFFFL, destination = "dtx_msgs") - self.ssn.message_flow(unit = 0, value = 10, destination = "dtx_msgs") - message_arrivals = self.ssn.incoming("dtx_msgs") - try: - message_arrivals.get(timeout=1) - assert False, 'Message present in queue before commit' - except Empty: pass - self.ssn.dtx_select() - self.assertEqual(self.XA_OK, self.ssn.dtx_commit(xid=txid, one_phase=False).status) - try: - msg = message_arrivals.get(timeout=1) - self.assertEqual("transactional message", msg.body) - except Empty: - assert False, 'Message should be present after dtx commit but is not' - - self.ssn.exchange_unbind(queue="Dtx_Q", exchange="Dtx_E", binding_key="Dtx") - self.ssn.exchange_delete(exchange="Dtx_E") - self.ssn.queue_delete(queue="Dtx_Q") diff --git a/cpp/src/tests/test.xquery b/cpp/src/tests/test.xquery deleted file mode 100644 index 4cfe3af02d..0000000000 --- a/cpp/src/tests/test.xquery +++ /dev/null @@ -1,6 +0,0 @@ - let $w := ./weather - return $w/station = 'Raleigh-Durham International Airport (KRDU)' - and $w/temperature_f > 50 - and $w/temperature_f - $w/dewpoint > 5 - and $w/wind_speed_mph > 7 - and $w/wind_speed_mph < 20 diff --git a/cpp/src/tests/test_env.sh.in b/cpp/src/tests/test_env.sh.in deleted file mode 100644 index 842d7729cb..0000000000 --- a/cpp/src/tests/test_env.sh.in +++ /dev/null @@ -1,79 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -absdir() { echo `cd $1 && pwd`; } - -# Environment variables substituted by configure/cmake. -srcdir=`absdir @abs_srcdir@` -builddir=`absdir @abs_builddir@` -top_srcdir=`absdir @abs_top_srcdir@` -top_builddir=`absdir @abs_top_builddir@` -moduledir=$top_builddir/src@builddir_lib_suffix@ -testmoduledir=$builddir@builddir_lib_suffix@ -export QPID_INSTALL_PREFIX=@prefix@ - -# Python paths and directories -export PYTHON_DIR=$builddir/python -export QPID_PYTHON_TEST=$PYTHON_DIR/commands/qpid-python-test -if [ ! -d $PYTHON_DIR -a -d $top_srcdir/../python ]; then - export PYTHON_DIR=$top_srcdir/../python - export QPID_PYTHON_TEST=$PYTHON_DIR/qpid-python-test -fi -export QPID_TESTS=$top_srcdir/../tests -export QPID_TESTS_PY=$QPID_TESTS/src/py -export QPID_TOOLS=$top_srcdir/../tools -export QMF_LIB=$top_srcdir/../extras/qmf/src/py -export PYTHON_COMMANDS=$QPID_TOOLS/src/py -export PYTHONPATH=$srcdir:$PYTHON_DIR:$PYTHON_COMMANDS:$QPID_TESTS_PY:$QMF_LIB:$PYTHONPATH -export QPID_CONFIG_EXEC=$PYTHON_COMMANDS/qpid-config -export QPID_ROUTE_EXEC=$PYTHON_COMMANDS/qpid-route -export QPID_CLUSTER_EXEC=$PYTHON_COMMANDS/qpid-cluster - -# Executables -export QPIDD_EXEC=$top_builddir/src/qpidd -export QPID_WATCHDOG_EXEC=$top_builddir/src/qpidd_watchdog - -# Test executables -export QPID_TEST_EXEC_DIR=$builddir -export RECEIVER_EXEC=$QPID_TEST_EXEC_DIR/receiver -export SENDER_EXEC=$QPID_TEST_EXEC_DIR/sender - -# Path -export PATH=$top_builddir/src:$builddir:$srcdir:$PYTHON_COMMANDS:$QPID_TEST_EXEC_DIR:$PATH - -# Modules -export TEST_STORE_LIB=$testmoduledir/test_store.so - -exportmodule() { test -f $moduledir/$2 && eval "export $1=$moduledir/$2"; } -exportmodule ACL_LIB acl.so -exportmodule CLUSTER_LIB cluster.so -exportmodule REPLICATING_LISTENER_LIB replicating_listener.so -exportmodule REPLICATION_EXCHANGE_LIB replication_exchange.so -exportmodule SSLCONNECTOR_LIB sslconnector.so -exportmodule SSL_LIB ssl.so -exportmodule WATCHDOG_LIB watchdog.so -exportmodule XML_LIB xml.so - -# Qpid options -export QPID_NO_MODULE_DIR=1 # Don't accidentally load installed modules -export QPID_DATA_DIR= # Default to no data dir, not ~/.qpidd - -# Options for boost test framework -export BOOST_TEST_SHOW_PROGRESS=yes -export BOOST_TEST_CATCH_SYSTEM_ERRORS=no diff --git a/cpp/src/tests/test_store.cpp b/cpp/src/tests/test_store.cpp deleted file mode 100644 index 257e77b6b4..0000000000 --- a/cpp/src/tests/test_store.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -/**@file - * Plug-in message store for tests. - * - * Add functionality as required, build up a comprehensive set of - * features to support persistent behavior tests. - * - * Current features special "action" messages can: - * - raise exception from enqueue. - * - force host process to exit. - * - do async completion after a delay. - */ - -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/Broker.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/log/Statement.h" -#include "qpid/Plugin.h" -#include "qpid/Options.h" -#include <boost/cast.hpp> -#include <boost/lexical_cast.hpp> -#include <memory> -#include <fstream> - -using namespace qpid; -using namespace broker; -using namespace std; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -struct TestStoreOptions : public Options { - - string name; - string dump; - - TestStoreOptions() : Options("Test Store Options") { - addOptions() - ("test-store-name", optValue(name, "NAME"), "Name of test store instance.") - ("test-store-dump", optValue(dump, "FILE"), "File to dump enqueued messages.") - ; - } -}; - -struct Completer : public Runnable { - boost::intrusive_ptr<PersistableMessage> message; - int usecs; - Completer(boost::intrusive_ptr<PersistableMessage> m, int u) : message(m), usecs(u) {} - void run() { - qpid::sys::usleep(usecs); - message->enqueueComplete(); - delete this; - } -}; - -class TestStore : public NullMessageStore { - public: - TestStore(const TestStoreOptions& opts, Broker& broker_) - : options(opts), name(opts.name), broker(broker_) - { - QPID_LOG(info, "TestStore name=" << name << " dump=" << options.dump); - if (!options.dump.empty()) - dump.reset(new ofstream(options.dump.c_str())); - } - - ~TestStore() { - for_each(threads.begin(), threads.end(), boost::bind(&Thread::join, _1)); - } - - virtual bool isNull() const { return false; } - - void enqueue(TransactionContext* , - const boost::intrusive_ptr<PersistableMessage>& pmsg, - const PersistableQueue& ) - { - Message* msg = dynamic_cast<Message*>(pmsg.get()); - assert(msg); - - // Dump the message if there is a dump file. - if (dump.get()) { - msg->getFrames().getMethod()->print(*dump); - *dump << endl << " "; - msg->getFrames().getHeaders()->print(*dump); - *dump << endl << " "; - *dump << msg->getFrames().getContentSize() << endl; - } - - // Check the message for special instructions. - string data = msg->getFrames().getContent(); - size_t i = string::npos; - size_t j = string::npos; - if (strncmp(data.c_str(), TEST_STORE_DO.c_str(), strlen(TEST_STORE_DO.c_str())) == 0 - && (i = data.find(name+"[")) != string::npos - && (j = data.find("]", i)) != string::npos) - { - size_t start = i+name.size()+1; - string action = data.substr(start, j-start); - - if (action == EXCEPTION) { - throw Exception(QPID_MSG("TestStore " << name << " throwing exception for: " << data)); - } - else if (action == EXIT_PROCESS) { - // FIXME aconway 2009-04-10: this is a dubious way to - // close the process at best, it can cause assertions or seg faults - // rather than clean exit. - QPID_LOG(critical, "TestStore " << name << " forcing process exit for: " << data); - exit(0); - } - else if (strncmp(action.c_str(), ASYNC.c_str(), strlen(ASYNC.c_str())) == 0) { - std::string delayStr(action.substr(ASYNC.size())); - int delay = boost::lexical_cast<int>(delayStr); - threads.push_back(Thread(*new Completer(msg, delay))); - } - else { - QPID_LOG(error, "TestStore " << name << " unknown action " << action); - msg->enqueueComplete(); - } - } - else - msg->enqueueComplete(); - } - - private: - static const string TEST_STORE_DO, EXCEPTION, EXIT_PROCESS, ASYNC; - TestStoreOptions options; - string name; - Broker& broker; - vector<Thread> threads; - std::auto_ptr<ofstream> dump; -}; - -const string TestStore::TEST_STORE_DO = "TEST_STORE_DO: "; -const string TestStore::EXCEPTION = "exception"; -const string TestStore::EXIT_PROCESS = "exit_process"; -const string TestStore::ASYNC="async "; - -struct TestStorePlugin : public Plugin { - - TestStoreOptions options; - - Options* getOptions() { return &options; } - - void earlyInitialize (Plugin::Target& target) - { - Broker* broker = dynamic_cast<Broker*>(&target); - if (!broker) return; - boost::shared_ptr<MessageStore> p(new TestStore(options, *broker)); - broker->setStore (p); - } - - void initialize(qpid::Plugin::Target&) {} -}; - -static TestStorePlugin pluginInstance; - -}} // namespace qpid::tests diff --git a/cpp/src/tests/test_tools.h b/cpp/src/tests/test_tools.h deleted file mode 100644 index de672f938a..0000000000 --- a/cpp/src/tests/test_tools.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef TEST_TOOLS_H -#define TEST_TOOLS_H - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "qpid/log/Logger.h" - -#include <limits.h> // Include before boost/test headers. -#include <boost/test/test_tools.hpp> -#include <boost/assign/list_of.hpp> -#include <boost/assign/list_of.hpp> -#include <vector> -#include <set> -#include <ostream> -#include <sstream> -#include <exception> - -// Print a sequence -template <class T> std::ostream& seqPrint(std::ostream& o, const T& seq) { - std::copy(seq.begin(), seq.end(), std::ostream_iterator<typename T::value_type>(o, " ")); - return o; -} - -// Compare sequences -template <class T, class U> -bool seqEqual(const T& a, const U& b) { - typename T::const_iterator i = a.begin(); - typename U::const_iterator j = b.begin(); - while (i != a.end() && j != b.end() && *i == *j) { ++i; ++j; } - return (i == a.end()) && (j == b.end()); -} - -// ostream and == operators so we can compare vectors and sets with -// boost::assign::list_of with BOOST_CHECK_EQUALS -namespace std { // In namespace std so boost can find them. - -template <class T> -ostream& operator<<(ostream& o, const vector<T>& v) { return seqPrint(o, v); } - -template <class T> -ostream& operator<<(ostream& o, const set<T>& v) { return seqPrint(o, v); } - -template <class T> -ostream& operator<<(ostream& o, const boost::assign_detail::generic_list<T>& l) { return seqPrint(o, l); } - -template <class T> -bool operator == (const vector<T>& a, const boost::assign_detail::generic_list<T>& b) { return seqEqual(a, b); } - -template <class T> -bool operator == (const boost::assign_detail::generic_list<T>& b, const vector<T>& a) { return seqEqual(a, b); } - -template <class T> -bool operator == (const set<T>& a, const boost::assign_detail::generic_list<T>& b) { return seqEqual(a, b); } - -template <class T> -bool operator == (const boost::assign_detail::generic_list<T>& b, const set<T>& a) { return seqEqual(a, b); } -} - -namespace qpid { -namespace tests { - -/** Check if types of two objects (as given by typeinfo::name()) match. */ -#define BOOST_CHECK_TYPEID_EQUAL(a,b) BOOST_CHECK_EQUAL(typeid(a).name(),typeid(b).name()) - -/** - * Supress all logging in a scope, restore to previous configuration in destructor. - */ -struct ScopedSuppressLogging { - typedef qpid::log::Logger Logger; - ScopedSuppressLogging(Logger& l=Logger::instance()) : logger(l), opts(l.getOptions()) { l.clear(); } - ~ScopedSuppressLogging() { logger.configure(opts); } - Logger& logger; - qpid::log::Options opts; -}; - -inline std::string getLibPath(const char* envName, const char* defaultPath = 0) { - const char* p = std::getenv(envName); - if (p != 0) - return p; - if (defaultPath == 0) { - std::ostringstream msg; - msg << "Environment variable " << envName << " not set."; - throw std::runtime_error(msg.str()); - } - return defaultPath; -} - -}} // namespace qpid::tests - -#endif /*!TEST_TOOLS_H*/ - diff --git a/cpp/src/tests/test_watchdog b/cpp/src/tests/test_watchdog deleted file mode 100755 index 2b4ae9246e..0000000000 --- a/cpp/src/tests/test_watchdog +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Tests for the watchdog plug-in - -source ./test_env.sh -# Start a broker with watchdog, freeze it with kill -STOP, verify that it is killed. -PORT=`$QPIDD_EXEC -dp0 --no-data-dir --auth=no --no-module-dir --load-module $WATCHDOG_LIB --log-to-file=qpidd_watchdog.log --watchdog-interval 2` || exit 1 -PID=`$QPIDD_EXEC --no-module-dir -cp $PORT` || exit 1 -kill -STOP $PID -sleep 3 - -if kill -0 $PID 2>/dev/null; then - echo "Hung process did not die." - kill $PID -else - true -fi diff --git a/cpp/src/tests/test_wrap b/cpp/src/tests/test_wrap deleted file mode 100755 index dd43c5a2e2..0000000000 --- a/cpp/src/tests/test_wrap +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Read the started broker port, set appropriate env vars -# then run the program under test - -QPID_PORT=`cat qpidd.port` -export QPID_PORT - -program=$1 -shift - -QPID_LOG_TO_FILE=`basename $program`.log -export QPID_LOG_TO_FILE - -ERROR=0 -$program $* || ERROR=1 - -# Check qpidd.log. -egrep 'warning\|error\|critical' $QPID_LOG_TO_FILE && { - echo "WARNING: Suspicious broker log entries in $QPID_LOG_TO_FILE, above." -} - -# Check valgrind log. -#if test -n "$VALGRIND"; then -# . `dirname $0`/vg_check $VG_LOG* -# vg_check qpidd.vglog* || ERROR=1 -#fi - -exit $ERROR diff --git a/cpp/src/tests/testagent.cpp b/cpp/src/tests/testagent.cpp deleted file mode 100644 index 98520b424a..0000000000 --- a/cpp/src/tests/testagent.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/management/Manageable.h> -#include <qpid/management/ManagementObject.h> -#include <qpid/agent/ManagementAgent.h> -#include <qpid/sys/Mutex.h> -#include <qpid/sys/Time.h> -#include "qmf/org/apache/qpid/agent/example/Parent.h" -#include "qmf/org/apache/qpid/agent/example/Child.h" -#include "qmf/org/apache/qpid/agent/example/ArgsParentCreate_child.h" -#include "qmf/org/apache/qpid/agent/example/EventChildCreated.h" -#include "qmf/org/apache/qpid/agent/example/Package.h" - -#include <signal.h> -#include <cstdlib> -#include <iostream> - -#include <sstream> - -static bool running = true; - -using namespace std; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::sys::Mutex; -namespace _qmf = qmf::org::apache::qpid::agent::example; - -class ChildClass; - -//============================================================== -// CoreClass is the operational class that corresponds to the -// "Parent" class in the management schema. -//============================================================== -class CoreClass : public Manageable -{ - string name; - ManagementAgent* agent; - _qmf::Parent* mgmtObject; - std::vector<ChildClass*> children; - Mutex vectorLock; - -public: - - CoreClass(ManagementAgent* agent, string _name); - ~CoreClass() { mgmtObject->resourceDestroy(); } - - ManagementObject* GetManagementObject(void) const - { return mgmtObject; } - - void doLoop(); - status_t ManagementMethod (uint32_t methodId, Args& args, string& text); -}; - -class ChildClass : public Manageable -{ - string name; - _qmf::Child* mgmtObject; - -public: - - ChildClass(ManagementAgent* agent, CoreClass* parent, string name); - ~ChildClass() { mgmtObject->resourceDestroy(); } - - ManagementObject* GetManagementObject(void) const - { return mgmtObject; } - - void doWork() - { - mgmtObject->inc_count(2); - } -}; - -CoreClass::CoreClass(ManagementAgent* _agent, string _name) : name(_name), agent(_agent) -{ - static uint64_t persistId = 0x111222333444555LL; - mgmtObject = new _qmf::Parent(agent, this, name); - - agent->addObject(mgmtObject, persistId++); - mgmtObject->set_state("IDLE"); -} - -void CoreClass::doLoop() -{ - // Periodically bump a counter to provide a changing statistical value - while (running) { - qpid::sys::sleep(1); - mgmtObject->inc_count(); - mgmtObject->set_state("IN_LOOP"); - - { - Mutex::ScopedLock _lock(vectorLock); - - for (std::vector<ChildClass*>::iterator iter = children.begin(); - iter != children.end(); - iter++) { - (*iter)->doWork(); - } - } - } -} - -Manageable::status_t CoreClass::ManagementMethod(uint32_t methodId, Args& args, string& /*text*/) -{ - Mutex::ScopedLock _lock(vectorLock); - - switch (methodId) { - case _qmf::Parent::METHOD_CREATE_CHILD: - _qmf::ArgsParentCreate_child& ioArgs = (_qmf::ArgsParentCreate_child&) args; - - ChildClass *child = new ChildClass(agent, this, ioArgs.i_name); - ioArgs.o_childRef = child->GetManagementObject()->getObjectId(); - - children.push_back(child); - - agent->raiseEvent(_qmf::EventChildCreated(ioArgs.i_name)); - - return STATUS_OK; - } - - return STATUS_NOT_IMPLEMENTED; -} - -ChildClass::ChildClass(ManagementAgent* agent, CoreClass* parent, string name) -{ - mgmtObject = new _qmf::Child(agent, this, parent, name); - - agent->addObject(mgmtObject); -} - - -//============================================================== -// Main program -//============================================================== - -ManagementAgent::Singleton* singleton; - -void shutdown(int) -{ - running = false; -} - -int main_int(int argc, char** argv) -{ - singleton = new ManagementAgent::Singleton(); - const char* host = argc>1 ? argv[1] : "127.0.0.1"; - int port = argc>2 ? atoi(argv[2]) : 5672; - - signal(SIGINT, shutdown); - - // Create the qmf management agent - ManagementAgent* agent = singleton->getInstance(); - - // Register the Qmf_example schema with the agent - _qmf::Package packageInit(agent); - - // Start the agent. It will attempt to make a connection to the - // management broker - agent->init(host, port, 5, false, ".magentdata"); - - // Allocate some core objects - CoreClass core1(agent, "Example Core Object #1"); - CoreClass core2(agent, "Example Core Object #2"); - CoreClass core3(agent, "Example Core Object #3"); - - core1.doLoop(); - - // done, cleanup and exit - delete singleton; - - return 0; -} - -int main(int argc, char** argv) -{ - try { - return main_int(argc, argv); - } catch(std::exception& e) { - cerr << "Top Level Exception: " << e.what() << endl; - return 1; - } -} - diff --git a/cpp/src/tests/testagent.mk b/cpp/src/tests/testagent.mk deleted file mode 100644 index 19d91ccab9..0000000000 --- a/cpp/src/tests/testagent.mk +++ /dev/null @@ -1,51 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Build a simple qmf agent for test purposes. - -TESTAGENT_GEN_SRC= \ - testagent_gen/qmf/org/apache/qpid/agent/example/Parent.h \ - testagent_gen/qmf/org/apache/qpid/agent/example/Child.h \ - testagent_gen/qmf/org/apache/qpid/agent/example/Parent.cpp \ - testagent_gen/qmf/org/apache/qpid/agent/example/Child.cpp \ - testagent_gen/qmf/org/apache/qpid/agent/example/ArgsParentCreate_child.h \ - testagent_gen/qmf/org/apache/qpid/agent/example/EventChildCreated.h \ - testagent_gen/qmf/org/apache/qpid/agent/example/EventChildDestroyed.h \ - testagent_gen/qmf/org/apache/qpid/agent/example/EventChildCreated.cpp \ - testagent_gen/qmf/org/apache/qpid/agent/example/EventChildDestroyed.cpp \ - testagent_gen/qmf/org/apache/qpid/agent/example/Package.h \ - testagent_gen/qmf/org/apache/qpid/agent/example/Package.cpp - -$(TESTAGENT_GEN_SRC): testagent_gen.timestamp -if GENERATE -TESTAGENT_DEPS=../mgen.timestamp -endif # GENERATE -testagent_gen.timestamp: testagent.xml ${TESTAGENT_DEPS} - $(QMF_GEN) -o testagent_gen/qmf $(srcdir)/testagent.xml - touch $@ - -CLEANFILES+=$(TESTAGENT_GEN_SRC) testagent_gen.timestamp - -testagent-testagent.$(OBJEXT): $(TESTAGENT_GEN_SRC) -qpidtest_PROGRAMS+=testagent -testagent_CXXFLAGS=$(CXXFLAGS) -Itestagent_gen -testagent_SOURCES=testagent.cpp $(TESTAGENT_GEN_SRC) -testagent_LDADD=$(top_builddir)/src/libqmf.la - -EXTRA_DIST+=testagent.xml diff --git a/cpp/src/tests/testagent.xml b/cpp/src/tests/testagent.xml deleted file mode 100644 index 0b1436f999..0000000000 --- a/cpp/src/tests/testagent.xml +++ /dev/null @@ -1,64 +0,0 @@ -<schema package="org.apache.qpid.agent.example"> - -<!-- - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. ---> - - <!-- - =============================================================== - Parent - =============================================================== - --> - <class name="Parent"> - - This class represents a parent object - - <property name="name" type="lstr" access="RC" index="y"/> - - <statistic name="state" type="sstr" desc="Operational state of the link"/> - <statistic name="count" type="count64" unit="tick" desc="Counter that increases monotonically"/> - - <method name="create_child" desc="Create child object"> - <arg name="name" dir="I" type="lstr"/> - <arg name="childRef" dir="O" type="objId"/> - </method> - </class> - - - <!-- - =============================================================== - Child - =============================================================== - --> - <class name="Child"> - <property name="ParentRef" type="objId" references="Parent" access="RC" index="y" parentRef="y"/> - <property name="name" type="lstr" access="RC" index="y"/> - - <statistic name="count" type="count64" unit="tick" desc="Counter that increases monotonically"/> - - <method name="delete"/> - </class> - - <eventArguments> - <arg name="childName" type="lstr"/> - </eventArguments> - - <event name="ChildCreated" args="childName"/> - <event name="ChildDestroyed" args="childName"/> -</schema> - diff --git a/cpp/src/tests/testlib.py b/cpp/src/tests/testlib.py deleted file mode 100644 index fe57a84a81..0000000000 --- a/cpp/src/tests/testlib.py +++ /dev/null @@ -1,766 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# -# Support library for qpid python tests. -# - -import os, re, signal, subprocess, time, unittest - -class TestBase(unittest.TestCase): - """ - Base class for qpid tests. Provides broker start/stop/kill methods - """ - - """ - The following environment vars control if and how the test is run, and determine where many of the helper - executables/libs are to be found. - """ - _storeLib = os.getenv("STORE_LIB") - _storeEnable = _storeLib != None # Must be True for durability to be enabled during the test - _qpiddExec = os.getenv("QPIDD_EXEC", "/usr/sbin/qpidd") - _tempStoreDir = os.path.abspath(os.getenv("TMP_DATA_DIR", "/tmp/qpid")) - - """Global message counter ensures unique messages""" - _msgCnt = 0 - - # --- Helper functions for parameter handling --- - - def _paramBool(self, key, val, keyOnly = False): - if val == None: - return "" - if keyOnly: - if val: - return " --%s" % key - else: - return "" - else: - if val: - return " --%s yes" % key - else: - return " --%s no" % key - - # --- Helper functions for message creation --- - - def _makeMessage(self, msgSize): - msg = "Message-%04d" % self._msgCnt - self._msgCnt = self._msgCnt + 1 - msgLen = len(msg) - if msgSize > msgLen: - for i in range(msgLen, msgSize): - if i == msgLen: - msg += "-" - else: - msg += chr(ord('a') + (i % 26)) - return msg - - def _makeMessageList(self, numMsgs, msgSize): - if msgSize == None: - msgSize = 12 - msgs = "" - for m in range(0, numMsgs): - msgs += "%s\n" % self._makeMessage(msgSize) - return msgs - - # --- Starting and stopping a broker --- - - def startBroker(self, qpiddArgs, logFile = None): - """Start a single broker daemon, returns tuple (pid, port)""" - if self._qpiddExec == None: - raise Exception("Environment variable QPIDD is not set") - cmd = "%s --daemon --port=0 %s" % (self._qpiddExec, qpiddArgs) - portStr = os.popen(cmd).read() - if len(portStr) == 0: - err = "Broker daemon startup failed." - if logFile != None: - err += " See log file %s" % logFile - raise Exception(err) - port = int(portStr) - pidStr = os.popen("%s -p %d -c" % (self._qpiddExec, port)).read() - try: - pid = int(pidStr) - except: - raise Exception("Unable to get pid: \"%s -p %d -c\" returned %s" % (self._qpiddExec, port, pidStr)) - #print "started broker: pid=%d, port=%d args: %s" % (pid, port, qpiddArgs) - return (pid, port) - - def killBroker(self, nodeTuple, ignoreFailures = False): - """Kill a broker using kill -9""" - try: - os.kill(nodeTuple[self.PID], signal.SIGKILL) - try: - os.waitpid(nodeTuple[self.PID], 0) - except: - pass - #print "killed broker: port=%d pid=%d" % (nodeTuple[self.PORT], nodeTuple[self.PID]) - except: - if ignoreFailures: - print "WARNING: killBroker (port=%d pid=%d) failed - ignoring." % (nodeTuple[self.PORT], nodeTuple[self.PID]) - else: - raise - - def stopBroker(self, nodeTuple, ignoreFailures = False): - """Stop a broker using qpidd -q""" - try: - ret = os.spawnl(os.P_WAIT, self._qpiddExec, self._qpiddExec, "--port=%d" % nodeTuple[self.PORT], "--quit", "--no-module-dir") - if ret != 0: - raise Exception("stopBroker(): port=%d: qpidd -q returned %d" % (nodeTuple[self.PORT], ret)) - try: - os.waitpid(nodeTuple[self.PID], 0) - except: - pass - #print "stopped broker: port=%d pid=%d" % (nodeTuple[self.PORT], nodeTuple[self.PID]) - except: - if ignoreFailures: - print "WARNING: stopBroker (port=%d pid=%d) failed - ignoring." % (nodeTuple[self.PORT], nodeTuple[self.PID]) - else: - raise - - - -class TestBaseCluster(TestBase): - """ - Base class for cluster tests. Provides methods for starting and stopping clusters and cluster nodes. - """ - - """ - The following environment vars control if and how the test is run, and determine where many of the helper - executables/libs are to be found. - """ - _clusterLib = os.getenv("CLUSTER_LIB") - _clusterTestEnable = _clusterLib != None # Must be True for these cluster tests to run - _xmlLib = os.getenv("XML_LIB") - _xmlEnable = _xmlLib != None - _qpidConfigExec = os.getenv("QPID_CONFIG_EXEC", "/usr/bin/qpid-config") - _qpidRouteExec = os.getenv("QPID_ROUTE_EXEC", "/usr/bin/qpid-route") - _receiverExec = os.getenv("RECEIVER_EXEC", "/usr/libexec/qpid/test/receiver") - _senderExec = os.getenv("SENDER_EXEC", "/usr/libexec/qpid/test/sender") - - - """ - _clusterDict is a dictionary of clusters: - key = cluster name (string) - val = dictionary of node numbers: - key = integer node number - val = tuple containing (pid, port) - For example, two clusters "TestCluster0" and "TestCluster1" containing several nodes would look as follows: - {"TestCluster0": {0: (pid0-0, port0-0), 1: (pid0-1, port0-1), ...}, "TestCluster1": {0: (pid1-0, port1-0), 1: (pid1-1, port1-1), ...}} - where pidm-n and portm-n are the int pid and port for TestCluster m node n respectively. - """ - _clusterDict = {} - - """Index for (pid, port) tuple""" - PID = 0 - PORT = 1 - - def run(self, res): - """ Skip cluster testing if env var RUN_CLUSTER_TESTS is not defined.""" - if not self._clusterTestEnable: - return - unittest.TestCase.run(self, res) - - # --- Private helper / convenience functions --- - - def _checkPids(self, clusterName = None): - for pid, port in self.getTupleList(): - try: - os.kill(pid, 0) - except: - raise Exception("_checkPids(): Broker with pid %d expected but does not exist! (crashed?)" % pid) - - - # --- Starting cluster node(s) --- - - def createClusterNode(self, nodeNumber, clusterName): - """Create a node and add it to the named cluster""" - if self._tempStoreDir == None: - raise Exception("Environment variable TMP_DATA_DIR is not set") - if self._clusterLib == None: - raise Exception("Environment variable LIBCLUSTER is not set") - name = "%s-%d" % (clusterName, nodeNumber) - dataDir = os.path.join(self._tempStoreDir, "cluster", name) - logFile = "%s.log" % dataDir - args = "--no-module-dir --load-module=%s --data-dir=%s --cluster-name=%s --auth=no --log-enable=notice+ --log-to-file=%s" % \ - (self._clusterLib, dataDir, clusterName, logFile) - if self._storeEnable: - if self._storeLib == None: - raise Exception("Environment variable LIBSTORE is not set") - args += " --load-module %s" % self._storeLib - self._clusterDict[clusterName][nodeNumber] = self.startBroker(args, logFile) - - def createCluster(self, clusterName, numberNodes = 0): - """Create a cluster containing an initial number of nodes""" - self._clusterDict[clusterName] = {} - for n in range(0, numberNodes): - self.createClusterNode(n, clusterName) - - def waitForNodes(self, clusterName): - """Wait for all nodes to become active (ie finish cluster sync)""" - # TODO - connect to each known node in cluster - # Until this is done, wait a bit (hack) - time.sleep(1) - - # --- Cluster and node status --- - - def getTupleList(self, clusterName = None): - """Get list of (pid, port) tuples of all known cluster brokers""" - tList = [] - for c, l in self._clusterDict.iteritems(): - if clusterName == None or c == clusterName: - for t in l.itervalues(): - tList.append(t) - return tList - - def getNumBrokers(self): - """Get total number of brokers in all known clusters""" - return len(self.getTupleList()) - - def checkNumBrokers(self, expected = None, checkPids = True): - """Check that the total number of brokers in all known clusters is the expected value""" - if expected != None and self.getNumBrokers() != expected: - raise Exception("Unexpected number of brokers: expected %d, found %d" % (expected, self.getNumBrokers())) - if checkPids: - self._checkPids() - - def getClusterTupleList(self, clusterName): - """Get list of (pid, port) tuples of all nodes in named cluster""" - if clusterName in self._clusterDict: - return self._clusterDict[clusterName].values() - return [] - - def getNumClusterBrokers(self, clusterName): - """Get total number of brokers in named cluster""" - return len(self.getClusterTupleList(clusterName)) - - def getNodeTuple(self, nodeNumber, clusterName): - """Get the (pid, port) tuple for the given cluster node""" - return self._clusterDict[clusterName][nodeNumber] - - def checkNumClusterBrokers(self, clusterName, expected = None, checkPids = True, waitForNodes = True): - """Check that the total number of brokers in the named cluster is the expected value""" - if expected != None and self.getNumClusterBrokers(clusterName) != expected: - raise Exception("Unexpected number of brokers in cluster %s: expected %d, found %d" % \ - (clusterName, expected, self.getNumClusterBrokers(clusterName))) - if checkPids: - self._checkPids(clusterName) - if waitForNodes: - self.waitForNodes(clusterName) - - def clusterExists(self, clusterName): - """ Return True if clusterName exists, False otherwise""" - return clusterName in self._clusterDict.keys() - - def clusterNodeExists(self, clusterName, nodeNumber): - """ Return True if nodeNumber in clusterName exists, False otherwise""" - if clusterName in self._clusterDict.keys(): - return nodeNumber in self._clusterDict[nodeName] - return False - - def createCheckCluster(self, clusterName, size): - """Create a cluster using the given name and size, then check the number of brokers""" - self.createCluster(clusterName, size) - self.checkNumClusterBrokers(clusterName, size) - - # --- Kill cluster nodes using signal 9 --- - - def killNode(self, nodeNumber, clusterName, updateDict = True, ignoreFailures = False): - """Kill the given node in the named cluster using kill -9""" - self.killBroker(self.getNodeTuple(nodeNumber, clusterName), ignoreFailures) - if updateDict: - del(self._clusterDict[clusterName][nodeNumber]) - - def killCluster(self, clusterName, updateDict = True, ignoreFailures = False): - """Kill all nodes in the named cluster""" - for n in self._clusterDict[clusterName].iterkeys(): - self.killNode(n, clusterName, False, ignoreFailures) - if updateDict: - del(self._clusterDict[clusterName]) - - def killClusterCheck(self, clusterName): - """Kill the named cluster and check that the name is removed from the cluster dictionary""" - self.killCluster(clusterName) - if self.clusterExists(clusterName): - raise Exception("Unable to kill cluster %s; %d nodes still exist" % \ - (clusterName, self.getNumClusterBrokers(clusterName))) - - def killAllClusters(self, ignoreFailures = False): - """Kill all known clusters""" - for n in self._clusterDict.iterkeys(): - self.killCluster(n, False, ignoreFailures) - self._clusterDict.clear() - - def killAllClustersCheck(self, ignoreFailures = False): - """Kill all known clusters and check that the cluster dictionary is empty""" - self.killAllClusters(ignoreFailures) - self.checkNumBrokers(0) - - # --- Stop cluster nodes using qpidd -q --- - - def stopNode(self, nodeNumber, clusterName, updateDict = True, ignoreFailures = False): - """Stop the given node in the named cluster using qpidd -q""" - self.stopBroker(self.getNodeTuple(nodeNumber, clusterName), ignoreFailures) - if updateDict: - del(self._clusterDict[clusterName][nodeNumber]) - - def stopAllClusters(self, ignoreFailures = False): - """Stop all known clusters""" - for n in self._clusterDict.iterkeys(): - self.stopCluster(n, False, ignoreFailures) - self._clusterDict.clear() - - - def stopCluster(self, clusterName, updateDict = True, ignoreFailures = False): - """Stop all nodes in the named cluster""" - for n in self._clusterDict[clusterName].iterkeys(): - self.stopNode(n, clusterName, False, ignoreFailures) - if updateDict: - del(self._clusterDict[clusterName]) - - def stopCheckCluster(self, clusterName, ignoreFailures = False): - """Stop the named cluster and check that the name is removed from the cluster dictionary""" - self.stopCluster(clusterName, True, ignoreFailures) - if self.clusterExists(clusterName): - raise Exception("Unable to kill cluster %s; %d nodes still exist" % (clusterName, self.getNumClusterBrokers(clusterName))) - - def stopAllCheck(self, ignoreFailures = False): - """Kill all known clusters and check that the cluster dictionary is empty""" - self.stopAllClusters() - self.checkNumBrokers(0) - - # --- qpid-config functions --- - - def _qpidConfig(self, nodeNumber, clusterName, action): - """Configure some aspect of a qpid broker using the qpid_config executable""" - port = self.getNodeTuple(nodeNumber, clusterName)[self.PORT] - #print "%s -a localhost:%d %s" % (self._qpidConfigExec, port, action) - ret = os.spawnl(os.P_WAIT, self._qpidConfigExec, self._qpidConfigExec, "-a", "localhost:%d" % port, *action.split()) - if ret != 0: - raise Exception("_qpidConfig(): cluster=\"%s\" nodeNumber=%d port=%d action=\"%s\" returned %d" % \ - (clusterName, nodeNumber, port, action, ret)) - - def addExchange(self, nodeNumber, clusterName, exchangeType, exchangeName, durable = False, sequence = False, \ - ive = False): - """Add a named exchange.""" - action = "add exchange %s %s" % (exchangeType, exchangeName) - action += self._paramBool("durable", durable, True) - action += self._paramBool("sequence", sequence, True) - action += self._paramBool("ive", ive, True) - self._qpidConfig(nodeNumber, clusterName, action) - - def deleteExchange(self, nodeNumber, clusterName, exchangeName): - """Delete a named exchange""" - self._qpidConfig(nodeNumber, clusterName, "del exchange %s" % exchangeName) - - def addQueue(self, nodeNumber, clusterName, queueName, configArgs = None): - """Add a queue using qpid-config.""" - action = "add queue %s" % queueName - if self._storeEnable: - action += " --durable" - if configArgs != None: - action += " %s" % configArgs - self._qpidConfig(nodeNumber, clusterName, action) - - def delQueue(self, nodeNumber, clusterName, queueName): - """Delete a named queue using qpid-config.""" - self._qpidConfig(nodeNumber, clusterName, "del queue %s" % queueName) - - def bind(self, nodeNumber, clusterName, exchangeName, queueName, key): - """Create an exchange-queue binding using qpid-config.""" - self._qpidConfig(nodeNumber, clusterName, "bind %s %s %s" % (exchangeName, queueName, key)) - - def unbind(self, nodeNumber, clusterName, exchangeName, queueName, key): - """Remove an exchange-queue binding using qpid-config.""" - self._qpidConfig(nodeNumber, clusterName, "unbind %s %s %s" % (exchangeName, queueName, key)) - - # --- qpid-route functions (federation) --- - - def brokerDict(self, nodeNumber, clusterName, host = "localhost", user = None, password = None): - """Returns a dictionary containing the broker info to be passed to route functions""" - port = self.getNodeTuple(nodeNumber, clusterName)[self.PORT] - return {"cluster": clusterName, "node":nodeNumber, "port":port, "host":host, "user":user, "password":password} - - def _brokerStr(self, brokerDict): - """Set up a broker string in the format [user/password@]host:port""" - str = "" - if brokerDict["user"] !=None and brokerDict["password"] != None: - str = "%s@%s" % (brokerDict["user"], brokerDict["password"]) - str += "%s:%d" % (brokerDict["host"], brokerDict["port"]) - return str - - def _qpidRoute(self, action): - """Set up a route using qpid-route""" - #print "%s %s" % (self._qpidRouteExec, action) - ret = os.spawnl(os.P_WAIT, self._qpidRouteExec, self._qpidRouteExec, *action.split()) - if ret != 0: - raise Exception("_qpidRoute(): action=\"%s\" returned %d" % (action, ret)) - - def routeDynamicAdd(self, destBrokerDict, srcBrokerDict, exchangeName): - self._qpidRoute("dynamic add %s %s %s" % (self._brokerStr(destBrokerDict), self._brokerStr(srcBrokerDict), exchangeName)) - - def routeDynamicDelete(self, destBrokerDict, srcBrokerDict, exchangeName): - self._qpidRoute("dynamic del %s %s %s" % (self._brokerStr(destBrokerDict), self._brokerStr(srcBrokerDict), exchangeName)) - - def routeAdd(self, destBrokerDict, srcBrokerDict, exchangeName, routingKey): - self._qpidRoute("route add %s %s %s %s" % (self._brokerStr(destBrokerDict), self._brokerStr(srcBrokerDict), exchangeName, routingKey)) - - def routeDelete(self, destBrokerDict, srcBrokerDict, exchangeName, routingKey): - self._qpidRoute("route del %s %s %s %s" % (self._brokerStr(destBrokerDict), self._brokerStr(srcBrokerDict), exchangeName, routingKey)) - - def routeQueueAdd(self, destBrokerDict, srcBrokerDict, exchangeName, queueName): - self._qpidRoute("queue add %s %s %s %s" % (self._brokerStr(destBrokerDict), self._brokerStr(srcBrokerDict), exchangeName, queueName)) - - def routeQueueDelete(self, destBrokerDict, srcBrokerDict, exchangeName, queueName): - self._qpidRoute("queue del %s %s %s %s" % (self._brokerStr(destBrokerDict), self._brokerStr(srcBrokerDict), exchangeName, queueName)) - - def routeLinkAdd(self, destBrokerDict, srcBrokerDict): - self._qpidRoute("link add %s %s" % (self._brokerStr(destBrokerDict), self._brokerStr(srcBrokerDict))) - - def routeLinkDelete(self, destBrokerDict, srcBrokerDict): - self._qpidRoute("link del %s %s" % (self._brokerStr(destBrokerDict), self._brokerStr(srcBrokerDict))) - - # --- Message send and receive functions --- - - def _receiver(self, action): - if self._receiverExec == None: - raise Exception("Environment variable RECEIVER is not set") - cmd = "%s %s" % (self._receiverExec, action) - #print cmd - return subprocess.Popen(cmd.split(), stdout = subprocess.PIPE) - - def _sender(self, action): - if self._senderExec == None: - raise Exception("Environment variable SENDER is not set") - cmd = "%s %s" % (self._senderExec, action) - #print cmd - return subprocess.Popen(cmd.split(), stdin = subprocess.PIPE) - - def createReciever(self, nodeNumber, clusterName, queueName, numMsgs = None, receiverArgs = None): - port = self.getNodeTuple(nodeNumber, clusterName)[self.PORT] - action = "--port %d --queue %s" % (port, queueName) - if numMsgs != None: - action += " --messages %d" % numMsgs - if receiverArgs != None: - action += " %s" % receiverArgs - return self._receiver(action) - - def createSender(self, nodeNumber, clusterName, exchangeName, routingKey, senderArgs = None): - port = self.getNodeTuple(nodeNumber, clusterName)[self.PORT] - action = "--port %d --exchange %s" % (port, exchangeName) - if routingKey != None and len(routingKey) > 0: - action += " --routing-key %s" % routingKey - if self._storeEnable: - action += " --durable yes" - if senderArgs != None: - action += " %s" % senderArgs - return self._sender(action) - - def createBindDirectExchangeQueue(self, nodeNumber, clusterName, exchangeName, queueName): - self.addExchange(nodeNumber, clusterName, "direct", exchangeName) - self.addQueue(nodeNumber, clusterName, queueName) - self.bind(nodeNumber, clusterName, exchangeName, queueName, queueName) - - def createBindTopicExchangeQueues(self, nodeNumber, clusterName, exchangeName, queueNameKeyList): - self.addExchange(nodeNumber, clusterName, "topic", exchangeName) - for queueName, key in queueNameKeyList.iteritems(): - self.addQueue(nodeNumber, clusterName, queueName) - self.bind(nodeNumber, clusterName, exchangeName, queueName, key) - - def createBindFanoutExchangeQueues(self, nodeNumber, clusterName, exchangeName, queueNameList): - self.addExchange(nodeNumber, clusterName, "fanout", exchangeName) - for queueName in queueNameList: - self.addQueue(nodeNumber, clusterName, queueName) - self.bind(nodeNumber, clusterName, exchangeName, queueName, "") - - def sendMsgs(self, nodeNumber, clusterName, exchangeName, routingKey, numMsgs, msgSize = None, wait = True): - msgs = self._makeMessageList(numMsgs, msgSize) - sender = self.createSender(nodeNumber, clusterName, exchangeName, routingKey) - sender.stdin.write(msgs) - sender.stdin.close() - if wait: - sender.wait() - return msgs - - def receiveMsgs(self, nodeNumber, clusterName, queueName, numMsgs, wait = True): - receiver = self.createReciever(nodeNumber, clusterName, queueName, numMsgs) - cnt = 0 - msgs = "" - while cnt < numMsgs: - rx = receiver.stdout.readline() - if rx == "" and receiver.poll() != None: break - msgs += rx - cnt = cnt + 1 - if wait: - receiver.wait() - return msgs - - - # --- Exchange-specific helper inner classes --- - - class TestHelper: - """ - This is a "virtual" superclass for test helpers, and is not useful on its own, but the - per-exchange subclasses are designed to keep track of the messages sent to and received - from queues which have bindings to that exchange type. - """ - - def __init__(self, testBaseCluster, clusterName, numNodes, exchangeName, queueNameList): - - """Dictionary of queues and lists of messages sent to them.""" - self._txMsgs = {} - """Dictionary of queues and lists of messages received from them.""" - self._rxMsgs = {} - """List of node numbers currently in the cluster""" - self._nodes = [] - """List of node numbers which have been killed and can therefore be recovered""" - self._deadNodes = [] - """Last node to be used""" - self._lastNode = None - - self._testBaseCluster = testBaseCluster - self._clusterName = clusterName - self._exchangeName = exchangeName - self._queueNameList = queueNameList - self._addQueues(queueNameList) - self._testBaseCluster.createCheckCluster(clusterName, numNodes) - self._nodes.extend(range(0, numNodes)) - - def _addQueues(self, queueNameList): - for qn in queueNameList: - if not qn in self._txMsgs: - self._txMsgs[qn] = [] - if not qn in self._rxMsgs: - self._rxMsgs[qn] = [] - - def _bindQueue(self, queueName, bindingKey, nodeNumber = None): - """Bind a queue to an exchange using a binding key.""" - if nodeNumber == None: - nodeNumber = self._nodes[0] # first available node - self._testBaseCluster.addQueue(nodeNumber, self._clusterName, queueName) - self._testBaseCluster.bind(nodeNumber, self._clusterName, self._exchangeName, queueName, bindingKey) - - def _highestNodeNumber(self): - """Find the highest node number used so far between the current nodes and those stopped/killed.""" - highestNode = self._nodes[-1] - if len(self._deadNodes) == 0: - return highestNode - highestDeadNode = self._deadNodes[-1] - if highestNode > highestDeadNode: - return highestNode - return highestDeadNode - - def killCluster(self): - """Kill all nodes in the cluster""" - self._testBaseCluster.killCluster(self._clusterName) - self._testBaseCluster.checkNumClusterBrokers(self._clusterName, 0) - self._deadNodes.extend(self._nodes) - self._deadNodes.sort() - del self._nodes[:] - - def restoreCluster(self, lastNode = None, restoreNodes = True): - """Restore a previously killed cluster""" - self._testBaseCluster.createCluster(self._clusterName) - if restoreNodes: - numNodes = len(self._deadNodes) - self.restoreNodes(lastNode) - self._testBaseCluster.checkNumClusterBrokers(self._clusterName, numNodes) - - def addNodes(self, numberOfNodes = 1): - """Add a fixed number of nodes to the cluster.""" - nodeStart = self._highestNodeNumber() + 1 - for i in range(0, numberOfNodes): - nodeNumber = nodeStart + i - self._testBaseCluster.createClusterNode(nodeNumber, self._clusterName) - self._nodes.append(nodeNumber) - self._testBaseCluster.checkNumClusterBrokers(self._clusterName, len(self._nodes)) - self._testBaseCluster.waitForNodes(self._clusterName) - - def restoreNode(self, nodeNumber): - """Restore a cluster node that has been previously killed""" - if nodeNumber not in self._deadNodes: - raise Exception("restoreNode(): Node number %d not in dead node list %s" % (nodeNumber, self._deadNodes)) - self._testBaseCluster.createClusterNode(nodeNumber, self._clusterName) - self._deadNodes.remove(nodeNumber) - self._nodes.append(nodeNumber) - self._nodes.sort() - - def restoreNodes(self, lastNode = None): - """Restore all known cluster nodes that have been previously killed starting with a known last-used node""" - if len(self._nodes) == 0: # restore last-used node first - if lastNode == None: - lastNode = self._lastNode - self.restoreNode(lastNode) - while len(self._deadNodes) > 0: - self.restoreNode(self._deadNodes[0]) - self._testBaseCluster.waitForNodes(self._clusterName) - - def killNode(self, nodeNumber): - """Kill a cluster node (if it is in the _nodes list).""" - if nodeNumber not in self._nodes: - raise Exception("killNode(): Node number %d not in node list %s" % (nodeNumber, self._nodes)) - self._testBaseCluster.killNode(nodeNumber, self._clusterName) - self._nodes.remove(nodeNumber) - self._deadNodes.append(nodeNumber) - self._deadNodes.sort() - - def sendMsgs(self, routingKey, numMsgs, nodeNumber = None, msgSize = None, wait = True): - """Send a fixed number of messages using the given routing key.""" - if nodeNumber == None: - nodeNumber = self._nodes[0] # Use first available node - msgs = self._testBaseCluster._makeMessageList(numMsgs, msgSize) - sender = self._testBaseCluster.createSender(nodeNumber, self._clusterName, self._exchangeName, routingKey) - sender.stdin.write(msgs) - sender.stdin.close() - if wait: - sender.wait() - self._lastNode = nodeNumber - return msgs.split() - - # TODO - this i/f is messy: one mumMsgs can be given, but a list of queues - # so assuming numMsgs for each queue - # A mechanism is needed to specify a different numMsgs per queue - def receiveMsgs(self, numMsgs, nodeNumber = None, queueNameList = None, wait = True): - """Receive a fixed number of messages from a named queue. If numMsgs == None, get all remaining messages.""" - if nodeNumber == None: - nodeNumber = self._nodes[0] # Use first available node - if queueNameList == None: - queueNameList = self._txMsgs.iterkeys() - for qn in queueNameList: - nm = numMsgs - if nm == None: - nm = len(self._txMsgs[qn]) - len(self._rxMsgs[qn]) # get all remaining messages - if nm > 0: - while nm > 0: - receiver = self._testBaseCluster.createReciever(nodeNumber, self._clusterName, qn, nm) - cnt = 0 - while cnt < nm: - rx = receiver.stdout.readline().strip() - if rx == "": - if receiver.poll() != None: break - elif rx not in self._rxMsgs[qn]: - self._rxMsgs[qn].append(rx) - cnt = cnt + 1 - nm = nm - cnt - if wait: - receiver.wait() - self._rxMsgs[qn].sort() - self._lastNode = nodeNumber - - def receiveRemainingMsgs(self, nodeNumber = None, queueNameList = None, wait = True): - """Receive all remaining messages on named queue.""" - self.receiveMsgs(None, nodeNumber, queueNameList, wait) - - def checkMsgs(self): - """Return True if all expected messages have been received (ie the transmit and receive list are identical).""" - txMsgTot = 0 - rxMsgTot = 0 - for qn, txMsgList in self._txMsgs.iteritems(): - rxMsgList = self._rxMsgs[qn] - txMsgTot = txMsgTot + len(txMsgList) - rxMsgTot = rxMsgTot + len(rxMsgList) - if len(txMsgList) != len(rxMsgList): - return False - for i, m in enumerate(txMsgList): - if m != rxMsgList[i]: - return False - if txMsgTot == 0 and rxMsgTot == 0: - print "WARNING: No messages were either sent or received" - return True - - def finalizeTest(self): - """Recover all the remaining messages on all queues, then check that all expected messages were received.""" - self.receiveRemainingMsgs() - self._testBaseCluster.stopAllCheck() - if not self.checkMsgs(): - self.printMsgs() - self._testBaseCluster.fail("Send - receive message mismatch") - - def printMsgs(self, txMsgs = True, rxMsgs = True): - """Print all messages transmitted and received.""" - for qn, txMsgList in self._txMsgs.iteritems(): - print "Queue: %s" % qn - if txMsgs: - print " txMsgList = %s" % txMsgList - if rxMsgs: - rxMsgList = self._rxMsgs[qn] - print " rxMsgList = %s" % rxMsgList - - - class DirectExchangeTestHelper(TestHelper): - - def __init__(self, testBaseCluster, clusterName, numNodes, exchangeName, queueNameList): - TestBaseCluster.TestHelper.__init__(self, testBaseCluster, clusterName, numNodes, exchangeName, queueNameList) - self._testBaseCluster.addExchange(0, clusterName, "direct", exchangeName) - for qn in queueNameList: - self._bindQueue(qn, qn) - - def addQueues(self, queueNameList): - self._addQueues(queueNameList) - for qn in queueNameList: - self._bindQueue(qn, qn) - - def sendMsgs(self, numMsgs, nodeNumber = None, queueNameList = None, msgSize = None, wait = True): - if queueNameList == None: - queueNameList = self._txMsgs.iterkeys() - for qn in queueNameList: - self._txMsgs[qn].extend(TestBaseCluster.TestHelper.sendMsgs(self, qn, numMsgs, nodeNumber, msgSize, wait)) - - - class TopicExchangeTestHelper(TestHelper): - - def __init__(self, testBaseCluster, clusterName, numNodes, exchangeName, queueNameKeyList): - self._queueNameKeyList = queueNameKeyList - TestBaseCluster.TestHelper.__init__(self, testBaseCluster, clusterName, numNodes, exchangeName, queueNameKeyList.iterkeys()) - self._testBaseCluster.addExchange(0, clusterName, "topic", exchangeName) - for qn, bk in queueNameKeyList.iteritems(): - self._bindQueue(qn, bk) - - def addQueues(self, queueNameKeyList): - self._addQueues(queueNameKeyList.iterkeys()) - for qn, bk in queueNameKeyList.iteritems(): - self._bindQueue(qn, bk) - - def _prepareRegex(self, bk): - # This regex conversion is not very complete - there are other chars that should be escaped too - return "^%s$" % bk.replace(".", r"\.").replace("*", r"[^.]*").replace("#", ".*") - - def sendMsgs(self, routingKey, numMsgs, nodeNumber = None, msgSize = None, wait = True): - msgList = TestBaseCluster.TestHelper.sendMsgs(self, routingKey, numMsgs, nodeNumber, msgSize, wait) - for qn, bk in self._queueNameKeyList.iteritems(): - if re.match(self._prepareRegex(bk), routingKey): - self._txMsgs[qn].extend(msgList) - - - class FanoutExchangeTestHelper(TestHelper): - - def __init__(self, testBaseCluster, clusterName, numNodes, exchangeName, queueNameList): - TestBaseCluster.TestHelper.__init__(self, testBaseCluster, clusterName, numNodes, exchangeName, queueNameList) - self._testBaseCluster.addExchange(0, clusterName, "fanout", exchangeName) - for qn in queueNameList: - self._bindQueue(qn, "") - - def addQueues(self, queueNameList): - self._addQueues(queueNameList) - for qn in queueNameList: - self._bindQueue(qn, "") - - def sendMsgs(self, numMsgs, nodeNumber = None, msgSize = None, wait = True): - msgList = TestBaseCluster.TestHelper.sendMsgs(self, "", numMsgs, nodeNumber, msgSize, wait) - for ml in self._txMsgs.itervalues(): - ml.extend(msgList) - diff --git a/cpp/src/tests/topic_perftest b/cpp/src/tests/topic_perftest deleted file mode 100755 index cd440b2458..0000000000 --- a/cpp/src/tests/topic_perftest +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -exec `dirname $0`/run_perftest 10000 --mode topic --qt 16 diff --git a/cpp/src/tests/topictest b/cpp/src/tests/topictest deleted file mode 100755 index 257c24bd81..0000000000 --- a/cpp/src/tests/topictest +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Run the C++ topic test - -# Clean up old log files -rm -f subscriber_*.log - -# Defaults values -SUBSCRIBERS=10 -MESSAGES=2000 -BATCHES=10 - -while getopts "s:m:b:h:t" opt ; do - case $opt in - s) SUBSCRIBERS=$OPTARG ;; - m) MESSAGES=$OPTARG ;; - b) BATCHES=$OPTARG ;; - h) HOST=-h$OPTARG ;; - t) TRANSACTIONAL="--transactional --durable" ;; - ?) - echo "Usage: %0 [-s <subscribers>] [-m <messages.] [-b <batches>]" - exit 1 - ;; - esac -done - -subscribe() { - echo Start subscriber $1 - LOG="subscriber_$1.log" - ./qpid-topic-listener $TRANSACTIONAL > $LOG 2>&1 && rm -f $LOG -} - -publish() { - ./qpid-topic-publisher --messages $MESSAGES --batches $BATCHES --subscribers $SUBSCRIBERS $HOST $TRANSACTIONAL -} - -for ((i=$SUBSCRIBERS ; i--; )); do - subscribe $i & -done -# FIXME aconway 2007-03-27: Hack around startup race. Fix topic test. -sleep 2 -publish 2>&1 || exit 1 diff --git a/cpp/src/tests/topictest.ps1 b/cpp/src/tests/topictest.ps1 deleted file mode 100644 index 59a483c2d5..0000000000 --- a/cpp/src/tests/topictest.ps1 +++ /dev/null @@ -1,73 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Parameters with default values: s (subscribers) m (messages) b (batches) -# h (host) t (false; use transactions) -param ( - [int]$subscribers = 10, - [int]$message_count = 2000, - [int]$batches = 10, - [string]$broker, - [switch] $t # transactional -) - -# Run the C++ topic test -[string]$me = $myInvocation.InvocationName -$srcdir = Split-Path $me -#$srcdir = Split-Path $myInvocation.InvocationName - -# Clean up old log files -Get-Item subscriber_*.log | Remove-Item - -if ($t) { - $transactional = "--transactional --durable" -} - -# Find which subdir the exes are in -. $srcdir\find_prog.ps1 .\topic_listener.exe - -function subscribe { - param ([int]$num, [string]$sub) - "Start subscriber $num" - $LOG = "subscriber_$num.log" - $cmdline = ".\$sub\topic_listener $transactional > $LOG 2>&1 - if (`$LastExitCode -ne 0) { Remove-Item $LOG }" - $cmdblock = $executioncontext.invokecommand.NewScriptBlock($cmdline) - . $srcdir\background.ps1 $cmdblock -} - -function publish { - param ([string]$sub) - Invoke-Expression ".\$sub\topic_publisher --messages $message_count --batches $batches --subscribers $subscribers $host $transactional" 2>&1 -} - -if ($broker.length) { - $broker = "-h$broker" -} - -$i = $subscribers -while ($i -gt 0) { - subscribe $i $sub - $i-- -} - -# FIXME aconway 2007-03-27: Hack around startup race. Fix topic test. -Start-Sleep 2 -publish $sub -exit $LastExitCode diff --git a/cpp/src/tests/txjob.cpp b/cpp/src/tests/txjob.cpp deleted file mode 100644 index a7a905c1b7..0000000000 --- a/cpp/src/tests/txjob.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <iostream> -#include <boost/bind.hpp> -#include <boost/ptr_container/ptr_vector.hpp> - -#include "TestOptions.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/FailoverManager.h" -#include "qpid/client/Message.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/sys/Thread.h" - -using namespace qpid::client; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -struct Args : public qpid::TestOptions -{ - string workQueue; - string source; - string dest; - uint messages; - uint jobs; - bool quit; - bool declareQueues; - - Args() : workQueue("txshift-control"), source("txshift-1"), dest("txshift-2"), messages(0), jobs(0), - quit(false), declareQueues(false) - { - addOptions() - ("messages", qpid::optValue(messages, "N"), "Number of messages to shift") - ("jobs", qpid::optValue(jobs, "N"), "Number of shift jobs to request") - ("source", qpid::optValue(source, "QUEUE NAME"), "source queue from which messages will be shifted") - ("dest", qpid::optValue(dest, "QUEUE NAME"), "dest queue to which messages will be shifted") - ("work-queue", qpid::optValue(workQueue, "QUEUE NAME"), "work queue from which to take instructions") - ("add-quit", qpid::optValue(quit), "add a 'quit' instruction to the queue (after any other jobs)") - ("declare-queues", qpid::optValue(declareQueues), "issue a declare for all queues"); - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -//TODO: might be nice to make this capable of failover as well at some -//point; for now its just for the setup phase. -int main(int argc, char** argv) -{ - Args opts; - try { - opts.parse(argc, argv); - Connection connection; - connection.open(opts.con); - Session session = connection.newSession(); - if (opts.declareQueues) { - session.queueDeclare(arg::queue=opts.workQueue); - session.queueDeclare(arg::queue=opts.source); - session.queueDeclare(arg::queue=opts.dest); - } - for (uint i = 0; i < opts.jobs; ++i) { - Message job("transfer", opts.workQueue); - job.getHeaders().setString("src", opts.source); - job.getHeaders().setString("dest", opts.dest); - job.getHeaders().setInt("count", opts.messages); - async(session).messageTransfer(arg::content=job); - } - - if (opts.quit) { - async(session).messageTransfer(arg::content=Message("quit", opts.workQueue)); - } - - session.sync(); - session.close(); - - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - return 1; - } -} diff --git a/cpp/src/tests/txshift.cpp b/cpp/src/tests/txshift.cpp deleted file mode 100644 index 882d3716d8..0000000000 --- a/cpp/src/tests/txshift.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <iostream> -#include <boost/bind.hpp> -#include <boost/ptr_container/ptr_vector.hpp> - -#include "TestOptions.h" -#include "qpid/client/AsyncSession.h" -#include "qpid/client/FailoverManager.h" -#include "qpid/client/Message.h" -#include "qpid/client/SubscriptionManager.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Thread.h" - -using namespace qpid::client; -using namespace qpid::sys; - -namespace qpid { -namespace tests { - -struct Args : public qpid::TestOptions -{ - string workQueue; - size_t workers; - - Args() : workQueue("txshift-control"), workers(1) - { - addOptions() - ("workers", qpid::optValue(workers, "N"), "Number of separate worker sessions to start") - ("work-queue", qpid::optValue(workQueue, "NAME"), "work queue from which to take instructions"); - } -}; - -struct Transfer : MessageListener -{ - std::string control; - std::string source; - std::string destination; - uint expected; - uint transfered; - SubscriptionSettings controlSettings; - Subscription controlSubscription; - SubscriptionSettings sourceSettings; - Subscription sourceSubscription; - - Transfer(const std::string control_) : control(control_), expected(0), transfered(0) {} - - void subscribeToSource(SubscriptionManager manager) - { - sourceSettings.autoAck = 0;//will accept once at the end of the batch - sourceSettings.flowControl = FlowControl::messageCredit(expected); - sourceSubscription = manager.subscribe(*this, source, sourceSettings); - QPID_LOG(info, "Subscribed to source: " << source << " expecting: " << expected); - } - - void subscribeToControl(SubscriptionManager manager) - { - controlSettings.flowControl = FlowControl::messageCredit(1); - controlSubscription = manager.subscribe(*this, control, controlSettings); - QPID_LOG(info, "Subscribed to job queue"); - } - - void received(Message& message) - { - QPID_LOG(debug, "received: " << message.getData() << " for " << message.getDestination()); - if (message.getDestination() == source) { - receivedFromSource(message); - } else if (message.getDestination() == control) { - receivedFromControl(message); - } else { - QPID_LOG(error, "Unexpected message: " << message.getData() << " to " << message.getDestination()); - } - } - - void receivedFromSource(Message& message) - { - QPID_LOG(debug, "transfering " << (transfered+1) << " of " << expected); - message.getDeliveryProperties().setRoutingKey(destination); - async(sourceSubscription.getSession()).messageTransfer(arg::content=message); - if (++transfered == expected) { - QPID_LOG(info, "completed job: " << transfered << " messages shifted from " << - source << " to " << destination); - sourceSubscription.accept(sourceSubscription.getUnaccepted()); - sourceSubscription.getSession().txCommit(); - sourceSubscription.cancel(); - //grant credit to allow broker to send us another control message - controlSubscription.grantMessageCredit(1); - } - } - - void receivedFromControl(Message& message) - { - if (message.getData() == "transfer") { - source = message.getHeaders().getAsString("src"); - destination = message.getHeaders().getAsString("dest"); - expected = message.getHeaders().getAsInt("count"); - transfered = 0; - QPID_LOG(info, "received transfer request: " << expected << " messages to be shifted from " << - source << " to " << destination); - subscribeToSource(controlSubscription.getSubscriptionManager()); - } else if (message.getData() == "quit") { - QPID_LOG(info, "received quit request"); - controlSubscription.cancel(); - } else { - std::cerr << "Rejecting invalid message: " << message.getData() << std::endl; - controlSubscription.getSession().messageReject(SequenceSet(message.getId())); - } - } - -}; - -struct Worker : FailoverManager::Command, Runnable -{ - FailoverManager& connection; - Transfer transfer; - Thread runner; - - Worker(FailoverManager& c, const std::string& controlQueue) : connection(c), transfer(controlQueue) {} - - void run() - { - connection.execute(*this); - } - - void start() - { - runner = Thread(this); - } - - void join() - { - runner.join(); - } - - void execute(AsyncSession& session, bool isRetry) - { - if (isRetry) QPID_LOG(info, "Retrying..."); - session.txSelect(); - SubscriptionManager subs(session); - transfer.subscribeToControl(subs); - subs.run(); - session.txCommit();//commit accept of control messages - } -}; - -}} // namespace qpid::tests - -using namespace qpid::tests; - -int main(int argc, char** argv) -{ - Args opts; - try { - opts.parse(argc, argv); - FailoverManager connection(opts.con); - connection.connect(); - if (opts.workers == 1) { - Worker worker(connection, opts.workQueue); - worker.run(); - } else { - boost::ptr_vector<Worker> workers; - for (size_t i = 0; i < opts.workers; i++) { - workers.push_back(new Worker(connection, opts.workQueue)); - } - std::for_each(workers.begin(), workers.end(), boost::bind(&Worker::start, _1)); - std::for_each(workers.begin(), workers.end(), boost::bind(&Worker::join, _1)); - } - - return 0; - } catch(const std::exception& e) { - std::cout << e.what() << std::endl; - return 1; - } -} diff --git a/cpp/src/tests/unit_test.cpp b/cpp/src/tests/unit_test.cpp deleted file mode 100644 index 00c61242e4..0000000000 --- a/cpp/src/tests/unit_test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// Defines test_main function to link with actual unit test code. -#define BOOST_AUTO_TEST_MAIN // Boost 1.33 -#define BOOST_TEST_MAIN -#include "unit_test.h" - diff --git a/cpp/src/tests/unit_test.h b/cpp/src/tests/unit_test.h deleted file mode 100644 index ed9623bcc0..0000000000 --- a/cpp/src/tests/unit_test.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef QPIPD_TEST_UNIT_TEST_H_ -#define QPIPD_TEST_UNIT_TEST_H_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// Workaround so we can build against boost 1.33 and boost 1.34. -// Remove when we no longer need to support 1.33. -// -#include <boost/version.hpp> -#include <limits.h> // Must be inclued beofre boost/test headers. - -// #include the correct header file. -// -#if (BOOST_VERSION < 103400) -# include <boost/test/auto_unit_test.hpp> -#else -# include <boost/test/unit_test.hpp> -#endif // BOOST_VERSION - -// Workarounds for BOOST_AUTO_TEST_CASE|SUITE|SUITE_END -// -#if (BOOST_VERSION < 103300) - -# define QPID_AUTO_TEST_SUITE(name) -# define QPID_AUTO_TEST_CASE(name) BOOST_AUTO_UNIT_TEST(name) -# define QPID_AUTO_TEST_SUITE_END() - -#elif (BOOST_VERSION < 103400) -// Note the trailing ';' -# define QPID_AUTO_TEST_SUITE(name) BOOST_AUTO_TEST_SUITE(name); -# define QPID_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END(); - -#endif // Workarounds for BOOST_AUTO_TEST_CASE|SUITE|SUITE_END - -// -// Default definitions for latest version of boost. -// - -#ifndef QPID_AUTO_TEST_SUITE -# define QPID_AUTO_TEST_SUITE(name) BOOST_AUTO_TEST_SUITE(name) -#endif - -#ifndef QPID_AUTO_TEST_CASE -# define QPID_AUTO_TEST_CASE(name) BOOST_AUTO_TEST_CASE(name) -#endif - -#ifndef QPID_AUTO_TEST_SUITE_END -# define QPID_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END() -#endif - -#endif // !QPIPD_TEST_UNIT_TEST_H_ diff --git a/cpp/src/tests/verify_cluster_objects b/cpp/src/tests/verify_cluster_objects deleted file mode 100755 index 94661cf6b9..0000000000 --- a/cpp/src/tests/verify_cluster_objects +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Verify managment objects are consistent in a cluster. -# Arguments: url of one broker in the cluster. - -import qmf.console, sys, re - -class Session(qmf.console.Session): - """A qmf.console.Session that caches useful values""" - - def __init__(self): - qmf.console.Session.__init__(self) - self.classes = None - - def all_classes(self): - if self.classes is None: - self.classes = [c for p in self.getPackages() for c in self.getClasses(p)] - return self.classes - -class Broker: - def __init__(self, url, qmf): - self.url = url - self.qmf = qmf - self.broker = self.qmf.addBroker(url) - self.broker._waitForStable() - self.objects = None - self.ignore_list = [ re.compile("org.apache.qpid.broker:system:") ] - - def get_objects(self): - def ignore(name): - for m in self.ignore_list: - if m.match(name): return True - if self.objects is None: - obj_list = [] - ignored=0 - for c in self.qmf.all_classes(): - for o in self.qmf.getObjects(_key=c, _broker=self.broker): - name=o.getObjectId().getObject() - if not ignore(name): obj_list.append(name) - else: ignored += 1 - self.objects = set(obj_list) - if (len(obj_list) != len(self.objects)): - raise Exception("Duplicates in object list for %s"%(self.url)) - print "%d objects on %s, ignored %d."%(len(self.objects), self.url, ignored) - return self.objects - - def compare(self,other): - def compare1(x,y): - diff = x.get_objects() - y.get_objects() - if diff: - print "ERROR: found on %s but not %s"%(x, y) - for o in diff: print " %s"%(o) - return False - return True - - so = compare1(self, other) - os = compare1(other, self) - return so and os - - def __str__(self): return self.url - - def get_cluster(self): - """Given one Broker, return list of all brokers in its cluster""" - clusters = self.qmf.getObjects(_class="cluster") - if not clusters: raise ("%s is not a cluster member"%(self.url)) - def first_address(url): - """Python doesn't understand the brokers URL syntax. Extract a simple addres""" - return re.compile("amqp:tcp:([^,]*)").match(url).group(1) - return [Broker(first_address(url), self.qmf) - for url in clusters[0].members.split(";")] - - def __del__(self): self.qmf.delBroker(self.broker) - -def main(argv=None): - if argv is None: argv = sys.argv - qmf = Session() - brokers = Broker(argv[1], qmf).get_cluster() - print "%d members in cluster."%(len(brokers)) - base = brokers.pop(0) - try: - for b in brokers: - if not base.compare(b): return 1 - print "No differences." - return 0 - finally: - del base - del brokers - -if __name__ == "__main__": sys.exit(main()) diff --git a/cpp/src/tests/vg_check b/cpp/src/tests/vg_check deleted file mode 100644 index 462f4cb5e4..0000000000 --- a/cpp/src/tests/vg_check +++ /dev/null @@ -1,43 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Check for valgrind errors. Sourced by test scripts. - -vg_failed() { - echo "Valgrind error log in $VG_LOG." 1>&2 - cat $VG_LOG 1>&2 - echo $1 1>&2 - exit 1 -} - -vg_check() -{ - test -z "$1" || VG_LOG=$1 - test -f $VG_LOG || vg_failed Valgrind log file $VG_LOG missing. - # Ensure there is an ERROR SUMMARY line. - grep -E '^==[0-9]+== ERROR SUMMARY:' $VG_LOG > /dev/null || \ - vg_failed "No valgrind ERROR SUMMARY line in $VG_LOG." - # Ensure that the number of errors is 0. - grep -E '^==[0-9]+== ERROR SUMMARY: [^0]' $VG_LOG > /dev/null && \ - vg_failed "Valgrind reported errors in $VG_LOG; see above." - # Check for leaks. - grep -E '^==[0-9]+== +.* lost: [^0]' $VG_LOG && \ - vg_failed "Found memory leaks (see log file, $VG_LOG); see above." - true -} diff --git a/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp b/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp deleted file mode 100644 index 024f20b147..0000000000 --- a/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// This file intends to prevent Windows from throwing up error boxes and -// offering to debug when serious errors happen. The errors are displayed -// on stderr instead. The purpose of this is to allow the tests to proceed -// scripted and catch the text for logging. If this behavior is desired, -// include this file with the executable being built. If the default -// behaviors are desired, don't include this file in the build. - -#if defined(_MSC_VER) -#include <crtdbg.h> -#endif -#include <windows.h> -#include <iostream> - -namespace { - -// Instead of popping up a window for exceptions, just print something out -LONG _stdcall UnhandledExceptionFilter (PEXCEPTION_POINTERS pExceptionInfo) -{ - DWORD dwExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode; - - if (dwExceptionCode == EXCEPTION_ACCESS_VIOLATION) - std::cerr << "\nERROR: ACCESS VIOLATION\n" << std::endl; - else - std::cerr << "\nERROR: UNHANDLED EXCEPTION\n" << std::endl; - - return EXCEPTION_EXECUTE_HANDLER; -} - -struct redirect_errors_to_stderr { - redirect_errors_to_stderr (); -}; - -static redirect_errors_to_stderr block; - -redirect_errors_to_stderr::redirect_errors_to_stderr() -{ -#if defined(_MSC_VER) - _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE); - _CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR); - _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR); - _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR); -#endif - - // Prevent the system from displaying the critical-error-handler - // and can't-open-file message boxes. - SetErrorMode(SEM_FAILCRITICALERRORS); - SetErrorMode(SEM_NOOPENFILEERRORBOX); - - // And this will catch all unhandled exceptions. - SetUnhandledExceptionFilter (&UnhandledExceptionFilter); -} - -} // namespace diff --git a/cpp/src/windows/QpiddBroker.cpp b/cpp/src/windows/QpiddBroker.cpp deleted file mode 100644 index 50bb45979c..0000000000 --- a/cpp/src/windows/QpiddBroker.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#else -// These need to be made something sensible, like reading a value from -// the registry. But for now, get things going with a local definition. -namespace { -const char *QPIDD_CONF_FILE = "qpid_broker.conf"; -const char *QPIDD_MODULE_DIR = "."; -} -#endif -#include "qpidd.h" -#include "qpid/Exception.h" -#include "qpid/Options.h" -#include "qpid/Plugin.h" -#include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/windows/check.h" -#include "qpid/broker/Broker.h" - -#include <iostream> -#include <windows.h> - -using namespace qpid::broker; - -BootstrapOptions::BootstrapOptions(const char* argv0) - : qpid::Options("Options"), - common("", QPIDD_CONF_FILE), - module(QPIDD_MODULE_DIR), - log(argv0) -{ - add(common); - add(module); - add(log); -} - -// Local functions to set and get the pid via a LockFile. -namespace { - -const std::string TCP = "tcp"; - -// ShutdownEvent maintains an event that can be used to ask the broker -// to stop. Analogous to sending SIGTERM/SIGINT to the posix broker. -// The signal() method signals the event. -class ShutdownEvent { - public: - ShutdownEvent(int port); - ~ShutdownEvent(); - - void create(); - void open(); - void signal(); - - private: - std::string eventName; - - protected: - HANDLE event; -}; - -class ShutdownHandler : public ShutdownEvent, public qpid::sys::Runnable { - public: - ShutdownHandler(int port, const boost::intrusive_ptr<Broker>& b) - : ShutdownEvent(port) { broker = b; } - - private: - virtual void run(); // Inherited from Runnable - boost::intrusive_ptr<Broker> broker; -}; - -ShutdownEvent::ShutdownEvent(int port) : event(NULL) { - std::ostringstream name; - name << "qpidd_" << port << std::ends; - eventName = name.str(); -} - -void ShutdownEvent::create() { - // Auto-reset event in case multiple processes try to signal a - // broker that doesn't respond for some reason. Initially not signaled. - event = ::CreateEvent(NULL, false, false, eventName.c_str()); - QPID_WINDOWS_CHECK_NULL(event); -} - -void ShutdownEvent::open() { - // TODO: Might need to search Global\\ name if unadorned name fails - event = ::OpenEvent(EVENT_MODIFY_STATE, false, eventName.c_str()); - QPID_WINDOWS_CHECK_NULL(event); -} - -ShutdownEvent::~ShutdownEvent() { - ::CloseHandle(event); - event = NULL; -} - -void ShutdownEvent::signal() { - QPID_WINDOWS_CHECK_NOT(::SetEvent(event), 0); -} - - -void ShutdownHandler::run() { - if (event == NULL) - return; - ::WaitForSingleObject(event, INFINITE); - if (broker.get()) { - broker->shutdown(); - broker = 0; // Release the broker reference - } -} - -// Console control handler to properly handle ctl-c. -int ourPort; -BOOL CtrlHandler(DWORD ctl) -{ - ShutdownEvent shutter(ourPort); // We have to have set up the port before interrupting - shutter.open(); - shutter.signal(); - return ((ctl == CTRL_C_EVENT || ctl == CTRL_CLOSE_EVENT) ? TRUE : FALSE); -} - -template <typename T> -class NamedSharedMemory { - std::string name; - HANDLE memory; - T* data; - -public: - NamedSharedMemory(const std::string&); - ~NamedSharedMemory(); - - T& create(); - T& get(); -}; - -template <typename T> -NamedSharedMemory<T>::NamedSharedMemory(const std::string& n) : - name(n), - memory(NULL), - data(0) -{} - -template <typename T> -NamedSharedMemory<T>::~NamedSharedMemory() { - if (data) - ::UnmapViewOfFile(data); - if (memory != NULL) - ::CloseHandle(memory); -} - -template <typename T> -T& NamedSharedMemory<T>::create() { - assert(memory == NULL); - - // Create named shared memory file - memory = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(T), name.c_str()); - QPID_WINDOWS_CHECK_NULL(memory); - - // Map file into memory - data = static_cast<T*>(::MapViewOfFile(memory, FILE_MAP_WRITE, 0, 0, 0)); - QPID_WINDOWS_CHECK_NULL(data); - - return *data; -} - -template <typename T> -T& NamedSharedMemory<T>::get() { - if (memory == NULL) { - // TODO: Might need to search Global\\ name if unadorned name fails - memory = ::OpenFileMapping(FILE_MAP_WRITE, FALSE, name.c_str()); - QPID_WINDOWS_CHECK_NULL(memory); - - data = static_cast<T*>(::MapViewOfFile(memory, FILE_MAP_WRITE, 0, 0, 0)); - QPID_WINDOWS_CHECK_NULL(data); - } - - return *data; -} - -std::string brokerInfoName(uint16_t port) -{ - std::ostringstream path; - path << "qpidd_info_" << port; - return path.str(); -} - -struct BrokerInfo { - DWORD pid; -}; - -} - -struct ProcessControlOptions : public qpid::Options { - bool quit; - bool check; - std::string transport; - - ProcessControlOptions() - : qpid::Options("Process control options"), - quit(false), - check(false), - transport(TCP) - { - addOptions() - ("check,c", qpid::optValue(check), "Prints the broker's process ID to stdout and returns 0 if the broker is running, otherwise returns 1") - ("transport", qpid::optValue(transport, "TRANSPORT"), "The transport for which to return the port") - ("quit,q", qpid::optValue(quit), "Tells the broker to shut down"); - } -}; - -struct QpiddWindowsOptions : public QpiddOptionsPrivate { - ProcessControlOptions control; - QpiddWindowsOptions(QpiddOptions *parent) : QpiddOptionsPrivate(parent) { - parent->add(control); - } -}; - -QpiddOptions::QpiddOptions(const char* argv0) - : qpid::Options("Options"), - common("", QPIDD_CONF_FILE), - module(QPIDD_MODULE_DIR), - log(argv0) -{ - add(common); - add(module); - add(broker); - add(log); - - platform.reset(new QpiddWindowsOptions(this)); - qpid::Plugin::addOptions(*this); -} - -void QpiddOptions::usage() const { - std::cout << "Usage: qpidd [OPTIONS]" << std::endl << std::endl - << *this << std::endl; -} - -int QpiddBroker::execute (QpiddOptions *options) { - // Options that affect a running daemon. - QpiddWindowsOptions *myOptions = - reinterpret_cast<QpiddWindowsOptions *>(options->platform.get()); - if (myOptions == 0) - throw qpid::Exception("Internal error obtaining platform options"); - - if (myOptions->control.check || myOptions->control.quit) { - // Relies on port number being set via --port or QPID_PORT env variable. - NamedSharedMemory<BrokerInfo> info(brokerInfoName(options->broker.port)); - int pid = info.get().pid; - if (pid < 0) - return 1; - if (myOptions->control.check) - std::cout << pid << std::endl; - if (myOptions->control.quit) { - ShutdownEvent shutter(options->broker.port); - shutter.open(); - shutter.signal(); - HANDLE brokerHandle = ::OpenProcess(SYNCHRONIZE, false, pid); - QPID_WINDOWS_CHECK_NULL(brokerHandle); - ::WaitForSingleObject(brokerHandle, INFINITE); - ::CloseHandle(brokerHandle); - } - return 0; - } - - boost::intrusive_ptr<Broker> brokerPtr(new Broker(options->broker)); - - // Need the correct port number to use in the pid file name. - if (options->broker.port == 0) - options->broker.port = brokerPtr->getPort(myOptions->control.transport); - - BrokerInfo info; - info.pid = ::GetCurrentProcessId(); - - NamedSharedMemory<BrokerInfo> sharedInfo(brokerInfoName(options->broker.port)); - sharedInfo.create() = info; - - // Allow the broker to receive a shutdown request via a qpidd --quit - // command. Note that when the broker is run as a service this operation - // should not be allowed. - ourPort = options->broker.port; - ShutdownHandler waitShut(ourPort, brokerPtr); - waitShut.create(); - qpid::sys::Thread waitThr(waitShut); // Wait for shutdown event - ::SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); - brokerPtr->accept(); - std::cout << options->broker.port << std::endl; - brokerPtr->run(); - waitShut.signal(); // In case we shut down some other way - waitThr.join(); - - // CloseHandle(h); - return 0; -} diff --git a/cpp/src/windows/resources/qpid-icon.ico b/cpp/src/windows/resources/qpid-icon.ico Binary files differdeleted file mode 100644 index 112f5d8f1f..0000000000 --- a/cpp/src/windows/resources/qpid-icon.ico +++ /dev/null diff --git a/cpp/src/windows/resources/template-resource.rc b/cpp/src/windows/resources/template-resource.rc deleted file mode 100644 index 725d1c9391..0000000000 --- a/cpp/src/windows/resources/template-resource.rc +++ /dev/null @@ -1,122 +0,0 @@ -//
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-//
-
-#include "version-resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "version-resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION ${winverFileVersionBinary}
- PRODUCTVERSION ${winverProductVersionBinary}
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "FileDescription", "${winverFileDescription}"
- VALUE "FileVersion", "${winverFileVersionString}"
- VALUE "LegalCopyright", "${winverLegalCopyright}"
- VALUE "InternalName", "${winverInternalName}"
- VALUE "OriginalFilename", "${winverOriginalFilename}"
- VALUE "ProductName", "${winverProductName}"
- VALUE "ProductVersion", "${winverProductVersionString}"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDI_ICON1 ICON "qpid-icon.ico"
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/cpp/src/windows/resources/version-resource.h b/cpp/src/windows/resources/version-resource.h deleted file mode 100644 index bf942abbaf..0000000000 --- a/cpp/src/windows/resources/version-resource.h +++ /dev/null @@ -1,35 +0,0 @@ -//
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-//
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Preserved for common usage by any Qpid exe/dll.
-
-#define IDI_ICON1 101
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 104
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/cpp/src/xml.mk b/cpp/src/xml.mk deleted file mode 100644 index baf3803647..0000000000 --- a/cpp/src/xml.mk +++ /dev/null @@ -1,29 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -dmoduleexec_LTLIBRARIES += xml.la - -xml_la_SOURCES = \ - qpid/xml/XmlExchange.cpp \ - qpid/xml/XmlExchange.h \ - qpid/xml/XmlExchangePlugin.cpp - -xml_la_LIBADD = -lxerces-c -lxqilla libqpidbroker.la - -xml_la_LDFLAGS = $(PLUGINLDFLAGS) - |