diff options
author | Ted Ross <tross@apache.org> | 2013-10-24 18:01:00 +0000 |
---|---|---|
committer | Ted Ross <tross@apache.org> | 2013-10-24 18:01:00 +0000 |
commit | a1d53aa6923cba3d92ae3d7d2ff2ab33eafc3279 (patch) | |
tree | 0dd1f54d9869db5d005f11b5288ebc745dfb5895 /extras | |
parent | ae2fa917369c8b0896c891425df0db31fe8eeaeb (diff) | |
download | qpid-python-a1d53aa6923cba3d92ae3d7d2ff2ab33eafc3279.tar.gz |
QPID-5257 - Removed dispatch code from its old location
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1535460 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'extras')
111 files changed, 0 insertions, 19905 deletions
diff --git a/extras/dispatch/CMakeLists.txt b/extras/dispatch/CMakeLists.txt deleted file mode 100644 index a55de067f9..0000000000 --- a/extras/dispatch/CMakeLists.txt +++ /dev/null @@ -1,189 +0,0 @@ -## -## Licensed to the Apache Software Foundation (ASF) under one -## or more contributor license agreements. See the NOTICE file -## distributed with this work for additional information -## regarding copyright ownership. The ASF licenses this file -## to you under the Apache License, Version 2.0 (the -## "License"); you may not use this file except in compliance -## with the License. You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, -## software distributed under the License is distributed on an -## "AS IS" BASIS, WITHOUT 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(qpid-dispatch C) - -cmake_minimum_required(VERSION 2.6) -include(CheckLibraryExists) -include(CheckSymbolExists) -include(CheckFunctionExists) -include(CheckIncludeFiles) -include(FindPythonInterp) -include(FindPythonLibs) - -enable_testing() -include (CTest) - -if (NOT PYTHONLIBS_FOUND) - message(FATAL_ERROR "Python Development Libraries are needed.") -endif (NOT PYTHONLIBS_FOUND) - -set (SO_VERSION_MAJOR 0) -set (SO_VERSION_MINOR 1) -set (SO_VERSION "${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}") - -if (NOT DEFINED LIB_SUFFIX) - get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) - if ("${LIB64}" STREQUAL "TRUE" AND ${CMAKE_SIZEOF_VOID_P} STREQUAL "8") - set(LIB_SUFFIX 64) - else() - set(LIB_SUFFIX "") - endif() -endif() - -set(INCLUDE_INSTALL_DIR include CACHE PATH "Include file directory") -set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "Library object file directory") -set(SYSCONF_INSTALL_DIR etc CACHE PATH "System read only configuration directory") -set(SHARE_INSTALL_DIR share CACHE PATH "Shared read only data directory") -set(DOC_INSTALL_DIR ${SHARE_INSTALL_DIR}/doc CACHE PATH "Shared read-only data directory") -set(MAN_INSTALL_DIR share/man CACHE PATH "Manpage directory") - -# determine the location for installing the python packages -if (PYTHONLIBS_FOUND) - execute_process(COMMAND ${PYTHON_EXECUTABLE} - -c "from distutils.sysconfig import get_python_lib; print get_python_lib(False)" - OUTPUT_VARIABLE PYTHON_SITELIB_PACKAGES - OUTPUT_STRIP_TRAILING_WHITESPACE) -endif (PYTHONLIBS_FOUND) - -## -## Find dependencies -## -find_library(proton_lib qpid-proton) -find_library(pthread_lib pthread) -find_library(rt_lib rt) -find_path(proton_include proton/driver.h) - -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${proton_include} - ${PYTHON_INCLUDE_PATH} - ) - -set(CMAKE_C_FLAGS "-pthread -Wall -Werror -std=gnu99") -set(CATCH_UNDEFINED "-Wl,--no-undefined") - -## -## Build the Multi-Threaded Server Library -## -set(server_SOURCES - src/agent.c - src/alloc.c - src/amqp.c - src/bitmask.c - src/buffer.c - src/compose.c - src/config.c - src/container.c - src/dispatch.c - src/hash.c - src/iovec.c - src/iterator.c - src/log.c - src/message.c - src/parse.c - src/posix/threading.c - src/python_embedded.c - src/router_agent.c - src/router_node.c - src/router_pynode.c - src/server.c - src/timer.c - src/work_queue.c - ) - -set_property(SOURCE src/python_embedded.c src/router_pynode.c - PROPERTY COMPILE_FLAGS -Wno-strict-aliasing - ) - -add_library(qpid-dispatch SHARED ${server_SOURCES}) -target_link_libraries(qpid-dispatch ${proton_lib} ${pthread_lib} ${rt_lib} ${PYTHON_LIBRARIES}) -set_target_properties(qpid-dispatch PROPERTIES - VERSION "${SO_VERSION}" - SOVERSION "${SO_VERSION_MAJOR}" - LINK_FLAGS "${CATCH_UNDEFINED}" - ) -install(TARGETS qpid-dispatch - LIBRARY DESTINATION ${LIB_INSTALL_DIR}) -file(GLOB headers "include/qpid/dispatch/*.h") -install(FILES ${headers} DESTINATION ${INCLUDE_INSTALL_DIR}/qpid/dispatch) -install(FILES include/qpid/dispatch.h DESTINATION ${INCLUDE_INSTALL_DIR}/qpid) -install(FILES etc/qpid-dispatch.conf DESTINATION ${SYSCONF_INSTALL_DIR}/qpid) - -## -## Python modules installation -## -set(PYTHON_STUBS_SOURCES - python/qpid/dispatch/stubs/__init__.py - python/qpid/dispatch/stubs/ioadapter.py - python/qpid/dispatch/stubs/logadapter.py -) - -set(PYTHON_ROUTER_SOURCES - python/qpid/dispatch/router/link.py - python/qpid/dispatch/router/router_engine.py - python/qpid/dispatch/router/__init__.py - python/qpid/dispatch/router/adapter.py - python/qpid/dispatch/router/mobile.py - python/qpid/dispatch/router/node.py - python/qpid/dispatch/router/routing.py - python/qpid/dispatch/router/data.py - python/qpid/dispatch/router/configuration.py - python/qpid/dispatch/router/neighbor.py - python/qpid/dispatch/router/path.py - python/qpid/dispatch/router/binding.py -) - -set(PYTHON_CONFIG_SOURCES - python/qpid/dispatch/config/parser.py - python/qpid/dispatch/config/__init__.py - python/qpid/dispatch/config/schema.py - python/qpid/dispatch/__init__.py -) - -set(DOC_FILES - ChangeLog - LICENSE - README.md - TODO -) - -install(FILES ${PYTHON_STUBS_SOURCES} - DESTINATION ${PYTHON_SITELIB_PACKAGES}/qpid/dispatch/stubs) - -install(FILES ${PYTHON_ROUTER_SOURCES} - DESTINATION ${PYTHON_SITELIB_PACKAGES}/qpid/dispatch/router) - -install(FILES ${PYTHON_CONFIG_SOURCES} - DESTINATION ${PYTHON_SITELIB_PACKAGES}/qpid/dispatch/config) - -install(FILES python/qpid/__init__.py - DESTINATION ${PYTHON_SITELIB_PACKAGES}/qpid) - -install(FILES python/qpid/dispatch/__init__.py - DESTINATION ${PYTHON_SITELIB_PACKAGES}/qpid/dispatch) - -install(FILES ${DOC_FILES} - DESTINATION ${DOC_INSTALL_DIR}/qpid-dispatch) -## -## Build Tests -## -add_subdirectory(router) -add_subdirectory(tests) diff --git a/extras/dispatch/ChangeLog b/extras/dispatch/ChangeLog deleted file mode 100644 index 2a5b4bc4b7..0000000000 --- a/extras/dispatch/ChangeLog +++ /dev/null @@ -1,26 +0,0 @@ -Version 0.1: - * Initial development work. - * QPID-5186: Install documentation files. - * QPID-5185: Install qpid-dispatch.conf to /etc/qpid - * QPID-4612: Dispatch - Change server and container pattern to be consistent with other objects - * QPID-4613: Dispatch Message API Improvement - * QPID-4614: CTEST for Dispatch - * QPID-4913: Dispatch - Add a configuration file reader to configure the service - * QPID-4968: Dispatch - Generalized framework for embedded Python modules - * QPID-4974: Dispatch - Improve the API for parsing and composing AMQP-typed fields - * QPID-5066: Dispatch - move Python code into the qpid.dispatch package - * QPID-5068: Dispatch - Internal feature to easily add and update Delivery Annotations - * QPID-5096: Dispatch - Install the configuration file - * QPID-5097: Dispatch - create a source tarball - * QPID-5181: Dispatch - Assign temporary source addresses for dynamic listener links - * QPID-5185: Move the qpid-dispatch.conf file to /etc/qpid - * QPID-5186: Installing Dispatch should also install the LICENSE, TODO and related files - * QPID-5189: Add a config.sh file for Qpid Dispatch to set an environment for running the router - - * QPID-4788: Dispatch - Re-schedule of an "immediate" timer causes crash - * QPID-4816: dispatch-router crashes when incomplete (but valid) url specified by client. - * QPID-4997: Dispatch - Thread safety issues in the usage of Proton - * QPID-5064: Dispatch - make-install doesn't install the Python artifacts - * QPID-5173: [dispatch] cmake ignores overrides to CMAKE_INCLUDE_PATH and CMAKE_LIBRARY_PATH - * QPID-5201: Dispatch - Fix build errors in Release mode - * QPID-5218: [dispatch] Crash when outgoing window > 0 and multiple subscribed Messenger clients diff --git a/extras/dispatch/LICENSE b/extras/dispatch/LICENSE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/extras/dispatch/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/extras/dispatch/README.md b/extras/dispatch/README.md deleted file mode 100644 index 1a4438fdf9..0000000000 --- a/extras/dispatch/README.md +++ /dev/null @@ -1,30 +0,0 @@ -Qpid Dispatch -============= - -A lightweight AMQP router for building scalable, available, and performant messaging -interconnect. - -Building -======== - -From the dispatch directory: - -$ mkdir build -$ cd build -$ cmake .. -$ make -$ make test # see below - -Note: Your PYTHONPATH _must_ include <dispatch>/python in its list of paths in order -to test and run Dispatch. - -Running The Tests -================= - -Prior to running the unit tests, you should source the file config.sh which is -found in the root directory. - -$ . config.sh - -The file sets up the environment so that the tests can find the Python -libraries, etc. diff --git a/extras/dispatch/TODO b/extras/dispatch/TODO deleted file mode 100644 index 5bb334a6ca..0000000000 --- a/extras/dispatch/TODO +++ /dev/null @@ -1,54 +0,0 @@ -Qpid Dispatch TODO List -============================================================================== -Beyond this simple laundry list, you can find the list of bugs and -enhancements to be fixed by going to the Apache Qpid JIRA instance: - - http://issues.apache.org/jira/browse/QPID -============================================================================== - -- Router Mode: - o Stand-Alone-Router - Does not participate in routing protocol, does not permit inter-router - links, acts as a normal interior-router otherwise. - o Interior-Router - Participates in the routing protocol - o Edge-Concentrator - Does not participate in routing protocol, requires uplink connection(s) - This mode should be used when Dispatch is integrated into an endpoint - application or when it is acting as a connection concentrator. - Proxy and access-protocol functions will be available in this mode. - -- Connection Annotation: - o Type: Inter-router, uplink, endpoint, etc. This formal annotation can be accessed internally - by the connection handlers to guide Dispatch's handling of new connections. - o Weight-{in,out}: Weight/Cost metrics for inter-router links - -- Statistics for Instrumentation: - o Link - . delivery count {unsettled, pre-settled} - . deliveries {accepted, rejected, released, modified} - . octets of delivery {accepted, rejected, released, modified} - . flow frame count - . disposition frame count {forward, backward} - o Address - . deliveries {ingress, egress, transit} - . octets of delivery {ingress, egress, transit} - -- Infrastructure - o Router_Link - Buffer and Iterator for a copy of the link's target address (for use - as an address for messages with no 'to' field). - o Router Event Queue - Event queue to feed alerts to the Python router code. - Neighbor-link-loss is a valuable event because it accelerates the - detection of topology change. - o All PyRouter stimulus through a work queue. - o Router Code Updates - . Report address mappings to routers - . Generate RA immediately after updating routing tables - . Generate unsolicited updates for mobile addresses? - o Expose idle-timeout/keepalive on connectors and listeners - -- Major Roadmap Features - o Security Policy Enforcement - o Proxy (Translation Node) Capability - o Address Provisioning with variable semantics - o Link Routing - o Management, Instrumentation, and Accounting - o Link Cost - o Area Routing diff --git a/extras/dispatch/config.sh b/extras/dispatch/config.sh deleted file mode 100644 index 3c96464ea9..0000000000 --- a/extras/dispatch/config.sh +++ /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. -# - -cd $(dirname ${BASH_SOURCE[0]}) > /dev/null -export QPID_DISPATCH_HOME=$(pwd) -cd - > /dev/null - -export PYTHONPATH=$QPID_DISPATCH_HOME/python:$QPID_DISPATCH_HOME/tools/src/py:$PYTHONPATH -export PATH=$QPID_DISPATCH_HOME/tools/src/py:$PATH - diff --git a/extras/dispatch/etc/qpid-dispatch.conf b/extras/dispatch/etc/qpid-dispatch.conf deleted file mode 100644 index bf25993130..0000000000 --- a/extras/dispatch/etc/qpid-dispatch.conf +++ /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 -## - - -## -## Container section - Configures the general operation of the AMQP container. -## -container { - ## - ## worker-threads - The number of threads that will be created to - ## process message traffic and other application work (timers, non-amqp - ## file descriptors, etc.) - ## - ## The number of threads should be related to the number of available - ## processor cores. To fully utilize a quad-core system, set the - ## number of threads to 4. - ## - worker-threads: 4 - - ## - ## container-name - The name of the AMQP container. If not specified, - ## the container name will be set to a value of the container's - ## choosing. The automatically assigned container name is not - ## guaranteed to be persistent across restarts of the container. - ## - container-name: Qpid.Dispatch.Router.A -} - - -## -## SSL Profile section - Zero or more SSL profiles may be defined here and -## then referenced later in listeners (for incoming connections) or -## connectors (for outgoing connectors). -## -ssl-profile { - ## - ## name - The name of the profile to be referenced later. - ## - name: ssl-profile-name - - ## - ## cert-db - The path to the database that contains the public - ## certificates of trusted certificate authorities (CAs). - ## - ## cert-db: /path/to/trusted-ca.db - - ## - ## cert-file - The path to the file containing the PEM-formatted public - ## certificate to be used on the local end of any connections using - ## this profile. - ## - ## cert-file: /path/to/cert-file.pem - - ## - ## key-file - The path to the file containing the PEM-formatted private - ## key for the above certificate. - ## - ## key-file: /path/to/private-key-file.pem - - ## - ## password-file - If the above private key is password protected, this - ## is the path to a file containing the password that unlocks the - ## certificate key. - ## - ## password-file: /path/to/password-file - - ## - ## password - An alternative to storing the password in a file - ## referenced by password-file is to supply the password right here in - ## the configuration file. This option can be used by supplying the - ## password in the 'password' option. Don't use both password and - ## password-file in the same profile. - ## - ## password: <password> -} - - -## -## Listeners and Connectors -## -listener { - addr: 0.0.0.0 - port: amqp - sasl-mechanisms: ANONYMOUS -} - -listener { - label: Router Interconnect Access - role: inter-router - addr: 0.0.0.0 - port: 5671 - sasl-mechanisms: EXTERNAL - ssl-profile: ssl-profile-name - require-peer-auth: yes - allow-unsecured: yes -} - -connector { - label: Router Uplink - role: inter-router - addr: backbone.enterprise.com - port: amqps - sasl-mechanisms: EXTERNAL - ssl-profile: ssl-profile-name - allow-redirect: no -} - - -## -## Router section - Configure the AMQP router function. -## -router { - ## - ## Router Mode: - ## - ## standalone - Standalone router. In standalone mode, the router operates as - ## a single component. It does not participate in the routing protocol - ## and therefore will not coorperate with other routers. - ## interior - Interior router. The router operates in cooreration with other - ## interior routers in an interconnected network. - ## edge - Edge router. The router operates with an uplink into an interior - ## router network. Edge routers are typically used as connection concentrators - ## or as security firewalls for access into the interior network. - ## - mode: standalone - - ## - ## For Interior router mode only. - ## - ## router-id - Each router is assigned a router-id that is unique. - ## - router-id: Router.A -} - - diff --git a/extras/dispatch/include/qpid/dispatch.h b/extras/dispatch/include/qpid/dispatch.h deleted file mode 100644 index 6b3d6a963f..0000000000 --- a/extras/dispatch/include/qpid/dispatch.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __dispatch_h__ -#define __dispatch_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/bitmask.h> -#include <qpid/dispatch/buffer.h> -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/hash.h> -#include <qpid/dispatch/iovec.h> -#include <qpid/dispatch/iterator.h> -#include <qpid/dispatch/log.h> -#include <qpid/dispatch/router.h> -#include <qpid/dispatch/amqp.h> -#include <qpid/dispatch/parse.h> -#include <qpid/dispatch/compose.h> -#include <qpid/dispatch/config.h> -#include <qpid/dispatch/threading.h> -#include <qpid/dispatch/timer.h> -#include <qpid/dispatch/user_fd.h> -#include <qpid/dispatch/server.h> -#include <qpid/dispatch/message.h> -#include <qpid/dispatch/container.h> -#include <qpid/dispatch/agent.h> -#include <qpid/dispatch/dispatch.h> - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/agent.h b/extras/dispatch/include/qpid/dispatch/agent.h deleted file mode 100644 index fb2279049f..0000000000 --- a/extras/dispatch/include/qpid/dispatch/agent.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef __dispatch_agent_h__ -#define __dispatch_agent_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/dispatch.h> -#include <stddef.h> -#include <stdbool.h> -#include <stdint.h> - -/** - * \defgroup Container Management Agent - * @{ - */ - -typedef struct dx_agent_class_t dx_agent_class_t; - - -/** - * \brief Get Schema Data Handler - * - * @param context The handler context supplied in dx_agent_register. - */ -typedef void (*dx_agent_schema_cb_t)(void* context, void *correlator); - - -/** - * \brief Query Handler - * - * @param context The handler context supplied in dx_agent_register. - * @param id The identifier of the instance being queried or NULL for all instances. - * @param correlator The correlation handle to be used in calls to dx_agent_value_* - */ -typedef void (*dx_agent_query_cb_t)(void* context, const char *id, void *correlator); - - -/** - * \brief Register a class/object-type with the agent. - */ -dx_agent_class_t *dx_agent_register_class(dx_dispatch_t *dx, - const char *fqname, - void *context, - dx_agent_schema_cb_t schema_handler, - dx_agent_query_cb_t query_handler); - -/** - * \brief Register an event-type with the agent. - */ -dx_agent_class_t *dx_agent_register_event(dx_dispatch_t *dx, - const char *fqname, - void *context, - dx_agent_schema_cb_t schema_handler); - -/** - * - */ -void dx_agent_value_string(void *correlator, const char *key, const char *value); -void dx_agent_value_uint(void *correlator, const char *key, uint64_t value); -void dx_agent_value_null(void *correlator, const char *key); -void dx_agent_value_boolean(void *correlator, const char *key, bool value); -void dx_agent_value_binary(void *correlator, const char *key, const uint8_t *value, size_t len); -void dx_agent_value_uuid(void *correlator, const char *key, const uint8_t *value); -void dx_agent_value_timestamp(void *correlator, const char *key, uint64_t value); - - -/** - * - */ -void dx_agent_value_complete(void *correlator, bool more); - - -/** - * - */ -void *dx_agent_raise_event(dx_dispatch_t *dx, dx_agent_class_t *event); - - -/** - * @} - */ - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/alloc.h b/extras/dispatch/include/qpid/dispatch/alloc.h deleted file mode 100644 index ae4190ad89..0000000000 --- a/extras/dispatch/include/qpid/dispatch/alloc.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef __dispatch_alloc_h__ -#define __dispatch_alloc_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 <stdint.h> -#include <qpid/dispatch/threading.h> - -typedef struct dx_alloc_pool_t dx_alloc_pool_t; - -typedef struct { - int transfer_batch_size; - int local_free_list_max; - int global_free_list_max; -} dx_alloc_config_t; - -typedef struct { - uint64_t total_alloc_from_heap; - uint64_t total_free_to_heap; - uint64_t held_by_threads; - uint64_t batches_rebalanced_to_threads; - uint64_t batches_rebalanced_to_global; -} dx_alloc_stats_t; - -typedef struct { - char *type_name; - size_t type_size; - size_t *additional_size; - size_t total_size; - dx_alloc_config_t *config; - dx_alloc_stats_t *stats; - dx_alloc_pool_t *global_pool; - sys_mutex_t *lock; -} dx_alloc_type_desc_t; - - -void *dx_alloc(dx_alloc_type_desc_t *desc, dx_alloc_pool_t **tpool); -void dx_dealloc(dx_alloc_type_desc_t *desc, dx_alloc_pool_t **tpool, void *p); - - -#define ALLOC_DECLARE(T) \ - T *new_##T(); \ - void free_##T(T *p) - -#define ALLOC_DEFINE_CONFIG(T,S,A,C) \ - dx_alloc_type_desc_t __desc_##T = {#T, S, A, 0, C, 0, 0, 0}; \ - __thread dx_alloc_pool_t *__local_pool_##T = 0; \ - T *new_##T() { return (T*) dx_alloc(&__desc_##T, &__local_pool_##T); } \ - void free_##T(T *p) { dx_dealloc(&__desc_##T, &__local_pool_##T, (void*) p); } \ - dx_alloc_stats_t *alloc_stats_##T() { return __desc_##T.stats; } - -#define ALLOC_DEFINE(T) ALLOC_DEFINE_CONFIG(T, sizeof(T), 0, 0) - - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/amqp.h b/extras/dispatch/include/qpid/dispatch/amqp.h deleted file mode 100644 index c27eec6589..0000000000 --- a/extras/dispatch/include/qpid/dispatch/amqp.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef __dispatch_amqp_h__ -#define __dispatch_amqp_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * AMQP Performative Tags - */ -#define DX_PERFORMATIVE_HEADER 0x70 -#define DX_PERFORMATIVE_DELIVERY_ANNOTATIONS 0x71 -#define DX_PERFORMATIVE_MESSAGE_ANNOTATIONS 0x72 -#define DX_PERFORMATIVE_PROPERTIES 0x73 -#define DX_PERFORMATIVE_APPLICATION_PROPERTIES 0x74 -#define DX_PERFORMATIVE_BODY_DATA 0x75 -#define DX_PERFORMATIVE_BODY_AMQP_SEQUENCE 0x76 -#define DX_PERFORMATIVE_BODY_AMQP_VALUE 0x77 -#define DX_PERFORMATIVE_FOOTER 0x78 - - -/** - * AMQP Type Tags - */ -#define DX_AMQP_NULL 0x40 -#define DX_AMQP_BOOLEAN 0x56 -#define DX_AMQP_TRUE 0x41 -#define DX_AMQP_FALSE 0x42 -#define DX_AMQP_UBYTE 0x50 -#define DX_AMQP_USHORT 0x60 -#define DX_AMQP_UINT 0x70 -#define DX_AMQP_SMALLUINT 0x52 -#define DX_AMQP_UINT0 0x43 -#define DX_AMQP_ULONG 0x80 -#define DX_AMQP_SMALLULONG 0x53 -#define DX_AMQP_ULONG0 0x44 -#define DX_AMQP_BYTE 0x51 -#define DX_AMQP_SHORT 0x61 -#define DX_AMQP_INT 0x71 -#define DX_AMQP_SMALLINT 0x54 -#define DX_AMQP_LONG 0x81 -#define DX_AMQP_SMALLLONG 0x55 -#define DX_AMQP_FLOAT 0x72 -#define DX_AMQP_DOUBLE 0x82 -#define DX_AMQP_DECIMAL32 0x74 -#define DX_AMQP_DECIMAL64 0x84 -#define DX_AMQP_DECIMAL128 0x94 -#define DX_AMQP_UTF32 0x73 -#define DX_AMQP_TIMESTAMP 0x83 -#define DX_AMQP_UUID 0x98 -#define DX_AMQP_VBIN8 0xa0 -#define DX_AMQP_VBIN32 0xb0 -#define DX_AMQP_STR8_UTF8 0xa1 -#define DX_AMQP_STR32_UTF8 0xb1 -#define DX_AMQP_SYM8 0xa3 -#define DX_AMQP_SYM32 0xb3 -#define DX_AMQP_LIST0 0x45 -#define DX_AMQP_LIST8 0xc0 -#define DX_AMQP_LIST32 0xd0 -#define DX_AMQP_MAP8 0xc1 -#define DX_AMQP_MAP32 0xd1 -#define DX_AMQP_ARRAY8 0xe0 -#define DX_AMQP_ARRAY32 0xf0 - -/** - * Delivery Annotation Headers - */ -const char * const DX_DA_INGRESS; // Ingress Router -const char * const DX_DA_TRACE; // Trace -const char * const DX_DA_TO; // To-Override - -/** - * Link Terminus Capabilities - */ -const char * const DX_CAPABILITY_ROUTER; - -/** - * Miscellaneous Strings - */ -const char * const DX_INTERNODE_LINK_NAME_1; -const char * const DX_INTERNODE_LINK_NAME_2; - -#endif - diff --git a/extras/dispatch/include/qpid/dispatch/bitmask.h b/extras/dispatch/include/qpid/dispatch/bitmask.h deleted file mode 100644 index fe436bc19b..0000000000 --- a/extras/dispatch/include/qpid/dispatch/bitmask.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __dispatch_bitmask_h__ -#define __dispatch_bitmask_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -typedef struct dx_bitmask_t dx_bitmask_t; - -int dx_bitmask_width(); -dx_bitmask_t *dx_bitmask(int initial); -void dx_bitmask_free(dx_bitmask_t *b); -void dx_bitmask_set_all(dx_bitmask_t *b); -void dx_bitmask_clear_all(dx_bitmask_t *b); -void dx_bitmask_set_bit(dx_bitmask_t *b, int bitnum); -void dx_bitmask_clear_bit(dx_bitmask_t *b, int bitnum); -int dx_bitmask_value(dx_bitmask_t *b, int bitnum); -int dx_bitmask_first_set(dx_bitmask_t *b, int *bitnum); - - - -#endif - diff --git a/extras/dispatch/include/qpid/dispatch/buffer.h b/extras/dispatch/include/qpid/dispatch/buffer.h deleted file mode 100644 index fadded4d74..0000000000 --- a/extras/dispatch/include/qpid/dispatch/buffer.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef __dispatch_buffer_h__ -#define __dispatch_buffer_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/ctools.h> - -typedef struct dx_buffer_t dx_buffer_t; - -DEQ_DECLARE(dx_buffer_t, dx_buffer_list_t); - -struct dx_buffer_t { - DEQ_LINKS(dx_buffer_t); - unsigned int size; -}; - -/** - */ -void dx_buffer_set_size(size_t size); - -/** - */ -dx_buffer_t *dx_buffer(void); - -/** - * @param buf A pointer to an allocated buffer - */ -void dx_buffer_free(dx_buffer_t *buf); - -/** - * @param buf A pointer to an allocated buffer - * @return A pointer to the first octet in the buffer - */ -unsigned char *dx_buffer_base(dx_buffer_t *buf); - -/** - * @param buf A pointer to an allocated buffer - * @return A pointer to the first free octet in the buffer, the insert point for new data. - */ -unsigned char *dx_buffer_cursor(dx_buffer_t *buf); - -/** - * @param buf A pointer to an allocated buffer - * @return The number of octets in the buffer's free space, how many octets may be inserted. - */ -size_t dx_buffer_capacity(dx_buffer_t *buf); - -/** - * @param buf A pointer to an allocated buffer - * @return The number of octets of data in the buffer - */ -size_t dx_buffer_size(dx_buffer_t *buf); - -/** - * Notify the buffer that octets have been inserted at the buffer's cursor. This will advance the - * cursor by len octets. - * - * @param buf A pointer to an allocated buffer - * @param len The number of octets that have been appended to the buffer - */ -void dx_buffer_insert(dx_buffer_t *buf, size_t len); - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/compose.h b/extras/dispatch/include/qpid/dispatch/compose.h deleted file mode 100644 index d68f6be746..0000000000 --- a/extras/dispatch/include/qpid/dispatch/compose.h +++ /dev/null @@ -1,184 +0,0 @@ -#ifndef __dispatch_compose_h__ -#define __dispatch_compose_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/buffer.h> -#include <qpid/dispatch/iterator.h> - -typedef struct dx_composed_field_t dx_composed_field_t; - -/** - * Begin composing a new field for a message. The new field can be standalone or - * appended onto an existing field. - * - * @param performative The performative for the message section being composed. - * @param extend An existing field onto which to append the new field or NULL to - * create a standalone field. - * @return A pointer to the newly created field. - */ -dx_composed_field_t *dx_compose(uint64_t performative, dx_composed_field_t *extend); - -/** - * Free the resources associated with a composed field. - * - * @param A field pointer returned by dx_compose. - */ -void dx_compose_free(dx_composed_field_t *field); - -/** - * Begin to compose the elements of a list in the field. This is called before inserting - * the first list element. - * - * @param field A field created by dx_compose. - */ -void dx_compose_start_list(dx_composed_field_t *field); - -/** - * Complete the composition of a list in the field. This is called after the last - * list element has been inserted. - * - * @param field A field created by dx_compose. - */ -void dx_compose_end_list(dx_composed_field_t *field); - -/** - * Begin to compose the elements os a map in the field. This is called before - * inserting the first element-pair into the map. - * - * @param field A field created by dx_compose. - */ -void dx_compose_start_map(dx_composed_field_t *field); - -/** - * Complete the composition of a map in the field. This is called after the last - * element-pair has been inserted. - * - * @param field A field created by dx_compose. - */ -void dx_compose_end_map(dx_composed_field_t *field); - -/** - * Insert a null element into the field. - * - * @param field A field created by dx_compose. - */ -void dx_compose_insert_null(dx_composed_field_t *field); - -/** - * Insert a boolean value into the field. - * - * @param field A field created by dx_compose. - * @param value The boolean (zero or non-zero) value to insert. - */ -void dx_compose_insert_bool(dx_composed_field_t *field, int value); - -/** - * Insert an unsigned integer (up to 32 bits) into the field. - * - * @param field A field created by dx_compose. - * @param value The unsigned integer value to be inserted. - */ -void dx_compose_insert_uint(dx_composed_field_t *field, uint32_t value); - -/** - * Insert a long (64-bit) unsigned value into the field. - * - * @param field A field created by dx_compose. - * @param value The unsigned integer value to be inserted. - */ -void dx_compose_insert_ulong(dx_composed_field_t *field, uint64_t value); - -/** - * Insert a signed integer (up to 32 bits) into the field. - * - * @param field A field created by dx_compose. - * @param value The integer value to be inserted. - */ -void dx_compose_insert_int(dx_composed_field_t *field, int32_t value); - -/** - * Insert a long signed integer (64 bits) into the field. - * - * @param field A field created by dx_compose. - * @param value The integer value to be inserted. - */ -void dx_compose_insert_long(dx_composed_field_t *field, int64_t value); - -/** - * Insert a timestamp into the field. - * - * @param field A field created by dx_compose. - * @param value The timestamp value to be inserted. - */ -void dx_compose_insert_timestamp(dx_composed_field_t *field, uint64_t value); - -/** - * Insert a UUID into the field. - * - * @param field A field created by dx_compose. - * @param value The pointer to the first octet in the UUID to be inserted. - */ -void dx_compose_insert_uuid(dx_composed_field_t *field, const uint8_t *value); - -/** - * Insert a binary blob into the field. - * - * @param field A field created by dx_compose. - * @param value The pointer to the first octet to be inserted. - * @param len The length, in octets, of the binary blob. - */ -void dx_compose_insert_binary(dx_composed_field_t *field, const uint8_t *value, uint32_t len); - -/** - * Insert a binary blob from a list of buffers. - * - * @param field A field created by dx_compose. - * @param buffers A pointer to a list of buffers to be inserted as binary data. Note that - * the buffer list will be left empty by this function. - */ -void dx_compose_insert_binary_buffers(dx_composed_field_t *field, dx_buffer_list_t *buffers); - -/** - * Insert a null-terminated utf8-encoded string into the field. - * - * @param field A field created by dx_compose. - * @param value A pointer to a null-terminated string. - */ -void dx_compose_insert_string(dx_composed_field_t *field, const char *value); - -/** - * Insert a utf8-encoded string into the field from an iterator - * - * @param field A field created by dx_compose. - * @param iter An iterator for a string value. The caller is responsible for freeing - * this iterator after the call is complete. - */ -void dx_compose_insert_string_iterator(dx_composed_field_t *field, dx_field_iterator_t *iter); - -/** - * Insert a symbol into the field. - * - * @param field A field created by dx_compose. - * @param value A pointer to a null-terminated ASCII string. - */ -void dx_compose_insert_symbol(dx_composed_field_t *field, const char *value); - -#endif - diff --git a/extras/dispatch/include/qpid/dispatch/config.h b/extras/dispatch/include/qpid/dispatch/config.h deleted file mode 100644 index 78186ee5cd..0000000000 --- a/extras/dispatch/include/qpid/dispatch/config.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef __dispatch_config_h__ -#define __dispatch_config_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <stdint.h> - -typedef struct dx_config_t dx_config_t; - -int dx_config_item_count(const dx_config_t *config, const char *section); -const char *dx_config_item_value_string(const dx_config_t *config, const char *section, int index, const char* key); -uint32_t dx_config_item_value_int(const dx_config_t *config, const char *section, int index, const char* key); -int dx_config_item_value_bool(const dx_config_t *config, const char *section, int index, const char* key); - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/container.h b/extras/dispatch/include/qpid/dispatch/container.h deleted file mode 100644 index 03fdd0c4cc..0000000000 --- a/extras/dispatch/include/qpid/dispatch/container.h +++ /dev/null @@ -1,209 +0,0 @@ -#ifndef __dispatch_container_h__ -#define __dispatch_container_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <proton/engine.h> -#include <qpid/dispatch/dispatch.h> -#include <qpid/dispatch/server.h> -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/ctools.h> - -typedef uint8_t dx_dist_mode_t; -#define DX_DIST_COPY 0x01 -#define DX_DIST_MOVE 0x02 -#define DX_DIST_BOTH 0x03 - -/** - * Node Lifetime Policy (see AMQP 3.5.9) - */ -typedef enum { - DX_LIFE_PERMANENT, - DX_LIFE_DELETE_CLOSE, - DX_LIFE_DELETE_NO_LINKS, - DX_LIFE_DELETE_NO_MESSAGES, - DX_LIFE_DELETE_NO_LINKS_MESSAGES -} dx_lifetime_policy_t; - - -/** - * Link Direction - */ -typedef enum { - DX_INCOMING, - DX_OUTGOING -} dx_direction_t; - - -typedef struct dx_node_t dx_node_t; -typedef struct dx_link_t dx_link_t; -typedef struct dx_delivery_t dx_delivery_t; - -typedef void (*dx_container_delivery_handler_t) (void *node_context, dx_link_t *link, dx_delivery_t *delivery); -typedef int (*dx_container_link_handler_t) (void *node_context, dx_link_t *link); -typedef int (*dx_container_link_detach_handler_t) (void *node_context, dx_link_t *link, int closed); -typedef void (*dx_container_node_handler_t) (void *type_context, dx_node_t *node); -typedef void (*dx_container_conn_handler_t) (void *type_context, dx_connection_t *conn); - -typedef struct { - char *type_name; - void *type_context; - int allow_dynamic_creation; - - //======================= - // Node-Instance Handlers - //======================= - - // - // rx_handler - Invoked when a new received delivery is avaliable for processing. - // - dx_container_delivery_handler_t rx_handler; - - // - // disp_handler - Invoked when an existing delivery changes disposition - // or settlement state. - // - dx_container_delivery_handler_t disp_handler; - - // - // incoming_handler - Invoked when an attach for a new incoming link is received. - // - dx_container_link_handler_t incoming_handler; - - // - // outgoing_handler - Invoked when an attach for a new outgoing link is received. - // - dx_container_link_handler_t outgoing_handler; - - // - // writable_handler - Invoked when an outgoing link is available for sending either - // deliveries or disposition changes. The handler must check the - // link's credit to determine whether (and how many) message - // deliveries may be sent. - // - dx_container_link_handler_t writable_handler; - - // - // link_detach_handler - Invoked when a link is detached. - // - dx_container_link_detach_handler_t link_detach_handler; - - //=================== - // Node-Type Handlers - //=================== - - // - // node_created_handler - Invoked when a new instance of the node-type is created. - // - dx_container_node_handler_t node_created_handler; - - // - // node_destroyed_handler - Invoked when an instance of the node type is destroyed. - // - dx_container_node_handler_t node_destroyed_handler; - - // - // inbound_conn_open_handler - Invoked when an incoming connection (via listener) - // is established. - // - dx_container_conn_handler_t inbound_conn_open_handler; - - // - // outbound_conn_open_handler - Invoked when an outgoing connection (via connector) - // is established. - // - dx_container_conn_handler_t outbound_conn_open_handler; -} dx_node_type_t; - - -int dx_container_register_node_type(dx_dispatch_t *dispatch, const dx_node_type_t *nt); - -dx_node_t *dx_container_set_default_node_type(dx_dispatch_t *dispatch, - const dx_node_type_t *nt, - void *node_context, - dx_dist_mode_t supported_dist); - -dx_node_t *dx_container_create_node(dx_dispatch_t *dispatch, - const dx_node_type_t *nt, - const char *name, - void *node_context, - dx_dist_mode_t supported_dist, - dx_lifetime_policy_t life_policy); -void dx_container_destroy_node(dx_node_t *node); - -void dx_container_node_set_context(dx_node_t *node, void *node_context); -dx_dist_mode_t dx_container_node_get_dist_modes(const dx_node_t *node); -dx_lifetime_policy_t dx_container_node_get_life_policy(const dx_node_t *node); - -dx_link_t *dx_link(dx_node_t *node, dx_connection_t *conn, dx_direction_t dir, const char *name); - -/** - * Context associated with the link for storing link-specific state. - */ -void dx_link_set_context(dx_link_t *link, void *link_context); -void *dx_link_get_context(dx_link_t *link); - -/** - * Link context associated with the link's connection for storing state shared across - * all links in a connection. - */ -void dx_link_set_conn_context(dx_link_t *link, void *link_context); -void *dx_link_get_conn_context(dx_link_t *link); - -dx_connection_t *dx_link_connection(dx_link_t *link); -pn_link_t *dx_link_pn(dx_link_t *link); -pn_terminus_t *dx_link_source(dx_link_t *link); -pn_terminus_t *dx_link_target(dx_link_t *link); -pn_terminus_t *dx_link_remote_source(dx_link_t *link); -pn_terminus_t *dx_link_remote_target(dx_link_t *link); -void dx_link_activate(dx_link_t *link); -void dx_link_close(dx_link_t *link); - -/** - * Important: dx_delivery must never be called twice in a row without an intervening pn_link_advance. - * The Disatch architecture provides a hook for discovering when an outgoing link is writable - * and has credit. When a link is writable, a delivery is allocated, written, and advanced - * in one operation. If a backlog of pending deliveries is created, an assertion will be - * thrown. - */ -dx_delivery_t *dx_delivery(dx_link_t *link, pn_delivery_tag_t tag); -void dx_delivery_free(dx_delivery_t *delivery, uint64_t final_disposition); -void dx_delivery_set_peer(dx_delivery_t *delivery, dx_delivery_t *peer); -dx_delivery_t *dx_delivery_peer(dx_delivery_t *delivery); -void dx_delivery_set_context(dx_delivery_t *delivery, void *context); -void *dx_delivery_context(dx_delivery_t *delivery); -pn_delivery_t *dx_delivery_pn(dx_delivery_t *delivery); -void dx_delivery_settle(dx_delivery_t *delivery); -bool dx_delivery_settled(dx_delivery_t *delivery); -bool dx_delivery_disp_changed(dx_delivery_t *delivery); -uint64_t dx_delivery_disp(dx_delivery_t *delivery); -dx_link_t *dx_delivery_link(dx_delivery_t *delivery); - - -typedef struct dx_link_item_t dx_link_item_t; - -struct dx_link_item_t { - DEQ_LINKS(dx_link_item_t); - dx_link_t *link; -}; - -ALLOC_DECLARE(dx_link_item_t); -DEQ_DECLARE(dx_link_item_t, dx_link_list_t); - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/ctools.h b/extras/dispatch/include/qpid/dispatch/ctools.h deleted file mode 100644 index 655c49f261..0000000000 --- a/extras/dispatch/include/qpid/dispatch/ctools.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef __dispatch_ctools_h__ -#define __dispatch_ctools_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 <assert.h> - -#define CT_ASSERT(exp) { assert(exp); } - -#define NEW(t) (t*) malloc(sizeof(t)) -#define NEW_ARRAY(t,n) (t*) malloc(sizeof(t)*(n)) -#define NEW_PTR_ARRAY(t,n) (t**) malloc(sizeof(t*)*(n)) - -#define DEQ_DECLARE(i,d) typedef struct { \ - i *head; \ - i *tail; \ - i *scratch; \ - size_t size; \ - } d - -#define DEQ_LINKS(t) t *prev; t *next - -#define DEQ_INIT(d) do { (d).head = 0; (d).tail = 0; (d).scratch = 0; (d).size = 0; } while (0) -#define DEQ_ITEM_INIT(i) do { (i)->next = 0; (i)->prev = 0; } while(0) -#define DEQ_HEAD(d) ((d).head) -#define DEQ_TAIL(d) ((d).tail) -#define DEQ_SIZE(d) ((d).size) -#define DEQ_NEXT(i) (i)->next -#define DEQ_PREV(i) (i)->prev - -#define DEQ_INSERT_HEAD(d,i) \ -do { \ - CT_ASSERT((i)->next == 0); \ - CT_ASSERT((i)->prev == 0); \ - if ((d).head) { \ - (i)->next = (d).head; \ - (d).head->prev = i; \ - } else { \ - (d).tail = i; \ - (i)->next = 0; \ - CT_ASSERT((d).size == 0); \ - } \ - (i)->prev = 0; \ - (d).head = i; \ - (d).size++; \ -} while (0) - -#define DEQ_INSERT_TAIL(d,i) \ -do { \ - CT_ASSERT((i)->next == 0); \ - CT_ASSERT((i)->prev == 0); \ - if ((d).tail) { \ - (i)->prev = (d).tail; \ - (d).tail->next = i; \ - } else { \ - (d).head = i; \ - (i)->prev = 0; \ - CT_ASSERT((d).size == 0); \ - } \ - (i)->next = 0; \ - (d).tail = i; \ - (d).size++; \ -} while (0) - -#define DEQ_REMOVE_HEAD(d) \ -do { \ - CT_ASSERT((d).head); \ - if ((d).head) { \ - (d).scratch = (d).head; \ - (d).head = (d).head->next; \ - if ((d).head == 0) { \ - (d).tail = 0; \ - CT_ASSERT((d).size == 1); \ - } else \ - (d).head->prev = 0; \ - (d).size--; \ - (d).scratch->next = 0; \ - (d).scratch->prev = 0; \ - } \ -} while (0) - -#define DEQ_REMOVE_TAIL(d) \ -do { \ - CT_ASSERT((d).tail); \ - if ((d).tail) { \ - (d).scratch = (d).tail; \ - (d).tail = (d).tail->prev; \ - if ((d).tail == 0) { \ - (d).head = 0; \ - CT_ASSERT((d).size == 1); \ - } else \ - (d).tail->next = 0; \ - (d).size--; \ - (d).scratch->next = 0; \ - (d).scratch->prev = 0; \ - } \ -} while (0) - -#define DEQ_INSERT_AFTER(d,i,a) \ -do { \ - CT_ASSERT((i)->next == 0); \ - CT_ASSERT((i)->prev == 0); \ - CT_ASSERT(a); \ - if ((a)->next) \ - (a)->next->prev = (i); \ - else \ - (d).tail = (i); \ - (i)->next = (a)->next; \ - (i)->prev = (a); \ - (a)->next = (i); \ - (d).size++; \ -} while (0) - -#define DEQ_REMOVE(d,i) \ -do { \ - if ((i)->next) \ - (i)->next->prev = (i)->prev; \ - else \ - (d).tail = (i)->prev; \ - if ((i)->prev) \ - (i)->prev->next = (i)->next; \ - else \ - (d).head = (i)->next; \ - (d).size--; \ - (i)->next = 0; \ - (i)->prev = 0; \ - CT_ASSERT((d).size || (!(d).head && !(d).tail)); \ -} while (0) - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/dispatch.h b/extras/dispatch/include/qpid/dispatch/dispatch.h deleted file mode 100644 index 87f3fc32d1..0000000000 --- a/extras/dispatch/include/qpid/dispatch/dispatch.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __dispatch_dispatch_h__ -#define __dispatch_dispatch_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * \defgroup General Dispatch Definitions - * @{ - */ - -typedef struct dx_dispatch_t dx_dispatch_t; - -/** - * \brief Initialize the Dispatch library and prepare it for operation. - * - * #param config_path The path to the configuration file. - * @return A handle to be used in API calls for this instance. - */ -dx_dispatch_t *dx_dispatch(const char *config_path); - - -/** - * \brief Finalize the Dispatch library after it has stopped running. - * - * @param dispatch The dispatch handle returned by dx_dispatch - */ -void dx_dispatch_free(dx_dispatch_t *dispatch); - -void dx_dispatch_configure(dx_dispatch_t *dispatch); - - -/** - * @} - */ - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/error.h b/extras/dispatch/include/qpid/dispatch/error.h deleted file mode 100644 index a62f80fde4..0000000000 --- a/extras/dispatch/include/qpid/dispatch/error.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __dispatch_error_h__ -#define __dispatch_error_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -typedef enum { - DX_ERROR_NONE = 0, - DX_ERROR_NOT_FOUND, - DX_ERROR_ALREADY_EXISTS, - DX_ERROR_ALLOC -} dx_error_t; - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/hash.h b/extras/dispatch/include/qpid/dispatch/hash.h deleted file mode 100644 index 4f079f6993..0000000000 --- a/extras/dispatch/include/qpid/dispatch/hash.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __dispatch_hash_h__ -#define __dispatch_hash_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 <qpid/dispatch/iterator.h> -#include <qpid/dispatch/error.h> - -typedef struct dx_hash_t dx_hash_t; -typedef struct dx_hash_handle_t dx_hash_handle_t; - -dx_hash_t *dx_hash(int bucket_exponent, int batch_size, int value_is_const); -void dx_hash_free(dx_hash_t *h); - -size_t dx_hash_size(dx_hash_t *h); -dx_error_t dx_hash_insert(dx_hash_t *h, dx_field_iterator_t *key, void *val, dx_hash_handle_t **handle); -dx_error_t dx_hash_insert_const(dx_hash_t *h, dx_field_iterator_t *key, const void *val, dx_hash_handle_t **handle); -dx_error_t dx_hash_retrieve(dx_hash_t *h, dx_field_iterator_t *key, void **val); -dx_error_t dx_hash_retrieve_const(dx_hash_t *h, dx_field_iterator_t *key, const void **val); -dx_error_t dx_hash_remove(dx_hash_t *h, dx_field_iterator_t *key); - -void dx_hash_handle_free(dx_hash_handle_t *handle); -const unsigned char *dx_hash_key_by_handle(const dx_hash_handle_t *handle); -dx_error_t dx_hash_remove_by_handle(dx_hash_t *h, dx_hash_handle_t *handle); -dx_error_t dx_hash_remove_by_handle2(dx_hash_t *h, dx_hash_handle_t *handle, unsigned char **key); - - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/iovec.h b/extras/dispatch/include/qpid/dispatch/iovec.h deleted file mode 100644 index 5b56c638ff..0000000000 --- a/extras/dispatch/include/qpid/dispatch/iovec.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __dispatch_iovec_h__ -#define __dispatch_iovec_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <sys/uio.h> - -typedef struct dx_iovec_t dx_iovec_t; - -dx_iovec_t *dx_iovec(int vector_count); -void dx_iovec_free(dx_iovec_t *iov); -struct iovec *dx_iovec_array(dx_iovec_t *iov); -int dx_iovec_count(dx_iovec_t *iov); - - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/iterator.h b/extras/dispatch/include/qpid/dispatch/iterator.h deleted file mode 100644 index e31e67e6fd..0000000000 --- a/extras/dispatch/include/qpid/dispatch/iterator.h +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef __dispatch_iterator_h__ -#define __dispatch_iterator_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <stdint.h> -#include <qpid/dispatch/buffer.h> -#include <qpid/dispatch/iovec.h> - -/** - * The field iterator is used to access fields within a buffer chain. - * It shields the user from the fact that the field may be split across - * one or more physical buffers. - */ -typedef struct dx_field_iterator_t dx_field_iterator_t; - -/** - * Iterator views allow the code traversing the field to see a transformed - * view of the raw field. - * - * ITER_VIEW_ALL - No transformation of the raw field data - * - * ITER_VIEW_NO_HOST - Remove the scheme and host fields from the view - * - * amqp://host.domain.com:port/node-id/node/specific - * ^^^^^^^^^^^^^^^^^^^^^ - * node-id/node/specific - * ^^^^^^^^^^^^^^^^^^^^^ - * - * ITER_VIEW_NODE_ID - Isolate the node identifier from an address - * - * amqp://host.domain.com:port/node-id/node/specific - * ^^^^^^^ - * node-id/node/specific - * ^^^^^^^ - * - * ITER_VIEW_NODE_SPECIFIC - Isolate node-specific text from an address - * - * amqp://host.domain.com:port/node-id/node/specific - * ^^^^^^^^^^^^^ - * node-id/node/specific - * ^^^^^^^^^^^^^ - * - * ITER_VIEW_ADDRESS_HASH - Isolate the hashable part of the address depending on address syntax - * - * amqp:/_local/<local> - * L^^^^^^^ - * amqp:/_topo/<area>/<router>/<local> - * A^^^^^^ - * amqp:/_topo/<my-area>/<router>/<local> - * R^^^^^^^^ - * amqp:/_topo/<my_area>/<my-router>/<local> - * L^^^^^^^ - * amqp:/_topo/<area>/all/<local> - * A^^^^^^ - * amqp:/_topo/<my-area>/all/<local> - * L^^^^^^^ - * amqp:/_topo/all/all/<local> - * L^^^^^^^ - * amqp:/<mobile> - * M^^^^^^^^ - * - * ITER_VIEW_NODE_HASH - Isolate the hashable part of a router-id, used for headers - * - * <area>/<router> - * A^^^^^^ - * - * <my_area>/<router> - * R^^^^^^^^ - * - */ -typedef enum { - ITER_VIEW_ALL, - ITER_VIEW_NO_HOST, - ITER_VIEW_NODE_ID, - ITER_VIEW_NODE_SPECIFIC, - ITER_VIEW_ADDRESS_HASH, - ITER_VIEW_NODE_HASH -} dx_iterator_view_t; - - -/** - * Set the area and router names for the local router. These are used to match - * my-area and my-router in address fields. - */ -void dx_field_iterator_set_address(const char *area, const char *router); - -/** - * Create an iterator from a null-terminated string. - * - * The "text" string must stay intact for the whole life of the iterator. The iterator - * does not copy the string, it references it. - */ -dx_field_iterator_t* dx_field_iterator_string(const char *text, - dx_iterator_view_t view); - -dx_field_iterator_t* dx_field_iterator_binary(const char *text, - int length, - dx_iterator_view_t view); - - -/** - * Create an iterator from a field in a buffer chain - */ -dx_field_iterator_t *dx_field_iterator_buffer(dx_buffer_t *buffer, - int offset, - int length, - dx_iterator_view_t view); - -/** - * Free an iterator - */ -void dx_field_iterator_free(dx_field_iterator_t *iter); - -/** - * Reset the iterator to the first octet and set a new view - */ -void dx_field_iterator_reset(dx_field_iterator_t *iter); - -void dx_field_iterator_reset_view(dx_field_iterator_t *iter, - dx_iterator_view_t view); - -/** - * Return the current octet in the iterator's view and step to the next. - */ -unsigned char dx_field_iterator_octet(dx_field_iterator_t *iter); - -/** - * Return true iff the iterator has no more octets in the view. - */ -int dx_field_iterator_end(dx_field_iterator_t *iter); - -/** - * Return a sub-iterator that equals the supplied iterator except that it - * starts at the supplied iterator's current position. - */ -dx_field_iterator_t *dx_field_iterator_sub(dx_field_iterator_t *iter, uint32_t length); - -void dx_field_iterator_advance(dx_field_iterator_t *iter, uint32_t length); - -/** - * Return the remaining length (in octets) for the iterator. - * - * IMPORTANT: This function returns the limit of the remaining length. - * The actual length *may* be less than indicated, but will - * never be more. This function is safe for allocating memory. - * - * @param iter A field iterator - * @return The number of octets remaining in the view (or more) - */ -uint32_t dx_field_iterator_remaining(dx_field_iterator_t *iter); - -/** - * Compare an input string to the iterator's view. Return true iff they are equal. - */ -int dx_field_iterator_equal(dx_field_iterator_t *iter, const unsigned char *string); - -/** - * Return true iff the string matches the characters at the current location in the view. - * This function ignores octets beyond the length of the prefix. - * This function does not alter the position of the iterator if the prefix does not match, - * if it matches, the prefix is consumed. - */ -int dx_field_iterator_prefix(dx_field_iterator_t *iter, const char *prefix); - -/** - * Return a copy of the iterator's view. - */ -unsigned char *dx_field_iterator_copy(dx_field_iterator_t *iter); - -/** - * Return the contents of this iter into an iovec structure. This is used in a - * scatter/gather IO mechanism. If the iterator spans multiple physical buffers, - * the iovec structure will contain one pointer per buffer. - * - * @param iter A field iterator - * @return An iovec structure that references the data in the iterator's buffers. - */ -dx_iovec_t *dx_field_iterator_iovec(const dx_field_iterator_t *iter); - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/log.h b/extras/dispatch/include/qpid/dispatch/log.h deleted file mode 100644 index 4b69733280..0000000000 --- a/extras/dispatch/include/qpid/dispatch/log.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __dispatch_log_h__ -#define __dispatch_log_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#define LOG_NONE 0x00000000 -#define LOG_TRACE 0x00000001 -#define LOG_DEBUG 0x00000002 -#define LOG_INFO 0x00000004 -#define LOG_NOTICE 0x00000008 -#define LOG_WARNING 0x00000010 -#define LOG_ERROR 0x00000020 -#define LOG_CRITICAL 0x00000040 - -void dx_log_impl(const char *module, int cls, const char *file, int line, const char *fmt, ...); -#define dx_log(m, c, f, ...) dx_log_impl(m, c, __FILE__, __LINE__, f , ##__VA_ARGS__) - -void dx_log_set_mask(int mask); - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/message.h b/extras/dispatch/include/qpid/dispatch/message.h deleted file mode 100644 index 8702e509b3..0000000000 --- a/extras/dispatch/include/qpid/dispatch/message.h +++ /dev/null @@ -1,188 +0,0 @@ -#ifndef __dispatch_message_h__ -#define __dispatch_message_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/iterator.h> -#include <qpid/dispatch/buffer.h> -#include <qpid/dispatch/compose.h> -#include <qpid/dispatch/parse.h> -#include <qpid/dispatch/container.h> - -// Callback for status change (confirmed persistent, loaded-in-memory, etc.) - -typedef struct dx_message_t dx_message_t; - -DEQ_DECLARE(dx_message_t, dx_message_list_t); - -struct dx_message_t { - DEQ_LINKS(dx_message_t); - // Private members not listed here. -}; - -typedef enum { - DX_DEPTH_NONE, - DX_DEPTH_HEADER, - DX_DEPTH_DELIVERY_ANNOTATIONS, - DX_DEPTH_MESSAGE_ANNOTATIONS, - DX_DEPTH_PROPERTIES, - DX_DEPTH_APPLICATION_PROPERTIES, - DX_DEPTH_BODY, - DX_DEPTH_ALL -} dx_message_depth_t; - - -typedef enum { - // - // Message Sections - // - DX_FIELD_HEADER, - DX_FIELD_DELIVERY_ANNOTATION, - DX_FIELD_MESSAGE_ANNOTATION, - DX_FIELD_PROPERTIES, - DX_FIELD_APPLICATION_PROPERTIES, - DX_FIELD_BODY, - DX_FIELD_FOOTER, - - // - // Fields of the Header Section - // - DX_FIELD_DURABLE, - DX_FIELD_PRIORITY, - DX_FIELD_TTL, - DX_FIELD_FIRST_ACQUIRER, - DX_FIELD_DELIVERY_COUNT, - - // - // Fields of the Properties Section - // - DX_FIELD_MESSAGE_ID, - DX_FIELD_USER_ID, - DX_FIELD_TO, - DX_FIELD_SUBJECT, - DX_FIELD_REPLY_TO, - DX_FIELD_CORRELATION_ID, - DX_FIELD_CONTENT_TYPE, - DX_FIELD_CONTENT_ENCODING, - DX_FIELD_ABSOLUTE_EXPIRY_TIME, - DX_FIELD_CREATION_TIME, - DX_FIELD_GROUP_ID, - DX_FIELD_GROUP_SEQUENCE, - DX_FIELD_REPLY_TO_GROUP_ID -} dx_message_field_t; - - -/** - * Allocate a new message. - * - * @return A pointer to a dx_message_t that is the sole reference to a newly allocated - * message. - */ -dx_message_t *dx_message(void); - -/** - * Free a message reference. If this is the last reference to the message, free the - * message as well. - * - * @param msg A pointer to a dx_message_t that is no longer needed. - */ -void dx_message_free(dx_message_t *msg); - -/** - * Make a new reference to an existing message. - * - * @param msg A pointer to a dx_message_t referencing a message. - * @return A new pointer to the same referenced message. - */ -dx_message_t *dx_message_copy(dx_message_t *msg); - -/** - * Retrieve the delivery annotations from a message. - * - * IMPORTANT: The pointer returned by this function remains owned by the message. - * The caller MUST NOT free the parsed field. - * - * @param msg Pointer to a received message. - * @return Pointer to the parsed field for the delivery annotations. If the message doesn't - * have delivery annotations, the return value shall be NULL. - */ -dx_parsed_field_t *dx_message_delivery_annotations(dx_message_t *msg); - -/** - * Set the delivery annotations for the message. If the message already has delivery annotations, - * they will be overwritten/replaced by the new field. - * - * @param msg Pointer to a receiver message. - * @param da Pointer to a composed field representing the new delivery annotations of the message. - * If null, the message will not have a delivery annotations field. - * IMPORTANT: The message will not take ownership of the composed field. The - * caller is responsible for freeing it after this call. Since the contents - * are copied into the message, it is safe to free the composed field - * any time after the call to this function. - */ -void dx_message_set_delivery_annotations(dx_message_t *msg, dx_composed_field_t *da); - -/** - * Receive message data via a delivery. This function may be called more than once on the same - * delivery if the message spans multiple frames. Once a complete message has been received, this - * function shall return the message. - * - * @param delivery An incoming delivery from a link - * @return A pointer to the complete message or 0 if the message is not yet complete. - */ -dx_message_t *dx_message_receive(dx_delivery_t *delivery); - -/** - * Send the message outbound on an outgoing link. - * - * @param msg A pointer to a message to be sent. - * @param link The outgoing link on which to send the message. - */ -void dx_message_send(dx_message_t *msg, dx_link_t *link); - -/** - * Check that the message is well-formed up to a certain depth. Any part of the message that is - * beyond the specified depth is not checked for validity. - */ -int dx_message_check(dx_message_t *msg, dx_message_depth_t depth); - -/** - * Return an iterator for the requested message field. If the field is not in the message, - * return NULL. - * - * @param msg A pointer to a message. - * @param field The field to be returned via iterator. - * @return A field iterator that spans the requested field. - */ -dx_field_iterator_t *dx_message_field_iterator(dx_message_t *msg, dx_message_field_t field); - -ssize_t dx_message_field_length(dx_message_t *msg, dx_message_field_t field); -ssize_t dx_message_field_copy(dx_message_t *msg, dx_message_field_t field, void *buffer); - -// -// Functions for composed messages -// - -// Convenience Functions -void dx_message_compose_1(dx_message_t *msg, const char *to, dx_buffer_list_t *buffers); -void dx_message_compose_2(dx_message_t *msg, dx_composed_field_t *content); - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/parse.h b/extras/dispatch/include/qpid/dispatch/parse.h deleted file mode 100644 index 087a440c4e..0000000000 --- a/extras/dispatch/include/qpid/dispatch/parse.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef __dispatch_parse_h__ -#define __dispatch_parse_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/buffer.h> -#include <qpid/dispatch/iterator.h> - -typedef struct dx_parsed_field_t dx_parsed_field_t; - -/** - * Parse a field delimited by a field iterator. - * - * @param iter Field iterator for the field being parsed - * @return A pointer to the newly created field. - */ -dx_parsed_field_t *dx_parse(dx_field_iterator_t *iter); - -/** - * Free the resources associated with a parsed field. - * - * @param A field pointer returned by dx_parse. - */ -void dx_parse_free(dx_parsed_field_t *field); - -/** - * Check to see if the field parse was successful (i.e. the field was - * well-formed). - * - * @param field The field pointer returned by dx_parse. - * @return true iff the field was well-formed and successfully parsed. - */ -int dx_parse_ok(dx_parsed_field_t *field); - -/** - * Return the text of the error describing the parse error if the field - * is not well-formed. - * - * @param field The field pointer returned by dx_parse. - * @return a null-terminated string describing the parse failure. - */ -const char *dx_parse_error(dx_parsed_field_t *field); - -/** - * Return the AMQP tag for the parsed (and well-formed) field. - * - * @param field The field pointer returned by dx_parse. - * @return The tag (see amqp.h) that indicates the type of the field. - */ -uint8_t dx_parse_tag(dx_parsed_field_t *field); - -/** - * Return an iterator for the raw content of the field. This is useful - * only for scalar fields. It is not appropriate for compound fields. - * For compound fields, use the sub-field functions instead. - * - * The returned iterator describes the raw content of the field, and can be - * used for comparison, indexing, or copying. - * - * IMPORTANT: The returned iterator is owned by the field and *must not* be - * freed by the caller of this function. - * - * @param field The field pointer returned by dx_parse. - * @return A field iterator that describes the field's raw content. - */ -dx_field_iterator_t *dx_parse_raw(dx_parsed_field_t *field); - -/** - * Return the raw content as an unsigned integer up to 32-bits. This is - * valid only for scalar fields of a fixed size of 4-octets or fewer. - * - * @param field The field pointer returned by dx_parse. - * @return The raw content of the field cast as a uint32_t. - */ -uint32_t dx_parse_as_uint(dx_parsed_field_t *field); - -/** - * Return the raw content as an unsigned integer up to 64-bits. This is - * valid only for scalar fields of a fixed size of 8-octets or fewer. - * - * @param field The field pointer returned by dx_parse. - * @return The raw content of the field cast as a uint64_t. - */ -uint64_t dx_parse_as_ulong(dx_parsed_field_t *field); - -/** - * Return the raw content as a signed integer up to 32-bits. This is - * valid only for scalar fields of a fixed size of 4-octets or fewer. - * - * @param field The field pointer returned by dx_parse. - * @return The raw content of the field cast as an int32_t. - */ -int32_t dx_parse_as_int(dx_parsed_field_t *field); - -/** - * Return the raw content as a signed integer up to 64-bits. This is - * valid only for scalar fields of a fixed size of 8-octets or fewer. - * - * @param field The field pointer returned by dx_parse. - * @return The raw content of the field cast as an int64_t. - */ -int64_t dx_parse_as_long(dx_parsed_field_t *field); - -/** - * Return the number of sub-field in a compound field. If the field is - * a list or array, this is the number of items in the list/array. If - * the field is a map, this is the number of key/value pairs in the map - * (i.e. half the number of actual sub-field in the map). - * - * For scalar fields, this function will return zero. - * - * @param field The field pointer returned by dx_parse. - * @return The number of sub-fields in the field. - */ -uint32_t dx_parse_sub_count(dx_parsed_field_t *field); - -/** - * Return a dx_parsed_field_t for the idx'th key in a map field. - * If 'field' is not a map, or idx is equal-to or greater-than the number - * of sub-fields in field, this function will return NULL. - * - * IMPORTANT: The pointer returned by this function remains owned by the - * parent field. It *must not* be freed by the caller. - * - * @param field The field pointer returned by dx_parse. - * @param idx The index of the desired sub-field (in range 0..sub_count) - * @return A pointer to the parsed sub-field - */ -dx_parsed_field_t *dx_parse_sub_key(dx_parsed_field_t *field, uint32_t idx); - -/** - * Return a dx_parsed_field_t for the idx'th value in a compound field. - * If idx is equal-to or greater-than the number of sub-fields in field, - * this function will return NULL. - * - * IMPORTANT: The pointer returned by this function remains owned by the - * parent field. It *must not* be freed by the caller. - * - * @param field The field pointer returned by dx_parse. - * @param idx The index of the desired sub-field (in range 0..sub_count) - * @return A pointer to the parsed sub-field - */ -dx_parsed_field_t *dx_parse_sub_value(dx_parsed_field_t *field, uint32_t idx); - -/** - * Convenience Function - Return true iff the field is a map. - * - * @param field The field pointer returned by dx_parse[_sub_{value,key}] - * @return non-zero if the condition is mat. - */ -int dx_parse_is_map(dx_parsed_field_t *field); - -/** - * Convenience Function - Return true iff the field is a list. - * - * @param field The field pointer returned by dx_parse[_sub_{value,key}] - * @return non-zero if the condition is mat. - */ -int dx_parse_is_list(dx_parsed_field_t *field); - -/** - * Convenience Function - Return true iff the field is a scalar type. - * - * @param field The field pointer returned by dx_parse[_sub_{value,key}] - * @return non-zero if the condition is mat. - */ -int dx_parse_is_scalar(dx_parsed_field_t *field); - -/** - * Convenience Function - Return the value for a key in a map. - * - * @param field The field pointer returned by dx_parse[_sub_{value,key}] - * @param key The key to search for in the map. - * @return The value field corresponding to the key or NULL. - */ -dx_parsed_field_t *dx_parse_value_by_key(dx_parsed_field_t *field, const char *key); - -#endif - diff --git a/extras/dispatch/include/qpid/dispatch/python_embedded.h b/extras/dispatch/include/qpid/dispatch/python_embedded.h deleted file mode 100644 index aad0453c24..0000000000 --- a/extras/dispatch/include/qpid/dispatch/python_embedded.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef __python_embedded_h__ -#define __python_embedded_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <Python.h> -#include <qpid/dispatch/dispatch.h> -#include <qpid/dispatch/compose.h> -#include <qpid/dispatch/parse.h> -#include <qpid/dispatch/iterator.h> - -/** - * Initialize the embedded-python subsystem. This must be called before - * any other call into this module is invoked. - */ -void dx_python_initialize(dx_dispatch_t *dx); - -/** - * Finalize the embedded-python subsystem. After this is called, there - * must be no further invocation of dx_python methods. - */ -void dx_python_finalize(); - -/** - * Start using embedded python. This is called once by each module that plans - * to use embedded python capabilities. It must call dx_python_start before - * using any python components. - */ -void dx_python_start(); - -/** - * Stop using embedded python. This is called once by each module after it is - * finished using embedded python capabilities. - */ -void dx_python_stop(); - -/** - * Get the Python top level "dispatch" module. - */ -PyObject *dx_python_module(); - -/** - * Convert a Python object to AMQP format and append to a composed_field. - * - * @param value A Python Object - * @param field A composed field - */ -void dx_py_to_composed(PyObject *value, dx_composed_field_t *field); - -/** - * Convert a parsed field to a Python object - * - * @param field A parsed field - * @return A generated Python object - */ -PyObject *dx_field_to_py(dx_parsed_field_t *field); - -/** - * These are temporary and will eventually be replaced by having an internal python - * work queue that feeds a dedicated embedded-python thread. - */ -void dx_python_lock(); -void dx_python_unlock(); - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/router.h b/extras/dispatch/include/qpid/dispatch/router.h deleted file mode 100644 index 82978dd440..0000000000 --- a/extras/dispatch/include/qpid/dispatch/router.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __dispatch_router_h__ -#define __dispatch_router_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/dispatch.h> -#include <qpid/dispatch/message.h> -#include <qpid/dispatch/iterator.h> -#include <stdbool.h> - -typedef struct dx_address_t dx_address_t; - - -typedef void (*dx_router_message_cb)(void *context, dx_message_t *msg, int link_id); - -const char *dx_router_id(const dx_dispatch_t *dx); - -dx_address_t *dx_router_register_address(dx_dispatch_t *dx, - const char *address, - dx_router_message_cb handler, - void *context); - -void dx_router_unregister_address(dx_address_t *address); - - -void dx_router_send(dx_dispatch_t *dx, - dx_field_iterator_t *address, - dx_message_t *msg); - -void dx_router_send2(dx_dispatch_t *dx, - const char *address, - dx_message_t *msg); - -void dx_router_build_node_list(dx_dispatch_t *dx, dx_composed_field_t *field); - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/server.h b/extras/dispatch/include/qpid/dispatch/server.h deleted file mode 100644 index e50f9ac75b..0000000000 --- a/extras/dispatch/include/qpid/dispatch/server.h +++ /dev/null @@ -1,459 +0,0 @@ -#ifndef __dispatch_server_h__ -#define __dispatch_server_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/dispatch.h> -#include <proton/engine.h> - -/** - * \defgroup Control Server Control Functions - * @{ - */ - -/** - * \brief Thread Start Handler - * - * Callback invoked when a new server thread is started. The callback is - * invoked on the newly created thread. - * - * This handler can be used to set processor affinity or other thread-specific - * tuning values. - * - * @param context The handler context supplied in dx_server_initialize. - * @param thread_id The integer thread identifier that uniquely identifies this thread. - */ -typedef void (*dx_thread_start_cb_t)(void* context, int thread_id); - - -/** - * \brief Set the optional thread-start handler. - * - * This handler is called once on each worker thread at the time the thread is - * started. This may be used to set tuning settings like processor affinity, - * etc. - * - * @param dx The dispatch handle returned by dx_dispatch. - * @param start_handler The thread-start handler invoked per thread on thread startup. - * @param context Opaque context to be passed back in the callback function. - */ -void dx_server_set_start_handler(dx_dispatch_t *dx, dx_thread_start_cb_t start_handler, void *context); - - -/** - * \brief Run the server threads until completion - The blocking version. - * - * Start the operation of the server, including launching all of the worker - * threads. This function does not return until after the server has been - * stopped. The thread that calls dx_server_run is used as one of the worker - * threads. - * - * @param dx The dispatch handle returned by dx_dispatch. - */ -void dx_server_run(dx_dispatch_t *dx); - - -/** - * \brief Start the server threads and return immediately - The non-blocking version. - * - * Start the operation of the server, including launching all of the worker - * threads. - * - * @param dx The dispatch handle returned by dx_dispatch. - */ -void dx_server_start(dx_dispatch_t *dx); - - -/** - * \brief Stop the server - * - * Stop the server and join all of its worker threads. This function may be - * called from any thread. When this function returns, all of the other - * server threads have been closed and joined. The calling thread will be the - * only running thread in the process. - * - * @param dx The dispatch handle returned by dx_dispatch. - */ -void dx_server_stop(dx_dispatch_t *dx); - - -/** - * \brief Pause (quiesce) the server. - * - * This call blocks until all of the worker threads (except the one calling - * this function) are finished processing and have been blocked. When this - * call returns, the calling thread is the only thread running in the process. - * - * If the calling process is *not* one of the server's worker threads, then - * this function will block all of the worker threads before returning. - * - * @param dx The dispatch handle returned by dx_dispatch. - */ -void dx_server_pause(dx_dispatch_t *dx); - - -/** - * \brief Resume normal operation of a paused server. - * - * This call unblocks all of the worker threads so they can resume normal - * connection processing. - * - * @param dx The dispatch handle returned by dx_dispatch. - */ -void dx_server_resume(dx_dispatch_t *dx); - - -/** - * @} - * \defgroup Signal Server Signal Handling Functions - * @{ - */ - - -/** - * \brief Signal Handler - * - * Callback for signal handling. This handler will be invoked on one of the - * worker threads in an orderly fashion. This callback is triggered by a call - * to dx_server_signal. - * - * @param context The handler context supplied in dx_server_initialize. - * @param signum The signal number that was passed into dx_server_signal. - */ -typedef void (*dx_signal_handler_cb_t)(void* context, int signum); - - -/** - * Set the signal handler for the server. The signal handler is invoked - * cleanly on a worker thread after a call is made to dx_server_signal. The - * signal handler is optional and need not be set. - * - * @param dx The dispatch handle returned by dx_dispatch. - * @param signal_handler The signal handler called when a registered signal is caught. - * @param context Opaque context to be passed back in the callback function. - */ -void dx_server_set_signal_handler(dx_dispatch_t *dx, dx_signal_handler_cb_t signal_handler, void *context); - - -/** - * \brief Schedule the invocation of the Server's signal handler. - * - * This function is safe to call from any context, including an OS signal - * handler or an Interrupt Service Routine. It schedules the orderly - * invocation of the Server's signal handler on one of the worker threads. - * - * @param dx The dispatch handle returned by dx_dispatch. - * @param signum The signal number... TODO - */ -void dx_server_signal(dx_dispatch_t *dx, int signum); - - -/** - * @} - * \defgroup Connection Server AMQP Connection Handling Functions - * @{ - */ - -/** - * \brief Listener objects represent the desire to accept incoming transport connections. - */ -typedef struct dx_listener_t dx_listener_t; - -/** - * \brief Connector objects represent the desire to create and maintain an outgoing transport connection. - */ -typedef struct dx_connector_t dx_connector_t; - -/** - * \brief Connection objects wrap Proton connection objects. - */ -typedef struct dx_connection_t dx_connection_t; - -/** - * \brief Event type for the connection callback. - */ -typedef enum { - /// The connection just opened via a listener (inbound). - DX_CONN_EVENT_LISTENER_OPEN, - - /// The connection just opened via a connector (outbound). - DX_CONN_EVENT_CONNECTOR_OPEN, - - /// The connection was closed at the transport level (not cleanly). - DX_CONN_EVENT_CLOSE, - - /// The connection requires processing. - DX_CONN_EVENT_PROCESS -} dx_conn_event_t; - - -/** - * \brief Configuration block for a connector or a listener. - */ -typedef struct dx_server_config_t { - /** - * Host name or network address to bind to a listener or use in the connector. - */ - const char *host; - - /** - * Port name or number to bind to a listener or use in the connector. - */ - const char *port; - - /** - * Space-separated list of SASL mechanisms to be accepted for the connection. - */ - const char *sasl_mechanisms; - - /** - * If appropriate for the mechanism, the username for authentication - * (connector only) - */ - const char *sasl_username; - - /** - * If appropriate for the mechanism, the password for authentication - * (connector only) - */ - const char *sasl_password; - - /** - * If appropriate for the mechanism, the minimum acceptable security strength factor - */ - int sasl_minssf; - - /** - * If appropriate for the mechanism, the maximum acceptable security strength factor - */ - int sasl_maxssf; - - /** - * SSL is enabled for this connection iff non-zero. - */ - int ssl_enabled; - - /** - * Connection will take on the role of SSL server iff non-zero. - */ - int ssl_server; - - /** - * Iff non-zero AND ssl_enabled is non-zero, this listener will detect the client's use - * of SSL or non-SSL and conform to the client's protocol. - * (listener only) - */ - int ssl_allow_unsecured_client; - - /** - * Path to the file containing the PEM-formatted public certificate for the local end - * of the connection. - */ - const char *ssl_certificate_file; - - /** - * Path to the file containing the PEM-formatted private key for the local end of the - * connection. - */ - const char *ssl_private_key_file; - - /** - * The password used to sign the private key, or NULL if the key is not protected. - */ - const char *ssl_password; - - /** - * Path to the file containing the PEM-formatted set of certificates of trusted CAs. - */ - const char *ssl_trusted_certificate_db; - - /** - * Iff non-zero, require that the peer's certificate be supplied and that it be authentic - * according to the set of trusted CAs. - */ - int ssl_require_peer_authentication; - - /** - * Allow the connection to be redirected by the peer (via CLOSE->Redirect). This is - * meaningful for outgoing (connector) connections only. - */ - int allow_redirect; - - /** - * The specified role of the connection. This can be used to control the behavior and - * capabilities of the connections. - */ - const char *role; -} dx_server_config_t; - - -/** - * \brief Connection Event Handler - * - * Callback invoked when processing is needed on a proton connection. This - * callback shall be invoked on one of the server's worker threads. The - * server guarantees that no two threads shall be allowed to process a single - * connection concurrently. The implementation of this handler may assume - * that it has exclusive access to the connection and its subservient - * components (sessions, links, deliveries, etc.). - * - * @param handler_context The handler context supplied in dx_server_set_conn_handler. - * @param conn_context The handler context supplied in dx_server_{connect,listen}. - * @param event The event/reason for the invocation of the handler. - * @param conn The connection that requires processing by the handler. - * @return A value greater than zero if the handler did any proton processing for - * the connection. If no work was done, zero is returned. - */ -typedef int (*dx_conn_handler_cb_t)(void *handler_context, void* conn_context, dx_conn_event_t event, dx_connection_t *conn); - - -/** - * \brief Set the connection event handler callback. - * - * Set the connection handler callback for the server. This callback is - * mandatory and must be set prior to the invocation of dx_server_run. - * - * @param dx The dispatch handle returned by dx_dispatch. - * @param conn_hander The handler for processing connection-related events. - */ -void dx_server_set_conn_handler(dx_dispatch_t *dx, dx_conn_handler_cb_t conn_handler, void *handler_context); - - -/** - * \brief Set the user context for a connection. - * - * @param conn Connection object supplied in DX_CONN_EVENT_{LISTENER,CONNETOR}_OPEN - * @param context User context to be stored with the connection. - */ -void dx_connection_set_context(dx_connection_t *conn, void *context); - - -/** - * \brief Get the user context from a connection. - * - * @param conn Connection object supplied in DX_CONN_EVENT_{LISTENER,CONNETOR}_OPEN - * @return The user context stored with the connection. - */ -void *dx_connection_get_context(dx_connection_t *conn); - - -/** - * \brief Set the link context for a connection. - * - * @param conn Connection object supplied in DX_CONN_EVENT_{LISTENER,CONNETOR}_OPEN - * @param context Link context to be stored with the connection. - */ -void dx_connection_set_link_context(dx_connection_t *conn, void *context); - - -/** - * \brief Get the link context from a connection. - * - * @param conn Connection object supplied in DX_CONN_EVENT_{LISTENER,CONNETOR}_OPEN - * @return The link context stored with the connection. - */ -void *dx_connection_get_link_context(dx_connection_t *conn); - - -/** - * \brief Activate a connection for output. - * - * This function is used to request that the server activate the indicated - * connection. It is assumed that the connection is one that the caller does - * not have permission to access (i.e. it may be owned by another thread - * currently). An activated connection will, when writable, appear in the - * internal work list and be invoked for processing by a worker thread. - * - * @param conn The connection over which the application wishes to send data - */ -void dx_server_activate(dx_connection_t *conn); - - -/** - * \brief Get the wrapped proton-engine connection object. - * - * @param conn Connection object supplied in DX_CONN_EVENT_{LISTENER,CONNETOR}_OPEN - * @return The proton connection object. - */ -pn_connection_t *dx_connection_pn(dx_connection_t *conn); - - -/** - * \brief Get the configuration that was used in the setup of this connection. - * - * @param conn Connection object supplied in DX_CONN_EVENT_{LISTENER,CONNETOR}_OPEN - * @return A pointer to the server configuration used in the establishment of this connection. - */ -const dx_server_config_t *dx_connection_config(const dx_connection_t *conn); - - -/** - * \brief Create a listener for incoming connections. - * - * @param dx The dispatch handle returned by dx_dispatch. - * @param config Pointer to a configuration block for this listener. This block will be - * referenced by the server, not copied. The referenced record must remain - * in-scope for the life of the listener. - * @param context User context passed back in the connection handler. - * @return A pointer to the new listener, or NULL in case of failure. - */ -dx_listener_t *dx_server_listen(dx_dispatch_t *dx, const dx_server_config_t *config, void *context); - - -/** - * \brief Free the resources associated with a listener. - * - * @param li A listener pointer returned by dx_listen. - */ -void dx_listener_free(dx_listener_t* li); - - -/** - * \brief Close a listener so it will accept no more connections. - * - * @param li A listener pointer returned by dx_listen. - */ -void dx_listener_close(dx_listener_t* li); - - -/** - * \brief Create a connector for an outgoing connection. - * - * @param dx The dispatch handle returned by dx_dispatch. - * @param config Pointer to a configuration block for this connector. This block will be - * referenced by the server, not copied. The referenced record must remain - * in-scope for the life of the connector.. - * @param context User context passed back in the connection handler. - * @return A pointer to the new connector, or NULL in case of failure. - */ -dx_connector_t *dx_server_connect(dx_dispatch_t *dx, const dx_server_config_t *config, void *context); - - -/** - * \brief Free the resources associated with a connector. - * - * @param ct A connector pointer returned by dx_connect. - */ -void dx_connector_free(dx_connector_t* ct); - -/** - * @} - */ - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/threading.h b/extras/dispatch/include/qpid/dispatch/threading.h deleted file mode 100644 index f275fc0086..0000000000 --- a/extras/dispatch/include/qpid/dispatch/threading.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __sys_threading_h__ -#define __sys_threading_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -typedef struct sys_mutex_t sys_mutex_t; - -sys_mutex_t *sys_mutex(void); -void sys_mutex_free(sys_mutex_t *mutex); -void sys_mutex_lock(sys_mutex_t *mutex); -void sys_mutex_unlock(sys_mutex_t *mutex); - - -typedef struct sys_cond_t sys_cond_t; - -sys_cond_t *sys_cond(void); -void sys_cond_free(sys_cond_t *cond); -void sys_cond_wait(sys_cond_t *cond, sys_mutex_t *held_mutex); -void sys_cond_signal(sys_cond_t *cond); -void sys_cond_signal_all(sys_cond_t *cond); - - -typedef struct sys_thread_t sys_thread_t; - -sys_thread_t *sys_thread(void *(*run_function) (void *), void *arg); -void sys_thread_free(sys_thread_t *thread); -void sys_thread_join(sys_thread_t *thread); - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/timer.h b/extras/dispatch/include/qpid/dispatch/timer.h deleted file mode 100644 index 1e04351822..0000000000 --- a/extras/dispatch/include/qpid/dispatch/timer.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef __dispatch_timer_h__ -#define __dispatch_timer_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/dispatch.h> -#include <qpid/dispatch/server.h> - -/** - * \defgroup Timer Server Timer Functions - * @{ - */ - -typedef struct dx_timer_t dx_timer_t; - -/** - * Timer Callback - * - * Callback invoked after a timer's interval expires and the timer fires. - * - * @param context The context supplied in dx_timer - */ -typedef void (*dx_timer_cb_t)(void* context); - - -/** - * Create a new timer object. - * - * @param cb The callback function to be invoked when the timer expires. - * @param context An opaque, user-supplied context to be passed into the callback. - * @return A pointer to the new timer object or NULL if memory is exhausted. - */ -dx_timer_t *dx_timer(dx_dispatch_t *dx, dx_timer_cb_t cb, void* context); - - -/** - * Free the resources for a timer object. If the timer was scheduled, it will be canceled - * prior to freeing. After this function returns, the callback will not be invoked for this - * timer. - * - * @param timer Pointer to the timer object returned by dx_timer. - */ -void dx_timer_free(dx_timer_t *timer); - - -/** - * Schedule a timer to fire in the future. - * - * Note that the timer callback will never be invoked synchronously during the execution - * of dx_timer_schedule. Even if the interval is immediate (0), the callback invocation will - * be asynchronous and after the return of this function. - * - * @param timer Pointer to the timer object returned by dx_timer. - * @param msec The minimum number of milliseconds of delay until the timer fires. - * If 0 is supplied, the timer will be scheduled to fire immediately. - */ -void dx_timer_schedule(dx_timer_t *timer, long msec); - - -/** - * Attempt to cancel a scheduled timer. Since the timer callback can be invoked on any - * server thread, it is always possible that a last-second cancel attempt may arrive too late - * to stop the timer from firing (i.e. the cancel is concurrent with the fire callback). - * - * @param timer Pointer to the timer object returned by dx_timer. - */ -void dx_timer_cancel(dx_timer_t *timer); - -/** - * @} - */ - -#endif diff --git a/extras/dispatch/include/qpid/dispatch/user_fd.h b/extras/dispatch/include/qpid/dispatch/user_fd.h deleted file mode 100644 index 2cd9627bd3..0000000000 --- a/extras/dispatch/include/qpid/dispatch/user_fd.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef __dispatch_user_fd_h__ -#define __dispatch_user_fd_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/dispatch.h> -#include <qpid/dispatch/server.h> - -/** - * \defgroup UserFd Server User-File-Descriptor Functions - * @{ - */ - -typedef struct dx_user_fd_t dx_user_fd_t; - - -/** - * User_fd Handler - * - * Callback invoked when a user-managed file descriptor is available for reading or writing or there - * was an error on the file descriptor. - * - * @param context The handler context supplied in the dx_user_fd call. - * @param ufd The user_fd handle for the processable fd. - */ -typedef void (*dx_user_fd_handler_cb_t)(void* context, dx_user_fd_t *ufd); - - -/** - * Set the user-fd handler callback for the server. This handler is optional, but must be supplied - * if the dx_server is used to manage the activation of user file descriptors. - */ -void dx_server_set_user_fd_handler(dx_dispatch_t *dx, dx_user_fd_handler_cb_t ufd_handler); - - -/** - * Create a tracker for a user-managed file descriptor. - * - * A user-fd is appropriate for use when the application opens and manages file descriptors - * for purposes other than AMQP communication. Registering a user fd with the dispatch server - * controls processing of the FD alongside the FDs used for messaging. - * - * @param fd The open file descriptor being managed by the application. - * @param context User context passed back in the connection handler. - * @return A pointer to the new user_fd. - */ -dx_user_fd_t *dx_user_fd(dx_dispatch_t *dx, int fd, void *context); - - -/** - * Free the resources for a user-managed FD tracker. - * - * @param ufd Structure pointer returned by dx_user_fd. - */ -void dx_user_fd_free(dx_user_fd_t *ufd); - - -/** - * Activate a user-fd for read. - * - * Use this activation when the application has capacity to receive data from the user-fd. This will - * cause the callback set in dx_server_set_user_fd_handler to later be invoked when the - * file descriptor has data to read. - * - * @param ufd Structure pointer returned by dx_user_fd. - */ -void dx_user_fd_activate_read(dx_user_fd_t *ufd); - - -/** - * Activate a user-fd for write. - * - * Use this activation when the application has data to write via the user-fd. This will - * cause the callback set in dx_server_set_user_fd_handler to later be invoked when the - * file descriptor is writable. - * - * @param ufd Structure pointer returned by dx_user_fd. - */ -void dx_user_fd_activate_write(dx_user_fd_t *ufd); - - -/** - * Check readable status of a user-fd - * - * Note: It is possible that readable status is spurious (i.e. this function returns true - * but the file-descriptor is not readable and will block if not set to O_NONBLOCK). - * Code accordingly. - * - * @param ufd Structure pointer returned by dx_user_fd. - * @return true iff the user file descriptor is readable. - */ -bool dx_user_fd_is_readable(dx_user_fd_t *ufd); - - -/** - * Check writable status of a user-fd - * - * @param ufd Structure pointer returned by dx_user_fd. - * @return true iff the user file descriptor is writable. - */ -bool dx_user_fd_is_writeable(dx_user_fd_t *ufd); - -/** - * @} - */ - -#endif diff --git a/extras/dispatch/python/qpid/__init__.py b/extras/dispatch/python/qpid/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/extras/dispatch/python/qpid/__init__.py +++ /dev/null diff --git a/extras/dispatch/python/qpid/dispatch/__init__.py b/extras/dispatch/python/qpid/dispatch/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/extras/dispatch/python/qpid/dispatch/__init__.py +++ /dev/null diff --git a/extras/dispatch/python/qpid/dispatch/config/__init__.py b/extras/dispatch/python/qpid/dispatch/config/__init__.py deleted file mode 100644 index 36121bb015..0000000000 --- a/extras/dispatch/python/qpid/dispatch/config/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -from parser import DXConfig diff --git a/extras/dispatch/python/qpid/dispatch/config/parser.py b/extras/dispatch/python/qpid/dispatch/config/parser.py deleted file mode 100644 index a809c78692..0000000000 --- a/extras/dispatch/python/qpid/dispatch/config/parser.py +++ /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 -## - -import json -from schema import config_schema -from dispatch import LogAdapter, LOG_TRACE, LOG_ERROR, LOG_INFO - -class Section: - """ - """ - - def __init__(self, name, kv_pairs, schema_section): - self.name = name - self.schema_section = schema_section - self.values = schema_section.check_and_default(kv_pairs) - self.index = schema_section.index_of(kv_pairs) - - def __repr__(self): - return "%r" % self.values - - -class ConfigMain: - """ - """ - - def __init__(self, schema): - self.sections_by_name = {} - self.sections_by_index = {} - self.schema = schema - - - def update(self, raw_config): - for sec_map in raw_config: - name = sec_map.keys()[0] - kv = sec_map[name] - schema_section = self.schema.sections[name] - sec = Section(name, kv, schema_section) - if name not in self.sections_by_name: - self.sections_by_name[name] = [] - self.sections_by_name[name].append(sec) - self.sections_by_index[sec.index] = sec - self._expand_references() - - - def item_count(self, name): - if name in self.sections_by_name: - return len(self.sections_by_name[name]) - return 0 - - - def get_value(self, name, idx, key): - if name in self.sections_by_name: - sec = self.sections_by_name[name] - if idx <= len(sec): - if key in sec[idx].values: - return sec[idx].values[key] - return None - - - def _expand_references(self): - for name, sec_list in self.sections_by_name.items(): - for sec in sec_list: - for k,v in sec.values.items(): - if sec.schema_section.is_expandable(k): - ref_name = "%s:%s" % (k, v) - if ref_name in self.sections_by_index: - ref_section = self.sections_by_index[ref_name] - for ek,ev in ref_section.values.items(): - if ref_section.schema_section.expand_copy(ek): - sec.values[ek] = ev - - -SECTION_SINGLETON = 0 -SECTION_VALUES = 1 - -VALUE_TYPE = 0 -VALUE_INDEX = 1 -VALUE_FLAGS = 2 -VALUE_DEFAULT = 3 - - -class SchemaSection: - """ - """ - - def __init__(self, name, section_tuple): - self.name = name - self.singleton = section_tuple[SECTION_SINGLETON] - self.values = section_tuple[SECTION_VALUES] - self.index_keys = [] - finding_index = True - index_ord = 0 - while finding_index: - finding_index = False - for k,v in self.values.items(): - if v[VALUE_INDEX] == index_ord: - self.index_keys.append(k) - index_ord += 1 - finding_index = True - - - def is_mandatory(self, key): - return self.values[key][VALUE_FLAGS].find('M') >= 0 - - - def is_expandable(self, key): - return self.values[key][VALUE_FLAGS].find('E') >= 0 - - - def expand_copy(self, key): - return self.values[key][VALUE_FLAGS].find('S') >= 0 - - - def default_value(self, key): - return self.values[key][VALUE_DEFAULT] - - - def check_and_default(self, kv_map): - copy = {} - for k,v in self.values.items(): - if k not in kv_map: - if self.is_mandatory(k): - raise Exception("In section '%s', missing mandatory key '%s'" % (self.name, k)) - else: - copy[k] = self.default_value(k) - for k,v in kv_map.items(): - if k not in self.values: - raise Exception("In section '%s', unknown key '%s'" % (self.name, k)) - copy[k] = v - return copy - - - def index_of(self, kv_map): - result = self.name - for key in self.index_keys: - result += ':%s' % kv_map[key] - if result == "": - result = "SINGLE" - return result - - -class Schema: - """ - """ - - def __init__(self): - self.sections = {} - for k,v in config_schema.items(): - self.sections[k] = SchemaSection(k, v) - - - -class DXConfig: - """ - Configuration File Parser for Qpid Dispatch - - Configuration files are made up of "sections" having the following form: - - section-name { - key0: value0 - key1: value1 - ... - keyN: valueN - } - - Sections may be repeated (i.e. there may be multiple instances with the same section name). - The keys must be unique within a section. Values can be of string or integer types. No - quoting is necessary anywhere in the configuration file. Values may contain whitespace. - - Comment lines starting with the '#' character will be ignored. - - This parser converts the configuration file into a json string where the file is represented - as a list of maps. Each map has one item, the key being the section name and the value being - a nested map of keys and values from the file. This json string is parsed into a data - structure that may then be queried. - - """ - - def __init__(self, path): - self.path = path - self.raw_config = None - self.config = None - self.schema = Schema() - self.log = LogAdapter('config.parser') - - - def read_file(self): - try: - self.log.log(LOG_INFO, "Reading Configuration File: %s" % self.path) - cfile = open(self.path) - text = cfile.read() - cfile.close() - - self.json_text = "[" + self._toJson(text) + "]" - self.raw_config = json.loads(self.json_text); - self._validate_raw_config() - self._process_schema() - except Exception, E: - print "Exception in read_file: %r" % E - raise - - - def __repr__(self): - return "%r" % self.config - - - def _toJson(self, text): - lines = text.split('\n') - stripped = "" - for line in lines: - sline = line.strip() - - # - # Ignore empty lines - # - if len(sline) == 0: - continue - - # - # Ignore comment lines - # - if sline.find('#') == 0: - continue - - # - # Convert section opens, closes, and colon-separated key:value lines into json - # - if sline[-1:] == '{': - sline = '{"' + sline[:-1].strip() + '" : {' - elif sline == '}': - sline = '}},' - else: - colon = sline.find(':') - if colon > 1: - sline = '"' + sline[:colon] + '":"' + sline[colon+1:].strip() + '",' - stripped += sline - - # - # Remove the trailing commas in map entries - # - stripped = stripped.replace(",}", "}") - - # - # Return the entire document minus the trailing comma - # - return stripped[:-1] - - - def _validate_raw_config(self): - """ - Ensure that the configuration is well-formed. Once this is validated, - further functions can assume a well-formed data structure is in place. - """ - if self.raw_config.__class__ != list: - raise Exception("Invalid Config: Expected List at top level") - for section in self.raw_config: - if section.__class__ != dict: - raise Exception("Invalid Config: List items must be maps") - if len(section) != 1: - raise Exception("Invalid Config: Map must have only one entry") - for key,val in section.items(): - if key.__class__ != str and key.__class__ != unicode: - raise Exception("Invalid Config: Key in map must be a string") - if val.__class__ != dict: - raise Exception("Invalid Config: Value in map must be a map") - for k,v in val.items(): - if k.__class__ != str and k.__class__ != unicode: - raise Exception("Invalid Config: Key in section must be a string") - if v.__class__ != str and v.__class__ != unicode: - raise Exception("Invalid Config: Value in section must be a string") - - - def _process_schema(self): - self.config = ConfigMain(self.schema) - self.config.update(self.raw_config) - self.raw_config = None - - - def item_count(self, section): - """ - Return the number of items in a section (i.e. the number if instances of a section-name). - """ - result = self.config.item_count(section) - return result - - - def _value(self, section, idx, key): - return self.config.get_value(section, idx, key) - - - def value_string(self, section, idx, key): - """ - Return the string value for the key in the idx'th item in the section. - """ - value = self._value(section, idx, key) - if value: - return str(value) - return None - - - def value_int(self, section, idx, key): - """ - Return the integer value for the key in the idx'th item in the section. - """ - value = self._value(section, idx, key) - return long(value) - - - def value_bool(self, section, idx, key): - """ - Return the boolean value for the key in the idx'th item in the section. - """ - value = self._value(section, idx, key) - if value: - if str(value) != "no": - return True - return None diff --git a/extras/dispatch/python/qpid/dispatch/config/schema.py b/extras/dispatch/python/qpid/dispatch/config/schema.py deleted file mode 100644 index 7b00000c99..0000000000 --- a/extras/dispatch/python/qpid/dispatch/config/schema.py +++ /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 -## - -# -# config_schema = -# { <section_name> : -# (<singleton>, -# {<key> : (<value-type>, <index>, <flags>, <default-value>) -# ) -# } -# -# <section-name> = String name of a configuration section -# <singleton> = False => There may be 0 or more sections with this name -# True => There must be exactly one section with this name -# <key> = String key of a section's key-value pair -# <value-type> = Python type for the value -# <index> = None => This value is not an index for multiple sections -# >= 0 => Ordinal of this value in the section primary-key -# <flags> = Set of characters: -# M = Mandatory (no default value) -# E = Expand referenced section into this record -# S = During expansion, this key should be copied -# <default-value> = If not mandatory and not specified, the value defaults to this -# value -# - -config_schema = { - 'container' : (True, { - 'worker-threads' : (int, None, "", 1), - 'container-name' : (str, None, "", None) - }), - 'ssl-profile' : (False, { - 'name' : (str, 0, "M"), - 'cert-db' : (str, None, "S", None), - 'cert-file' : (str, None, "S", None), - 'key-file' : (str, None, "S", None), - 'password-file' : (str, None, "S", None), - 'password' : (str, None, "S", None) - }), - 'listener' : (False, { - 'addr' : (str, 0, "M"), - 'port' : (str, 1, "M"), - 'label' : (str, None, "", None), - 'role' : (str, None, "", 'normal'), - 'sasl-mechanisms' : (str, None, "M"), - 'ssl-profile' : (str, None, "E", None), - 'require-peer-auth' : (bool, None, "", True), - 'allow-unsecured' : (bool, None, "", False) - }), - 'connector' : (False, { - 'addr' : (str, 0, "M"), - 'port' : (str, 1, "M"), - 'label' : (str, None, "", None), - 'role' : (str, None, "", 'normal'), - 'sasl-mechanisms' : (str, None, "M"), - 'ssl-profile' : (str, None, "E", None), - 'allow-redirect' : (bool, None, "", True) - }), - 'router' : (True, { - 'mode' : (str, None, "", 'standalone'), - 'router-id' : (str, None, "M"), - 'area' : (str, None, "", None), - 'hello-interval' : (int, None, "", 1), - 'hello-max-age' : (int, None, "", 3), - 'ra-interval' : (int, None, "", 30), - 'remote-ls-max-age' : (int, None, "", 60), - 'mobile-addr-max-age' : (int, None, "", 60) - })} - diff --git a/extras/dispatch/python/qpid/dispatch/router/__init__.py b/extras/dispatch/python/qpid/dispatch/router/__init__.py deleted file mode 100644 index bdb26a0c11..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -from .router_engine import * diff --git a/extras/dispatch/python/qpid/dispatch/router/configuration.py b/extras/dispatch/python/qpid/dispatch/router/configuration.py deleted file mode 100644 index e0fd060b82..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/configuration.py +++ /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. -# - -class Configuration(object): - """ - This module manages and holds the configuration and tuning parameters for a router. - """ - def __init__(self, overrides={}): - ## - ## Load default values - ## - self.values = { 'hello_interval' : 1.0, - 'hello_max_age' : 3.0, - 'ra_interval' : 30.0, - 'remote_ls_max_age' : 60.0, - 'mobile_addr_max_age' : 60.0 } - - ## - ## Apply supplied overrides - ## - for k, v in overrides.items(): - self.values[k] = v - - def __getattr__(self, key): - if key in self.values: - return self.values[key] - raise KeyError - - def __repr__(self): - return "%r" % self.values - diff --git a/extras/dispatch/python/qpid/dispatch/router/data.py b/extras/dispatch/python/qpid/dispatch/router/data.py deleted file mode 100644 index 812369768f..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/data.py +++ /dev/null @@ -1,275 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -try: - from dispatch import * -except ImportError: - from ..stubs import * - - -def getMandatory(data, key, cls=None): - """ - Get the value mapped to the requested key. If it's not present, raise an exception. - """ - if key in data: - value = data[key] - if cls and value.__class__ != cls: - raise Exception("Protocol field has wrong data type: '%s' type=%r expected=%r" % (key, value.__class__, cls)) - return value - raise Exception("Mandatory protocol field missing: '%s'" % key) - - -def getOptional(data, key, default=None, cls=None): - """ - Get the value mapped to the requested key. If it's not present, return the default value. - """ - if key in data: - value = data[key] - if cls and value.__class__ != cls: - raise Exception("Protocol field has wrong data type: '%s' type=%r expected=%r" % (key, value.__class__, cls)) - return value - return default - - -class LinkState(object): - """ - The link-state of a single router. The link state consists of a list of neighbor routers reachable from - the reporting router. The link-state-sequence number is incremented each time the link state changes. - """ - def __init__(self, body, _id=None, _area=None, _ls_seq=None, _peers=None): - self.last_seen = 0 - if body: - self.id = getMandatory(body, 'id', str) - self.area = getMandatory(body, 'area', str) - self.ls_seq = getMandatory(body, 'ls_seq', long) - self.peers = getMandatory(body, 'peers', list) - else: - self.id = _id - self.area = _area - self.ls_seq = long(_ls_seq) - self.peers = _peers - - def __repr__(self): - return "LS(id=%s area=%s ls_seq=%d peers=%r)" % (self.id, self.area, self.ls_seq, self.peers) - - def to_dict(self): - return {'id' : self.id, - 'area' : self.area, - 'ls_seq' : self.ls_seq, - 'peers' : self.peers} - - def add_peer(self, _id): - if self.peers.count(_id) == 0: - self.peers.append(_id) - return True - return False - - def del_peer(self, _id): - if self.peers.count(_id) > 0: - self.peers.remove(_id) - return True - return False - - def bump_sequence(self): - self.ls_seq += 1 - - -class MessageHELLO(object): - """ - HELLO Message - scope: neighbors only - HELLO messages travel at most one hop - This message is used by directly connected routers to determine with whom they have - bidirectional connectivity. - """ - def __init__(self, body, _id=None, _area=None, _seen_peers=None): - if body: - self.id = getMandatory(body, 'id', str) - self.area = getMandatory(body, 'area', str) - self.seen_peers = getMandatory(body, 'seen', list) - else: - self.id = _id - self.area = _area - self.seen_peers = _seen_peers - - def __repr__(self): - return "HELLO(id=%s area=%s seen=%r)" % (self.id, self.area, self.seen_peers) - - def get_opcode(self): - return 'HELLO' - - def to_dict(self): - return {'id' : self.id, - 'area' : self.area, - 'seen' : self.seen_peers} - - def is_seen(self, _id): - return self.seen_peers.count(_id) > 0 - - -class MessageRA(object): - """ - Router Advertisement (RA) Message - scope: all routers in the area and all designated routers - This message is sent periodically to indicate the originating router's sequence numbers - for link-state and mobile-address-state. - """ - def __init__(self, body, _id=None, _area=None, _ls_seq=None, _mobile_seq=None): - if body: - self.id = getMandatory(body, 'id', str) - self.area = getMandatory(body, 'area', str) - self.ls_seq = getMandatory(body, 'ls_seq', long) - self.mobile_seq = getMandatory(body, 'mobile_seq', long) - else: - self.id = _id - self.area = _area - self.ls_seq = long(_ls_seq) - self.mobile_seq = long(_mobile_seq) - - def get_opcode(self): - return 'RA' - - def __repr__(self): - return "RA(id=%s area=%s ls_seq=%d mobile_seq=%d)" % \ - (self.id, self.area, self.ls_seq, self.mobile_seq) - - def to_dict(self): - return {'id' : self.id, - 'area' : self.area, - 'ls_seq' : self.ls_seq, - 'mobile_seq' : self.mobile_seq} - - -class MessageLSU(object): - """ - """ - def __init__(self, body, _id=None, _area=None, _ls_seq=None, _ls=None): - if body: - self.id = getMandatory(body, 'id', str) - self.area = getMandatory(body, 'area', str) - self.ls_seq = getMandatory(body, 'ls_seq', long) - self.ls = LinkState(getMandatory(body, 'ls', dict)) - else: - self.id = _id - self.area = _area - self.ls_seq = long(_ls_seq) - self.ls = _ls - - def get_opcode(self): - return 'LSU' - - def __repr__(self): - return "LSU(id=%s area=%s ls_seq=%d ls=%r)" % \ - (self.id, self.area, self.ls_seq, self.ls) - - def to_dict(self): - return {'id' : self.id, - 'area' : self.area, - 'ls_seq' : self.ls_seq, - 'ls' : self.ls.to_dict()} - - -class MessageLSR(object): - """ - """ - def __init__(self, body, _id=None, _area=None): - if body: - self.id = getMandatory(body, 'id', str) - self.area = getMandatory(body, 'area', str) - else: - self.id = _id - self.area = _area - - def get_opcode(self): - return 'LSR' - - def __repr__(self): - return "LSR(id=%s area=%s)" % (self.id, self.area) - - def to_dict(self): - return {'id' : self.id, - 'area' : self.area} - - -class MessageMAU(object): - """ - """ - def __init__(self, body, _id=None, _area=None, _seq=None, _add_list=None, _del_list=None, _exist_list=None): - if body: - self.id = getMandatory(body, 'id', str) - self.area = getMandatory(body, 'area', str) - self.mobile_seq = getMandatory(body, 'mobile_seq', long) - self.add_list = getOptional(body, 'add', None, list) - self.del_list = getOptional(body, 'del', None, list) - self.exist_list = getOptional(body, 'exist', None, list) - else: - self.id = _id - self.area = _area - self.mobile_seq = long(_seq) - self.add_list = _add_list - self.del_list = _del_list - self.exist_list = _exist_list - - def get_opcode(self): - return 'MAU' - - def __repr__(self): - _add = '' - _del = '' - _exist = '' - if self.add_list: _add = ' add=%r' % self.add_list - if self.del_list: _del = ' del=%r' % self.del_list - if self.exist_list: _exist = ' exist=%r' % self.exist_list - return "MAU(id=%s area=%s mobile_seq=%d%s%s%s)" % \ - (self.id, self.area, self.mobile_seq, _add, _del, _exist) - - def to_dict(self): - body = { 'id' : self.id, - 'area' : self.area, - 'mobile_seq' : self.mobile_seq } - if self.add_list: body['add'] = self.add_list - if self.del_list: body['del'] = self.del_list - if self.exist_list: body['exist'] = self.exist_list - return body - - -class MessageMAR(object): - """ - """ - def __init__(self, body, _id=None, _area=None, _have_seq=None): - if body: - self.id = getMandatory(body, 'id', str) - self.area = getMandatory(body, 'area', str) - self.have_seq = getMandatory(body, 'have_seq', long) - else: - self.id = _id - self.area = _area - self.have_seq = long(_have_seq) - - def get_opcode(self): - return 'MAR' - - def __repr__(self): - return "MAR(id=%s area=%s have_seq=%d)" % (self.id, self.area, self.have_seq) - - def to_dict(self): - return {'id' : self.id, - 'area' : self.area, - 'have_seq' : self.have_seq} - diff --git a/extras/dispatch/python/qpid/dispatch/router/link.py b/extras/dispatch/python/qpid/dispatch/router/link.py deleted file mode 100644 index 11307cd079..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/link.py +++ /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. -# - -from data import MessageRA, MessageLSU, MessageLSR -from time import time - -try: - from dispatch import * -except ImportError: - from ..stubs import * - -class LinkStateEngine(object): - """ - This module is responsible for running the Link State protocol and maintaining the set - of link states that are gathered from the domain. It notifies outbound when changes to - the link-state-collection are detected. - """ - def __init__(self, container): - self.container = container - self.id = self.container.id - self.area = self.container.area - self.ra_interval = self.container.config.ra_interval - self.remote_ls_max_age = self.container.config.remote_ls_max_age - self.last_ra_time = 0 - self.collection = {} - self.collection_changed = False - self.mobile_seq = 0 - self.needed_lsrs = {} - - - def tick(self, now): - self._expire_ls(now) - self._send_lsrs() - - if now - self.last_ra_time >= self.ra_interval: - self.last_ra_time = now - self._send_ra() - - if self.collection_changed: - self.collection_changed = False - self.container.log(LOG_INFO, "New Link-State Collection:") - for a,b in self.collection.items(): - self.container.log(LOG_INFO, " %s => %r" % (a, b.peers)) - self.container.ls_collection_changed(self.collection) - - - def handle_ra(self, msg, now): - if msg.id == self.id: - return - if msg.id in self.collection: - ls = self.collection[msg.id] - ls.last_seen = now - if ls.ls_seq < msg.ls_seq: - self.needed_lsrs[(msg.area, msg.id)] = None - else: - self.needed_lsrs[(msg.area, msg.id)] = None - - - def handle_lsu(self, msg, now): - if msg.id == self.id: - return - if msg.id in self.collection: - ls = self.collection[msg.id] - if ls.ls_seq < msg.ls_seq: - ls = msg.ls - self.collection[msg.id] = ls - self.collection_changed = True - ls.last_seen = now - else: - ls = msg.ls - self.collection[msg.id] = ls - self.collection_changed = True - ls.last_seen = now - self.container.new_node(msg.id) - self.container.log(LOG_INFO, "Learned link-state from new router: %s" % msg.id) - # Schedule LSRs for any routers referenced in this LS that we don't know about - for _id in msg.ls.peers: - if _id not in self.collection: - self.container.new_node(_id) - self.needed_lsrs[(msg.area, _id)] = None - - - def handle_lsr(self, msg, now): - if msg.id == self.id: - return - if self.id not in self.collection: - return - my_ls = self.collection[self.id] - self.container.send('amqp:/_topo/%s/%s/qdxrouter' % (msg.area, msg.id), MessageLSU(None, self.id, self.area, my_ls.ls_seq, my_ls)) - - - def new_local_link_state(self, link_state): - self.collection[self.id] = link_state - self.collection_changed = True - self._send_ra() - - - def set_mobile_sequence(self, seq): - self.mobile_seq = seq - - - def get_collection(self): - return self.collection - - - def _expire_ls(self, now): - to_delete = [] - for key, ls in self.collection.items(): - if key != self.id and now - ls.last_seen > self.remote_ls_max_age: - to_delete.append(key) - for key in to_delete: - ls = self.collection.pop(key) - self.collection_changed = True - self.container.lost_node(key) - self.container.log(LOG_INFO, "Expired link-state from router: %s" % key) - - - def _send_lsrs(self): - for (_area, _id) in self.needed_lsrs.keys(): - self.container.send('amqp:/_topo/%s/%s/qdxrouter' % (_area, _id), MessageLSR(None, self.id, self.area)) - self.needed_lsrs = {} - - - def _send_ra(self): - ls_seq = 0 - if self.id in self.collection: - ls_seq = self.collection[self.id].ls_seq - self.container.send('amqp:/_topo/%s/all/qdxrouter' % self.area, MessageRA(None, self.id, self.area, ls_seq, self.mobile_seq)) diff --git a/extras/dispatch/python/qpid/dispatch/router/mobile.py b/extras/dispatch/python/qpid/dispatch/router/mobile.py deleted file mode 100644 index 117cf98c22..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/mobile.py +++ /dev/null @@ -1,189 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -from data import MessageRA, MessageMAR, MessageMAU - -try: - from dispatch import * -except ImportError: - from ..stubs import * - -class MobileAddressEngine(object): - """ - This module is responsible for maintaining an up-to-date list of mobile addresses in the domain. - It runs the Mobile-Address protocol and generates an un-optimized routing table for mobile addresses. - Note that this routing table maps from the mobile address to the remote router where that address - is directly bound. - """ - def __init__(self, container, node_tracker): - self.container = container - self.node_tracker = node_tracker - self.id = self.container.id - self.area = self.container.area - self.mobile_addr_max_age = self.container.config.mobile_addr_max_age - self.mobile_seq = 0 - self.local_addrs = [] - self.added_addrs = [] - self.deleted_addrs = [] - self.remote_lists = {} # map router_id => (sequence, list of addrs) - self.remote_last_seen = {} # map router_id => time of last seen advertizement/update - self.needed_mars = {} - - - def tick(self, now): - self._expire_remotes(now) - self._send_mars() - - ## - ## If local addrs have changed, collect the changes and send a MAU with the diffs - ## Note: it is important that the differential-MAU be sent before a RA is sent - ## - if len(self.added_addrs) > 0 or len(self.deleted_addrs) > 0: - self.mobile_seq += 1 - self.container.send('amqp:/_topo/%s/all/qdxrouter' % self.area, - MessageMAU(None, self.id, self.area, self.mobile_seq, self.added_addrs, self.deleted_addrs)) - self.local_addrs.extend(self.added_addrs) - for addr in self.deleted_addrs: - self.local_addrs.remove(addr) - self.added_addrs = [] - self.deleted_addrs = [] - self.container.mobile_sequence_changed(self.mobile_seq) - - - def add_local_address(self, addr): - """ - """ - if self.local_addrs.count(addr) == 0: - if self.added_addrs.count(addr) == 0: - self.added_addrs.append(addr) - else: - if self.deleted_addrs.count(addr) > 0: - self.deleted_addrs.remove(addr) - - - def del_local_address(self, addr): - """ - """ - if self.local_addrs.count(addr) > 0: - if self.deleted_addrs.count(addr) == 0: - self.deleted_addrs.append(addr) - else: - if self.added_addrs.count(addr) > 0: - self.added_addrs.remove(addr) - - - def handle_ra(self, msg, now): - if msg.id == self.id: - return - - if msg.mobile_seq == 0: - return - - if msg.id in self.remote_lists: - _seq, _list = self.remote_lists[msg.id] - self.remote_last_seen[msg.id] = now - if _seq < msg.mobile_seq: - self.needed_mars[(msg.id, msg.area, _seq)] = None - else: - self.needed_mars[(msg.id, msg.area, 0)] = None - - - def handle_mau(self, msg, now): - ## - ## If the MAU is differential, we can only use it if its sequence is exactly one greater - ## than our stored sequence. If not, we will ignore the content and schedule a MAR. - ## - ## If the MAU is absolute, we can use it in all cases. - ## - if msg.id == self.id: - return - - if msg.exist_list: - ## - ## Absolute MAU - ## - if msg.id in self.remote_lists: - _seq, _list = self.remote_lists[msg.id] - if _seq >= msg.mobile_seq: # ignore duplicates - return - self.remote_lists[msg.id] = (msg.mobile_seq, msg.exist_list) - self.remote_last_seen[msg.id] = now - (add_list, del_list) = self.node_tracker.overwrite_addresses(msg.id, msg.exist_list) - self._activate_remotes(msg.id, add_list, del_list) - else: - ## - ## Differential MAU - ## - if msg.id in self.remote_lists: - _seq, _list = self.remote_lists[msg.id] - if _seq == msg.mobile_seq: # ignore duplicates - return - self.remote_last_seen[msg.id] = now - if _seq + 1 == msg.mobile_seq: - ## - ## This is one greater than our stored value, incorporate the deltas - ## - if msg.add_list and msg.add_list.__class__ == list: - _list.extend(msg.add_list) - if msg.del_list and msg.del_list.__class__ == list: - for addr in msg.del_list: - _list.remove(addr) - self.remote_lists[msg.id] = (msg.mobile_seq, _list) - if msg.add_list: - self.node_tracker.add_addresses(msg.id, msg.add_list) - if msg.del_list: - self.node_tracker.del_addresses(msg.id, msg.del_list) - self._activate_remotes(msg.id, msg.add_list, msg.del_list) - else: - self.needed_mars[(msg.id, msg.area, _seq)] = None - else: - self.needed_mars[(msg.id, msg.area, 0)] = None - - - def handle_mar(self, msg, now): - if msg.id == self.id: - return - if msg.have_seq < self.mobile_seq: - self.container.send('amqp:/_topo/%s/%s/qdxrouter' % (msg.area, msg.id), - MessageMAU(None, self.id, self.area, self.mobile_seq, None, None, self.local_addrs)) - - - def _expire_remotes(self, now): - for _id, t in self.remote_last_seen.items(): - if now - t > self.mobile_addr_max_age: - self.remote_lists.pop(_id) - self.remote_last_seen.pop(_id) - self.remote_changed = True - - - def _send_mars(self): - for _id, _area, _seq in self.needed_mars.keys(): - self.container.send('amqp:/_topo/%s/%s/qdxrouter' % (_area, _id), MessageMAR(None, self.id, self.area, _seq)) - self.needed_mars = {} - - - def _activate_remotes(self, _id, added, deleted): - bit = self.node_tracker.maskbit_for_node(_id) - if added: - for a in added: - self.container.router_adapter.map_destination(a, bit) - if deleted: - for d in deleted: - self.container.router_adapter.unmap_destination(d, bit) - diff --git a/extras/dispatch/python/qpid/dispatch/router/neighbor.py b/extras/dispatch/python/qpid/dispatch/router/neighbor.py deleted file mode 100644 index 37b7888efe..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/neighbor.py +++ /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. -# - -from data import LinkState, MessageHELLO -from time import time - -try: - from dispatch import * -except ImportError: - from ..stubs import * - - -class NeighborEngine(object): - """ - This module is responsible for maintaining this router's link-state. It runs the HELLO protocol - with the router's neighbors and notifies outbound when the list of neighbors-in-good-standing (the - link-state) changes. - """ - def __init__(self, container): - self.container = container - self.id = self.container.id - self.area = self.container.area - self.last_hello_time = 0.0 - self.hello_interval = container.config.hello_interval - self.hello_max_age = container.config.hello_max_age - self.hellos = {} - self.link_state_changed = False - self.link_state = LinkState(None, self.id, self.area, 0, []) - - - def tick(self, now): - self._expire_hellos(now) - - if now - self.last_hello_time >= self.hello_interval: - self.last_hello_time = now - self.container.send('amqp:/_local/qdxhello', MessageHELLO(None, self.id, self.area, self.hellos.keys())) - - if self.link_state_changed: - self.link_state_changed = False - self.link_state.bump_sequence() - self.container.local_link_state_changed(self.link_state) - - - def handle_hello(self, msg, now, link_id): - if msg.id == self.id: - return - self.hellos[msg.id] = now - if msg.is_seen(self.id): - if self.link_state.add_peer(msg.id): - self.link_state_changed = True - self.container.new_neighbor(msg.id, link_id) - self.container.log(LOG_INFO, "New neighbor established: %s on link: %d" % (msg.id, link_id)) - ## - ## TODO - Use this function to detect area boundaries - ## - - def _expire_hellos(self, now): - to_delete = [] - for key, last_seen in self.hellos.items(): - if now - last_seen > self.hello_max_age: - to_delete.append(key) - for key in to_delete: - self.hellos.pop(key) - if self.link_state.del_peer(key): - self.link_state_changed = True - self.container.lost_neighbor(key) - self.container.log(LOG_INFO, "Neighbor lost: %s" % key) diff --git a/extras/dispatch/python/qpid/dispatch/router/node.py b/extras/dispatch/python/qpid/dispatch/router/node.py deleted file mode 100644 index ef697428da..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/node.py +++ /dev/null @@ -1,174 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -try: - from dispatch import * -except ImportError: - from ..stubs import * - - -class NodeTracker(object): - """ - This module is responsible for tracking the set of router nodes that are known to this - router. It tracks whether they are neighbor or remote and whether they are reachable. - - This module is also responsible for assigning a unique mask bit value to each router. - The mask bit is used in the main router to represent sets of valid destinations for addresses. - """ - def __init__(self, container, max_routers): - self.container = container - self.max_routers = max_routers - self.nodes = {} # id => RemoteNode - self.maskbits = [] - self.next_maskbit = 1 # Reserve bit '0' to represent this router - for i in range(max_routers): - self.maskbits.append(None) - self.maskbits[0] = True - - - def tick(self, now): - pass - - - def new_neighbor(self, node_id, link_maskbit): - """ - A node, designated by node_id, has been discovered as a neighbor over a link with - a maskbit of link_maskbit. - """ - if node_id in self.nodes: - node = self.nodes[node_id] - if node.neighbor: - return - self.container.del_remote_router(node.maskbit) - node.neighbor = True - else: - node = RemoteNode(node_id, self._allocate_maskbit(), True) - self.nodes[node_id] = node - self.container.add_neighbor_router(self._address(node_id), node.maskbit, link_maskbit) - - - def lost_neighbor(self, node_id): - """ - We have lost contact with a neighboring node node_id. - """ - node = self.nodes[node_id] - node.neighbor = False - self.container.del_neighbor_router(node.maskbit) - if node.remote: - self.container.add_remote_router(self._address(node.id), node.maskbit) - else: - self._free_maskbit(node.maskbit) - self.nodes.pop(node_id) - - - def new_node(self, node_id): - """ - A node, designated by node_id, has been discovered through the an advertisement from a - remote peer. - """ - if node_id not in self.nodes: - node = RemoteNode(node_id, self._allocate_maskbit(), False) - self.nodes[node_id] = node - self.container.add_remote_router(self._address(node.id), node.maskbit) - else: - node = self.nodes[node_id] - node.remote = True - - - def lost_node(self, node_id): - """ - A remote node, node_id, has not been heard from for too long and is being deemed lost. - """ - node = self.nodes[node_id] - if node.remote: - node.remote = False - if not node.neighbor: - self.container.del_remote_router(node.maskbit) - self._free_maskbit(node.maskbit) - self.nodes.pop(node_id) - - - def maskbit_for_node(self, node_id): - """ - """ - node = self.nodes[node_id] - if node: - return node.maskbit - return None - - - def add_addresses(self, node_id, addrs): - node = self.nodes[node_id] - for a in addrs: - node.addrs[a] = 1 - - - def del_addresses(self, node_id, addrs): - node = self.nodes[node_id] - for a in addrs: - node.addrs.pop(a) - - - def overwrite_addresses(self, node_id, addrs): - node = self.nodes[node_id] - added = [] - deleted = [] - for a in addrs: - if a not in node.addrs.keys(): - added.append(a) - for a in node.addrs.keys(): - if a not in addrs: - deleted.append(a) - for a in addrs: - node.addrs[a] = 1 - return (added, deleted) - - - def _allocate_maskbit(self): - if self.next_maskbit == None: - raise Exception("Exceeded Maximum Router Count") - result = self.next_maskbit - self.next_maskbit = None - self.maskbits[result] = True - for n in range(result + 1, self.max_routers): - if self.maskbits[n] == None: - self.next_maskbit = n - break - return result - - - def _free_maskbit(self, i): - self.maskbits[i] = None - if self.next_maskbit == None or i < self.next_maskbit: - self.next_maskbit = i - - - def _address(self, node_id): - return "amqp:/_topo/%s/%s" % (self.container.area, node_id) - - -class RemoteNode(object): - - def __init__(self, node_id, maskbit, neighbor): - self.id = node_id - self.maskbit = maskbit - self.neighbor = neighbor - self.remote = not neighbor - self.addrs = {} # Address => Count at Node (1 only for the present) - diff --git a/extras/dispatch/python/qpid/dispatch/router/path.py b/extras/dispatch/python/qpid/dispatch/router/path.py deleted file mode 100644 index da04474e75..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/path.py +++ /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. -# - -try: - from dispatch import * -except ImportError: - from ..stubs import * - -class PathEngine(object): - """ - This module is responsible for computing the next-hop for every router/area in the domain - based on the collection of link states that have been gathered. - """ - def __init__(self, container): - self.container = container - self.id = self.container.id - self.area = self.container.area - self.recalculate = False - self.collection = None - - - def tick(self, now_unused): - if self.recalculate: - self.recalculate = False - self._calculate_routes() - - - def ls_collection_changed(self, collection): - self.recalculate = True - self.collection = collection - - - def _calculate_tree_from_root(self, root): - ## - ## Make a copy of the current collection of link-states that contains - ## a fake link-state for nodes that are known-peers but are not in the - ## collection currently. This is needed to establish routes to those nodes - ## so we can trade link-state information with them. - ## - link_states = {} - for _id, ls in self.collection.items(): - link_states[_id] = ls.peers - for p in ls.peers: - if p not in link_states: - link_states[p] = [_id] - - ## - ## Setup Dijkstra's Algorithm - ## - cost = {} - prev = {} - for _id in link_states: - cost[_id] = None # infinite - prev[_id] = None # undefined - cost[root] = 0 # no cost to the root node - unresolved = NodeSet(cost) - - ## - ## Process unresolved nodes until lowest cost paths to all reachable nodes have been found. - ## - while not unresolved.empty(): - u = unresolved.lowest_cost() - if cost[u] == None: - # There are no more reachable nodes in unresolved - break - for v in link_states[u]: - if unresolved.contains(v): - alt = cost[u] + 1 # TODO - Use link cost instead of 1 - if cost[v] == None or alt < cost[v]: - cost[v] = alt - prev[v] = u - unresolved.set_cost(v, alt) - - ## - ## Remove unreachable nodes from the map. Note that this will also remove the - ## root node (has no previous node) from the map. - ## - for u, val in prev.items(): - if not val: - prev.pop(u) - - ## - ## Return previous-node map. This is a map of all reachable, remote nodes to - ## their predecessor node. - ## - return prev - - - def _calculate_valid_origins(self, nodeset): - ## - ## Calculate the tree from each origin, determine the set of origins-per-dest - ## for which the path from origin to dest passes through us. This is the set - ## of valid origins for forwarding to the destination. - ## - valid_origin = {} # Map of destination => List of Valid Origins - for node in nodeset: - if node != self.id: - valid_origin[node] = [] - - for root in valid_origin.keys(): - prev = self._calculate_tree_from_root(root) - nodes = prev.keys() - while len(nodes) > 0: - u = nodes[0] - path = [u] - nodes.remove(u) - v = prev[u] - while v != root: - if v in nodes: - if v != self.id: - path.append(v) - nodes.remove(v) - if v == self.id: - valid_origin[root].extend(path) - u = v - v = prev[u] - return valid_origin - - - def _calculate_routes(self): - ## - ## Generate the shortest-path tree with the local node as root - ## - prev = self._calculate_tree_from_root(self.id) - nodes = prev.keys() - - ## - ## Distill the path tree into a map of next hops for each node - ## - next_hops = {} - while len(nodes) > 0: - u = nodes[0] # pick any destination - path = [u] - nodes.remove(u) - v = prev[u] - while v != self.id: # build a list of nodes in the path back to the root - if v in nodes: - path.append(v) - nodes.remove(v) - u = v - v = prev[u] - for w in path: # mark each node in the path as reachable via the next hop - next_hops[w] = u - - self.container.next_hops_changed(next_hops) - - ## - ## Calculate the valid origins for remote routers - ## - valid_origin = self._calculate_valid_origins(prev.keys()) - self.container.valid_origins_changed(valid_origin) - - - -class NodeSet(object): - """ - This data structure is an ordered list of node IDs, sorted in increasing order by their cost. - Equal cost nodes are secondarily sorted by their ID in order to provide deterministic and - repeatable ordering. - """ - def __init__(self, cost_map): - self.nodes = [] - for _id, cost in cost_map.items(): - ## - ## Assume that nodes are either unreachable (cost = None) or local (cost = 0) - ## during this initialization. - ## - if cost == 0: - self.nodes.insert(0, (_id, cost)) - else: - ## - ## There is no need to sort unreachable nodes by ID - ## - self.nodes.append((_id, cost)) - - - def __repr__(self): - return self.nodes.__repr__() - - - def empty(self): - return len(self.nodes) == 0 - - - def contains(self, _id): - for a, b in self.nodes: - if a == _id: - return True - return False - - - def lowest_cost(self): - """ - Remove and return the lowest cost node ID. - """ - _id, cost = self.nodes.pop(0) - return _id - - - def set_cost(self, _id, new_cost): - """ - Set the cost for an ID in the NodeSet and re-insert the ID so that the list - remains sorted in increasing cost order. - """ - index = 0 - for i, c in self.nodes: - if i == _id: - break - index += 1 - self.nodes.pop(index) - - index = 0 - for i, c in self.nodes: - if c == None or new_cost < c or (new_cost == c and _id < i): - break - index += 1 - - self.nodes.insert(index, (_id, new_cost)) - diff --git a/extras/dispatch/python/qpid/dispatch/router/router_engine.py b/extras/dispatch/python/qpid/dispatch/router/router_engine.py deleted file mode 100644 index 0bc7ba72c2..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/router_engine.py +++ /dev/null @@ -1,301 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -from time import time -from uuid import uuid4 - -from configuration import Configuration -from data import * -from neighbor import NeighborEngine -from link import LinkStateEngine -from path import PathEngine -from mobile import MobileAddressEngine -from routing import RoutingTableEngine -from node import NodeTracker - -import sys -import traceback - -## -## Import the Dispatch adapters from the environment. If they are not found -## (i.e. we are in a test bench, etc.), load the stub versions. -## -try: - from dispatch import * -except ImportError: - from ..stubs import * - - -class RouterEngine: - """ - """ - - def __init__(self, router_adapter, router_id, area, max_routers, config_override={}): - """ - Initialize an instance of a router for a domain. - """ - ## - ## Record important information about this router instance - ## - self.domain = "domain" - self.router_adapter = router_adapter - self.log_adapter = LogAdapter("dispatch.router") - self.io_adapter = IoAdapter(self, ("qdxrouter", "qdxhello")) - self.max_routers = max_routers - self.id = router_id - self.area = area - self.log(LOG_INFO, "Router Engine Instantiated: area=%s id=%s max_routers=%d" % - (self.area, self.id, self.max_routers)) - - ## - ## Setup configuration - ## - self.config = Configuration(config_override) - self.log(LOG_INFO, "Config: %r" % self.config) - - ## - ## Launch the sub-module engines - ## - self.node_tracker = NodeTracker(self, self.max_routers) - self.neighbor_engine = NeighborEngine(self) - self.link_state_engine = LinkStateEngine(self) - self.path_engine = PathEngine(self) - self.mobile_address_engine = MobileAddressEngine(self, self.node_tracker) - self.routing_table_engine = RoutingTableEngine(self, self.node_tracker) - - - - ##======================================================================================== - ## Adapter Entry Points - invoked from the adapter - ##======================================================================================== - def getId(self): - """ - Return the router's ID - """ - return self.id - - - def addressAdded(self, addr): - """ - """ - try: - if addr.find('Mtemp.') == 0: ## This is a temporary measure until dynamic is added to Messenger - return - if addr.find('M') == 0: - self.mobile_address_engine.add_local_address(addr[1:]) - except Exception, e: - self.log(LOG_ERROR, "Exception in new-address processing: exception=%r" % e) - exc_type, exc_value, exc_traceback = sys.exc_info() - traceback.print_tb(exc_traceback) - - - def addressRemoved(self, addr): - """ - """ - try: - if addr.find('Mtemp.') == 0: - return - if addr.find('M') == 0: - self.mobile_address_engine.del_local_address(addr[1:]) - except Exception, e: - self.log(LOG_ERROR, "Exception in del-address processing: exception=%r" % e) - exc_type, exc_value, exc_traceback = sys.exc_info() - traceback.print_tb(exc_traceback) - - - def handleTimerTick(self): - """ - """ - try: - now = time() - self.neighbor_engine.tick(now) - self.link_state_engine.tick(now) - self.path_engine.tick(now) - self.mobile_address_engine.tick(now) - self.routing_table_engine.tick(now) - self.node_tracker.tick(now) - except Exception, e: - self.log(LOG_ERROR, "Exception in timer processing: exception=%r" % e) - exc_type, exc_value, exc_traceback = sys.exc_info() - traceback.print_tb(exc_traceback) - - - def handleControlMessage(self, opcode, body, link_id): - """ - """ - try: - now = time() - if opcode == 'HELLO': - msg = MessageHELLO(body) - self.log(LOG_TRACE, "RCVD: %r" % msg) - self.neighbor_engine.handle_hello(msg, now, link_id) - - elif opcode == 'RA': - msg = MessageRA(body) - self.log(LOG_DEBUG, "RCVD: %r" % msg) - self.link_state_engine.handle_ra(msg, now) - self.mobile_address_engine.handle_ra(msg, now) - - elif opcode == 'LSU': - msg = MessageLSU(body) - self.log(LOG_DEBUG, "RCVD: %r" % msg) - self.link_state_engine.handle_lsu(msg, now) - - elif opcode == 'LSR': - msg = MessageLSR(body) - self.log(LOG_DEBUG, "RCVD: %r" % msg) - self.link_state_engine.handle_lsr(msg, now) - - elif opcode == 'MAU': - msg = MessageMAU(body) - self.log(LOG_DEBUG, "RCVD: %r" % msg) - self.mobile_address_engine.handle_mau(msg, now) - - elif opcode == 'MAR': - msg = MessageMAR(body) - self.log(LOG_DEBUG, "RCVD: %r" % msg) - self.mobile_address_engine.handle_mar(msg, now) - - except Exception, e: - self.log(LOG_ERROR, "Exception in message processing: opcode=%s body=%r exception=%r" % (opcode, body, e)) - exc_type, exc_value, exc_traceback = sys.exc_info() - traceback.print_tb(exc_traceback) - - - def receive(self, message_properties, body, link_id): - """ - This is the IoAdapter message-receive handler - """ - try: - #self.log(LOG_DEBUG, "Raw Receive: mp=%r body=%r link_id=%r" % (message_properties, body, link_id)) - self.handleControlMessage(message_properties['opcode'], body, link_id) - except Exception, e: - self.log(LOG_ERROR, "Exception in raw message processing: properties=%r body=%r exception=%r" % - (message_properties, body, e)) - exc_type, exc_value, exc_traceback = sys.exc_info() - traceback.print_tb(exc_traceback) - - - def getRouterData(self, kind): - """ - """ - if kind == 'help': - return { 'help' : "Get list of supported values for kind", - 'link-state' : "This router's link state", - 'link-state-set' : "The set of link states from known routers", - 'next-hops' : "Next hops to each known router" - } - if kind == 'link-state' : return self.neighbor_engine.link_state.to_dict() - if kind == 'next-hops' : return self.routing_table_engine.next_hops - if kind == 'link-state-set' : - copy = {} - for _id,_ls in self.link_state_engine.collection.items(): - copy[_id] = _ls.to_dict() - return copy - - return {'notice':'Use kind="help" to get a list of possibilities'} - - - ##======================================================================================== - ## Adapter Calls - outbound calls to Dispatch - ##======================================================================================== - def log(self, level, text): - """ - Emit a log message to the host's event log - """ - self.log_adapter.log(level, text) - - - def send(self, dest, msg): - """ - Send a control message to another router. - """ - app_props = {'opcode' : msg.get_opcode() } - self.io_adapter.send(dest, app_props, msg.to_dict()) - if "qdxhello" in dest: - self.log(LOG_TRACE, "SENT: %r dest=%s" % (msg, dest)) - else: - self.log(LOG_DEBUG, "SENT: %r dest=%s" % (msg, dest)) - - - def node_updated(self, addr, reachable, neighbor): - """ - """ - self.router_adapter(addr, reachable, neighbor) - - - ##======================================================================================== - ## Interconnect between the Sub-Modules - ##======================================================================================== - def local_link_state_changed(self, link_state): - self.log(LOG_DEBUG, "Event: local_link_state_changed: %r" % link_state) - self.link_state_engine.new_local_link_state(link_state) - - def ls_collection_changed(self, collection): - self.log(LOG_DEBUG, "Event: ls_collection_changed: %r" % collection) - self.path_engine.ls_collection_changed(collection) - - def next_hops_changed(self, next_hop_table): - self.log(LOG_DEBUG, "Event: next_hops_changed: %r" % next_hop_table) - self.routing_table_engine.next_hops_changed(next_hop_table) - - def valid_origins_changed(self, valid_origins): - self.log(LOG_DEBUG, "Event: valid_origins_changed: %r" % valid_origins) - self.routing_table_engine.valid_origins_changed(valid_origins) - - def mobile_sequence_changed(self, mobile_seq): - self.log(LOG_DEBUG, "Event: mobile_sequence_changed: %d" % mobile_seq) - self.link_state_engine.set_mobile_sequence(mobile_seq) - - def get_next_hops(self): - return self.routing_table_engine.get_next_hops() - - def new_neighbor(self, rid, link_id): - self.log(LOG_DEBUG, "Event: new_neighbor: id=%s link_id=%d" % (rid, link_id)) - self.node_tracker.new_neighbor(rid, link_id) - - def lost_neighbor(self, rid): - self.log(LOG_DEBUG, "Event: lost_neighbor: id=%s" % rid) - self.node_tracker.lost_neighbor(rid) - - def new_node(self, rid): - self.log(LOG_DEBUG, "Event: new_node: id=%s" % rid) - self.node_tracker.new_node(rid) - - def lost_node(self, rid): - self.log(LOG_DEBUG, "Event: lost_node: id=%s" % rid) - self.node_tracker.lost_node(rid) - - def add_neighbor_router(self, address, router_bit, link_bit): - self.log(LOG_DEBUG, "Event: add_neighbor_router: address=%s, router_bit=%d, link_bit=%d" % \ - (address, router_bit, link_bit)) - self.router_adapter.add_neighbor_router(address, router_bit, link_bit) - - def del_neighbor_router(self, router_bit): - self.log(LOG_DEBUG, "Event: del_neighbor_router: router_bit=%d" % router_bit) - self.router_adapter.del_neighbor_router(router_bit) - - def add_remote_router(self, address, router_bit): - self.log(LOG_DEBUG, "Event: add_remote_router: address=%s, router_bit=%d" % (address, router_bit)) - self.router_adapter.add_remote_router(address, router_bit) - - def del_remote_router(self, router_bit): - self.log(LOG_DEBUG, "Event: del_remote_router: router_bit=%d" % router_bit) - self.router_adapter.del_remote_router(router_bit) - diff --git a/extras/dispatch/python/qpid/dispatch/router/routing.py b/extras/dispatch/python/qpid/dispatch/router/routing.py deleted file mode 100644 index a4b3e5484a..0000000000 --- a/extras/dispatch/python/qpid/dispatch/router/routing.py +++ /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. -# - -try: - from dispatch import * -except ImportError: - from ..stubs import * - -class RoutingTableEngine(object): - """ - This module is responsible for converting the set of next hops to remote routers to a routing - table in the "topological" address class. - """ - def __init__(self, container, node_tracker): - self.container = container - self.node_tracker = node_tracker - self.id = self.container.id - self.area = self.container.area - self.next_hops = {} - - - def tick(self, now): - pass - - - def next_hops_changed(self, next_hops): - # Convert next_hops into routing table - self.next_hops = next_hops - for _id, next_hop in next_hops.items(): - mb_id = self.node_tracker.maskbit_for_node(_id) - mb_nh = self.node_tracker.maskbit_for_node(next_hop) - self.container.router_adapter.set_next_hop(mb_id, mb_nh) - - - def valid_origins_changed(self, valid_origins): - for _id, vo in valid_origins.items(): - mb_id = self.node_tracker.maskbit_for_node(_id) - mb_vo = [] - for o in vo: - mb_vo.append(self.node_tracker.maskbit_for_node(o)) - self.container.router_adapter.set_valid_origins(mb_id, mb_vo) - - - def get_next_hops(self): - return self.next_hops - diff --git a/extras/dispatch/python/qpid/dispatch/stubs/__init__.py b/extras/dispatch/python/qpid/dispatch/stubs/__init__.py deleted file mode 100644 index 85100d26df..0000000000 --- a/extras/dispatch/python/qpid/dispatch/stubs/__init__.py +++ /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. -# - -from .logadapter import * -from .ioadapter import * - diff --git a/extras/dispatch/python/qpid/dispatch/stubs/ioadapter.py b/extras/dispatch/python/qpid/dispatch/stubs/ioadapter.py deleted file mode 100644 index 1e465f98c3..0000000000 --- a/extras/dispatch/python/qpid/dispatch/stubs/ioadapter.py +++ /dev/null @@ -1,27 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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 IoAdapter: - def __init__(self, handler, address): - self.handler = handler - self.address = address - - def send(self, address, app_properties, body): - print "IO: send(addr=%s props=%r body=%r" % (address, app_properties, body) - diff --git a/extras/dispatch/python/qpid/dispatch/stubs/logadapter.py b/extras/dispatch/python/qpid/dispatch/stubs/logadapter.py deleted file mode 100644 index 3d717d3ed2..0000000000 --- a/extras/dispatch/python/qpid/dispatch/stubs/logadapter.py +++ /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. -# - -LOG_TRACE = 1 -LOG_DEBUG = 2 -LOG_INFO = 4 -LOG_NOTICE = 8 -LOG_WARNING = 16 -LOG_ERROR = 32 -LOG_CRITICAL = 64 - -class LogAdapter: - def __init__(self, mod_name): - self.mod_name = mod_name - - def log(self, level, text): - print "LOG: mod=%s level=%d text=%s" % (self.mod_name, level, text) diff --git a/extras/dispatch/release.sh b/extras/dispatch/release.sh deleted file mode 100755 index 9b76a9c562..0000000000 --- a/extras/dispatch/release.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/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 pull together an Apache Release -# - -ME=$(basename $0) - -usage() { - cat <<-EOF -USAGE: ${ME} [options] SVNPATH SVNREV VERSION -Creates an Apache release tarball. - -Mandatory arguments: - SVNPATH The path within the source code repository. - SVNREV The revision at which to create the release. - VERSION The release version. - -Optional arguments: - -h This help screen -EOF -} - -while getopts "h" opt; do - case $opt in - h) - usage - exit 0 - ;; - - \?) - echo "Invalid option: -$OPTARG" >&2 - usage - exit 1 - ;; - - :) - echo "Option -$OPTARG requires an argument." >&2 - usage - exit 1 - ;; - esac -done - -SVNPATH=${1-} -SVNREV=${2-} -VERSION=${3-} - -if [[ -z "$SVNPATH" ]] || [[ -z "$SVNREV" ]] || [[ -z "$VERSION" ]]; then - printf "Missing one or more required argument.\n\n" >&2 - usage - exit 1 -fi - -URL=http://svn.apache.org/repos/asf/qpid/${SVNPATH} - -WORKDIR=$(mktemp -d) -BASENAME=qpid-dispatch-${VERSION} -FILENAME=$PWD/${BASENAME}.tar.gz - -if [ -f $FILENAME ]; then rm -f $FILENAME; fi - -( -echo "Checking out to ${WORKDIR}..." -cd $WORKDIR -svn export -r ${SVNREV} ${URL}/extras/dispatch ${BASENAME} >/dev/null - -echo "Building source tarball..." -cd $WORKDIR -tar --exclude release.sh -zcvf $FILENAME ${BASENAME} >/dev/null -) - -echo "Done!" diff --git a/extras/dispatch/router/CMakeLists.txt b/extras/dispatch/router/CMakeLists.txt deleted file mode 100644 index 388e0d7119..0000000000 --- a/extras/dispatch/router/CMakeLists.txt +++ /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. -## - - -set(DEFAULT_CONFIG_PATH "/etc/qpid/qpid-dispatch.conf" CACHE string "Default Config File Path") - -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) - -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -## -## Build the router application -## -set(router_SOURCES - src/main.c - ) - -add_executable(dispatch-router ${router_SOURCES}) -target_link_libraries(dispatch-router qpid-dispatch ${proton_lib}) - -install(TARGETS dispatch-router RUNTIME DESTINATION bin) - diff --git a/extras/dispatch/router/src/config.h.in b/extras/dispatch/router/src/config.h.in deleted file mode 100644 index dab91c5004..0000000000 --- a/extras/dispatch/router/src/config.h.in +++ /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. - */ - -#cmakedefine DEFAULT_CONFIG_PATH "${DEFAULT_CONFIG_PATH}" - diff --git a/extras/dispatch/router/src/main.c b/extras/dispatch/router/src/main.c deleted file mode 100644 index e0d6849d1b..0000000000 --- a/extras/dispatch/router/src/main.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 <qpid/dispatch.h> -#include <signal.h> -#include <sys/types.h> -#include <unistd.h> -#include <getopt.h> -#include "config.h" - -static int exit_with_sigint = 0; -static dx_dispatch_t *dispatch; - - -/** - * The thread_start_handler is invoked once for each server thread at thread startup. - */ -static void thread_start_handler(void* context, int thread_id) -{ -} - - -/** - * This is the OS signal handler, invoked on an undetermined thread at a completely - * arbitrary point of time. It is not safe to do anything here but signal the dispatch - * server with the signal number. - */ -static void signal_handler(int signum) -{ - dx_server_signal(dispatch, signum); -} - - -/** - * This signal handler is called cleanly by one of the server's worker threads in - * response to an earlier call to dx_server_signal. - */ -static void server_signal_handler(void* context, int signum) -{ - dx_server_pause(dispatch); - - switch (signum) { - case SIGINT: - exit_with_sigint = 1; - - case SIGQUIT: - case SIGTERM: - fflush(stdout); - dx_server_stop(dispatch); - break; - - case SIGHUP: - break; - - default: - break; - } - - dx_server_resume(dispatch); -} - - -static void startup(void *context) -{ - dx_server_pause(dispatch); - dx_dispatch_configure(dispatch); - dx_server_resume(dispatch); -} - - -int main(int argc, char **argv) -{ - const char *config_path = DEFAULT_CONFIG_PATH; - - static struct option long_options[] = { - {"config", required_argument, 0, 'c'}, - {"help", no_argument, 0, 'h'}, - {0, 0, 0, 0} - }; - - while (1) { - int c = getopt_long(argc, argv, "c:h", long_options, 0); - if (c == -1) - break; - - switch (c) { - case 'c' : - config_path = optarg; - break; - - case 'h' : - printf("Usage: %s [OPTION]\n\n", argv[0]); - printf(" -c, --config=PATH (%s)\n", DEFAULT_CONFIG_PATH); - printf(" Load configuration from file at PATH\n"); - printf(" -h, --help Print this help\n"); - exit(0); - - case '?' : - exit(1); - } - } - - dx_log_set_mask(0xFFFFFFFE); - - dispatch = dx_dispatch(config_path); - - dx_server_set_signal_handler(dispatch, server_signal_handler, 0); - dx_server_set_start_handler(dispatch, thread_start_handler, 0); - - dx_timer_t *startup_timer = dx_timer(dispatch, startup, 0); - dx_timer_schedule(startup_timer, 0); - - signal(SIGHUP, signal_handler); - signal(SIGQUIT, signal_handler); - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - - dx_server_run(dispatch); - dx_dispatch_free(dispatch); - - if (exit_with_sigint) { - signal(SIGINT, SIG_DFL); - kill(getpid(), SIGINT); - } - - return 0; -} - diff --git a/extras/dispatch/src/agent.c b/extras/dispatch/src/agent.c deleted file mode 100644 index 784c333ec4..0000000000 --- a/extras/dispatch/src/agent.c +++ /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 "dispatch_private.h" -#include <qpid/dispatch/error.h> -#include <qpid/dispatch/agent.h> -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/hash.h> -#include <qpid/dispatch/container.h> -#include <qpid/dispatch/message.h> -#include <qpid/dispatch/threading.h> -#include <qpid/dispatch/timer.h> -#include <qpid/dispatch/router.h> -#include <qpid/dispatch/log.h> -#include <qpid/dispatch/compose.h> -#include <qpid/dispatch/parse.h> -#include <qpid/dispatch/amqp.h> -#include <string.h> -#include <stdio.h> - -struct dx_agent_class_t { - DEQ_LINKS(dx_agent_class_t); - dx_hash_handle_t *hash_handle; - void *context; - dx_agent_schema_cb_t schema_handler; - dx_agent_query_cb_t query_handler; // 0 iff class is an event. -}; - -DEQ_DECLARE(dx_agent_class_t, dx_agent_class_list_t); - - -struct dx_agent_t { - dx_dispatch_t *dx; - dx_hash_t *class_hash; - dx_agent_class_list_t class_list; - dx_message_list_t in_fifo; - dx_message_list_t out_fifo; - sys_mutex_t *lock; - dx_timer_t *timer; - dx_address_t *address; - dx_agent_class_t *container_class; -}; - - -typedef struct { - dx_agent_t *agent; - dx_composed_field_t *response; -} dx_agent_request_t; - - -static char *log_module = "AGENT"; - - -static dx_composed_field_t *dx_agent_setup_response(dx_field_iterator_t *reply_to) -{ - // - // Compose the header - // - dx_composed_field_t *field = dx_compose(DX_PERFORMATIVE_HEADER, 0); - dx_compose_start_list(field); - dx_compose_insert_bool(field, 0); // durable - dx_compose_end_list(field); - - // - // Compose the Properties - // - field = dx_compose(DX_PERFORMATIVE_PROPERTIES, field); - dx_compose_start_list(field); - dx_compose_insert_null(field); // message-id - dx_compose_insert_null(field); // user-id - dx_compose_insert_string_iterator(field, reply_to); // to - dx_compose_insert_null(field); // subject - dx_compose_insert_null(field); // reply-to - dx_compose_insert_string(field, "1"); // correlation-id // TODO - fix - dx_compose_end_list(field); - - // - // Compose the Application Properties - // - field = dx_compose(DX_PERFORMATIVE_APPLICATION_PROPERTIES, field); - dx_compose_start_map(field); - dx_compose_insert_string(field, "status-code"); - dx_compose_insert_uint(field, 200); - - dx_compose_insert_string(field, "status-descriptor"); - dx_compose_insert_string(field, "OK"); - dx_compose_end_map(field); - - return field; -} - - -static void dx_agent_process_get(dx_agent_t *agent, dx_parsed_field_t *map, dx_field_iterator_t *reply_to) -{ - dx_parsed_field_t *cls = dx_parse_value_by_key(map, "type"); - if (cls == 0) - return; - - dx_field_iterator_t *cls_string = dx_parse_raw(cls); - const dx_agent_class_t *cls_record; - dx_hash_retrieve_const(agent->class_hash, cls_string, (const void**) &cls_record); - if (cls_record == 0) - return; - - dx_log(log_module, LOG_TRACE, "Received GET request for type: %s", dx_hash_key_by_handle(cls_record->hash_handle)); - - dx_composed_field_t *field = dx_agent_setup_response(reply_to); - - // - // Open the Body (AMQP Value) to be filled in by the handler. - // - field = dx_compose(DX_PERFORMATIVE_BODY_AMQP_VALUE, field); - dx_compose_start_list(field); - dx_compose_start_map(field); - - // - // The request record is allocated locally because the entire processing of the request - // will be done synchronously. - // - dx_agent_request_t request; - request.agent = agent; - request.response = field; - - cls_record->query_handler(cls_record->context, 0, &request); - - // - // The response is complete, close the list. - // - dx_compose_end_list(field); - - // - // Create a message and send it. - // - dx_message_t *msg = dx_message(); - dx_message_compose_2(msg, field); - dx_router_send(agent->dx, reply_to, msg); - - dx_message_free(msg); - dx_compose_free(field); -} - - -static void dx_agent_process_discover_types(dx_agent_t *agent, dx_parsed_field_t *map, dx_field_iterator_t *reply_to) -{ - dx_log(log_module, LOG_TRACE, "Received DISCOVER-TYPES request"); - - dx_composed_field_t *field = dx_agent_setup_response(reply_to); - - // - // Open the Body (AMQP Value) to be filled in by the handler. - // - field = dx_compose(DX_PERFORMATIVE_BODY_AMQP_VALUE, field); - dx_compose_start_map(field); - - // - // Put entries into the map for each known entity type - // - sys_mutex_lock(agent->lock); - dx_agent_class_t *cls = DEQ_HEAD(agent->class_list); - while (cls) { - dx_compose_insert_string(field, (const char*) dx_hash_key_by_handle(cls->hash_handle)); - dx_compose_insert_null(field); // TODO - https://tools.oasis-open.org/issues/browse/AMQP-87 - cls = DEQ_NEXT(cls); - } - sys_mutex_unlock(agent->lock); - dx_compose_end_map(field); - - // - // Create a message and send it. - // - dx_message_t *msg = dx_message(); - dx_message_compose_2(msg, field); - dx_router_send(agent->dx, reply_to, msg); - - dx_message_free(msg); - dx_compose_free(field); -} - - -static void dx_agent_process_discover_operations(dx_agent_t *agent, dx_parsed_field_t *map, dx_field_iterator_t *reply_to) -{ - dx_log(log_module, LOG_TRACE, "Received DISCOVER-OPERATIONS request"); - - dx_composed_field_t *field = dx_agent_setup_response(reply_to); - - // - // Open the Body (AMQP Value) to be filled in by the handler. - // - field = dx_compose(DX_PERFORMATIVE_BODY_AMQP_VALUE, field); - dx_compose_start_map(field); - - // - // Put entries into the map for each known entity type - // - sys_mutex_lock(agent->lock); - dx_agent_class_t *cls = DEQ_HEAD(agent->class_list); - while (cls) { - dx_compose_insert_string(field, (const char*) dx_hash_key_by_handle(cls->hash_handle)); - dx_compose_start_list(field); - dx_compose_insert_string(field, "READ"); - dx_compose_end_list(field); - cls = DEQ_NEXT(cls); - } - sys_mutex_unlock(agent->lock); - dx_compose_end_map(field); - - // - // Create a message and send it. - // - dx_message_t *msg = dx_message(); - dx_message_compose_2(msg, field); - dx_router_send(agent->dx, reply_to, msg); - - dx_message_free(msg); - dx_compose_free(field); -} - - -static void dx_agent_process_discover_nodes(dx_agent_t *agent, dx_parsed_field_t *map, dx_field_iterator_t *reply_to) -{ - dx_log(log_module, LOG_TRACE, "Received DISCOVER-MGMT-NODES request"); - - dx_composed_field_t *field = dx_agent_setup_response(reply_to); - - // - // Open the Body (AMQP Value) to be filled in by the handler. - // - field = dx_compose(DX_PERFORMATIVE_BODY_AMQP_VALUE, field); - - // - // Put entries into the list for each known management node - // - dx_compose_start_list(field); - dx_compose_insert_string(field, "amqp:/_local/$management"); - dx_router_build_node_list(agent->dx, field); - dx_compose_end_list(field); - - // - // Create a message and send it. - // - dx_message_t *msg = dx_message(); - dx_message_compose_2(msg, field); - dx_router_send(agent->dx, reply_to, msg); - - dx_message_free(msg); - dx_compose_free(field); -} - - -static void dx_agent_process_request(dx_agent_t *agent, dx_message_t *msg) -{ - // - // Parse the message through the body and exit if the message is not well formed. - // - if (!dx_message_check(msg, DX_DEPTH_BODY)) - return; - - // - // Get an iterator for the application-properties. Exit if the message has none. - // - dx_field_iterator_t *ap = dx_message_field_iterator(msg, DX_FIELD_APPLICATION_PROPERTIES); - if (ap == 0) - return; - - // - // Get an iterator for the reply-to. Exit if not found. - // - dx_field_iterator_t *reply_to = dx_message_field_iterator(msg, DX_FIELD_REPLY_TO); - if (reply_to == 0) - return; - - // - // Try to get a map-view of the application-properties. - // - dx_parsed_field_t *map = dx_parse(ap); - if (map == 0) { - dx_field_iterator_free(ap); - return; - } - - // - // Exit if there was a parsing error. - // - if (!dx_parse_ok(map)) { - dx_log(log_module, LOG_TRACE, "Received unparsable App Properties: %s", dx_parse_error(map)); - dx_field_iterator_free(ap); - dx_parse_free(map); - return; - } - - // - // Exit if it is not a map. - // - if (!dx_parse_is_map(map)) { - dx_field_iterator_free(ap); - dx_parse_free(map); - return; - } - - // - // Get an iterator for the "operation" field in the map. Exit if the key is not found. - // - dx_parsed_field_t *operation = dx_parse_value_by_key(map, "operation"); - if (operation == 0) { - dx_parse_free(map); - dx_field_iterator_free(ap); - return; - } - - // - // Dispatch the operation to the appropriate handler - // - dx_field_iterator_t *operation_string = dx_parse_raw(operation); - if (dx_field_iterator_equal(operation_string, (unsigned char*) "GET")) - dx_agent_process_get(agent, map, reply_to); - if (dx_field_iterator_equal(operation_string, (unsigned char*) "DISCOVER-TYPES")) - dx_agent_process_discover_types(agent, map, reply_to); - if (dx_field_iterator_equal(operation_string, (unsigned char*) "DISCOVER-OPERATIONS")) - dx_agent_process_discover_operations(agent, map, reply_to); - if (dx_field_iterator_equal(operation_string, (unsigned char*) "DISCOVER-MGMT-NODES")) - dx_agent_process_discover_nodes(agent, map, reply_to); - - dx_parse_free(map); - dx_field_iterator_free(ap); - dx_field_iterator_free(reply_to); -} - - -static void dx_agent_deferred_handler(void *context) -{ - dx_agent_t *agent = (dx_agent_t*) context; - dx_message_t *msg; - - do { - sys_mutex_lock(agent->lock); - msg = DEQ_HEAD(agent->in_fifo); - if (msg) - DEQ_REMOVE_HEAD(agent->in_fifo); - sys_mutex_unlock(agent->lock); - - if (msg) { - dx_agent_process_request(agent, msg); - dx_message_free(msg); - } - } while (msg); -} - - -static void dx_agent_rx_handler(void *context, dx_message_t *msg, int unused_link_id) -{ - dx_agent_t *agent = (dx_agent_t*) context; - dx_message_t *copy = dx_message_copy(msg); - - sys_mutex_lock(agent->lock); - DEQ_INSERT_TAIL(agent->in_fifo, copy); - sys_mutex_unlock(agent->lock); - - dx_timer_schedule(agent->timer, 0); -} - - -static dx_agent_class_t *dx_agent_register_class_LH(dx_agent_t *agent, - const char *fqname, - void *context, - dx_agent_schema_cb_t schema_handler, - dx_agent_query_cb_t query_handler) -{ - dx_agent_class_t *cls = NEW(dx_agent_class_t); - assert(cls); - DEQ_ITEM_INIT(cls); - cls->context = context; - cls->schema_handler = schema_handler; - cls->query_handler = query_handler; - - dx_field_iterator_t *iter = dx_field_iterator_string(fqname, ITER_VIEW_ALL); - int result = dx_hash_insert_const(agent->class_hash, iter, cls, &cls->hash_handle); - dx_field_iterator_free(iter); - if (result < 0) - assert(false); - - DEQ_INSERT_TAIL(agent->class_list, cls); - - dx_log(log_module, LOG_INFO, "Manageable Entity Type (%s) %s", query_handler ? "object" : "event", fqname); - return cls; -} - - -dx_agent_t *dx_agent(dx_dispatch_t *dx) -{ - dx_agent_t *agent = NEW(dx_agent_t); - agent->dx = dx; - agent->class_hash = dx_hash(6, 10, 1); - DEQ_INIT(agent->class_list); - DEQ_INIT(agent->in_fifo); - DEQ_INIT(agent->out_fifo); - agent->lock = sys_mutex(); - agent->timer = dx_timer(dx, dx_agent_deferred_handler, agent); - agent->address = dx_router_register_address(dx, "$management", dx_agent_rx_handler, agent); - - return agent; -} - - -void dx_agent_free(dx_agent_t *agent) -{ - dx_router_unregister_address(agent->address); - sys_mutex_free(agent->lock); - dx_timer_free(agent->timer); - dx_hash_free(agent->class_hash); - free(agent); -} - - -dx_agent_class_t *dx_agent_register_class(dx_dispatch_t *dx, - const char *fqname, - void *context, - dx_agent_schema_cb_t schema_handler, - dx_agent_query_cb_t query_handler) -{ - dx_agent_t *agent = dx->agent; - dx_agent_class_t *cls; - - sys_mutex_lock(agent->lock); - cls = dx_agent_register_class_LH(agent, fqname, context, schema_handler, query_handler); - sys_mutex_unlock(agent->lock); - return cls; -} - - -dx_agent_class_t *dx_agent_register_event(dx_dispatch_t *dx, - const char *fqname, - void *context, - dx_agent_schema_cb_t schema_handler) -{ - return dx_agent_register_class(dx, fqname, context, schema_handler, 0); -} - - -void dx_agent_value_string(void *correlator, const char *key, const char *value) -{ - dx_agent_request_t *request = (dx_agent_request_t*) correlator; - dx_compose_insert_string(request->response, key); - dx_compose_insert_string(request->response, value); -} - - -void dx_agent_value_uint(void *correlator, const char *key, uint64_t value) -{ - dx_agent_request_t *request = (dx_agent_request_t*) correlator; - dx_compose_insert_string(request->response, key); - dx_compose_insert_uint(request->response, value); -} - - -void dx_agent_value_null(void *correlator, const char *key) -{ - dx_agent_request_t *request = (dx_agent_request_t*) correlator; - dx_compose_insert_string(request->response, key); - dx_compose_insert_null(request->response); -} - - -void dx_agent_value_boolean(void *correlator, const char *key, bool value) -{ - dx_agent_request_t *request = (dx_agent_request_t*) correlator; - dx_compose_insert_string(request->response, key); - dx_compose_insert_bool(request->response, value); -} - - -void dx_agent_value_binary(void *correlator, const char *key, const uint8_t *value, size_t len) -{ - dx_agent_request_t *request = (dx_agent_request_t*) correlator; - dx_compose_insert_string(request->response, key); - dx_compose_insert_binary(request->response, value, len); -} - - -void dx_agent_value_uuid(void *correlator, const char *key, const uint8_t *value) -{ - dx_agent_request_t *request = (dx_agent_request_t*) correlator; - dx_compose_insert_string(request->response, key); - dx_compose_insert_uuid(request->response, value); -} - - -void dx_agent_value_timestamp(void *correlator, const char *key, uint64_t value) -{ - dx_agent_request_t *request = (dx_agent_request_t*) correlator; - dx_compose_insert_string(request->response, key); - dx_compose_insert_timestamp(request->response, value); -} - - -void dx_agent_value_complete(void *correlator, bool more) -{ - dx_agent_request_t *request = (dx_agent_request_t*) correlator; - dx_compose_end_map(request->response); - if (more) - dx_compose_start_map(request->response); -} - - -void *dx_agent_raise_event(dx_dispatch_t *dx, dx_agent_class_t *event) -{ - return 0; -} - diff --git a/extras/dispatch/src/alloc.c b/extras/dispatch/src/alloc.c deleted file mode 100644 index bf10f03633..0000000000 --- a/extras/dispatch/src/alloc.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/log.h> -#include <qpid/dispatch/agent.h> -#include <memory.h> -#include <stdio.h> - -typedef struct dx_alloc_type_t dx_alloc_type_t; -typedef struct dx_alloc_item_t dx_alloc_item_t; - -struct dx_alloc_type_t { - DEQ_LINKS(dx_alloc_type_t); - dx_alloc_type_desc_t *desc; -}; - -DEQ_DECLARE(dx_alloc_type_t, dx_alloc_type_list_t); - - -struct dx_alloc_item_t { - DEQ_LINKS(dx_alloc_item_t); -}; - -DEQ_DECLARE(dx_alloc_item_t, dx_alloc_item_list_t); - - -struct dx_alloc_pool_t { - dx_alloc_item_list_t free_list; -}; - -dx_alloc_config_t dx_alloc_default_config_big = {16, 32, 0}; -dx_alloc_config_t dx_alloc_default_config_small = {64, 128, 0}; -#define BIG_THRESHOLD 256 - -static sys_mutex_t *init_lock; -static dx_alloc_type_list_t type_list; - -static void dx_alloc_init(dx_alloc_type_desc_t *desc) -{ - sys_mutex_lock(init_lock); - - desc->total_size = desc->type_size; - if (desc->additional_size) - desc->total_size += *desc->additional_size; - - //dx_log("ALLOC", LOG_TRACE, "Initialized Allocator - type=%s type-size=%d total-size=%d", - // desc->type_name, desc->type_size, desc->total_size); - - if (!desc->global_pool) { - if (desc->config == 0) - desc->config = desc->total_size > BIG_THRESHOLD ? - &dx_alloc_default_config_big : &dx_alloc_default_config_small; - - assert (desc->config->local_free_list_max >= desc->config->transfer_batch_size); - - desc->global_pool = NEW(dx_alloc_pool_t); - DEQ_INIT(desc->global_pool->free_list); - desc->lock = sys_mutex(); - desc->stats = NEW(dx_alloc_stats_t); - memset(desc->stats, 0, sizeof(dx_alloc_stats_t)); - - dx_alloc_type_t *type_item = NEW(dx_alloc_type_t); - DEQ_ITEM_INIT(type_item); - type_item->desc = desc; - DEQ_INSERT_TAIL(type_list, type_item); - } - - sys_mutex_unlock(init_lock); -} - - -void *dx_alloc(dx_alloc_type_desc_t *desc, dx_alloc_pool_t **tpool) -{ - int idx; - - // - // If the descriptor is not initialized, set it up now. - // - if (!desc->global_pool) - dx_alloc_init(desc); - - // - // If this is the thread's first pass through here, allocate the - // thread-local pool for this type. - // - if (*tpool == 0) { - *tpool = NEW(dx_alloc_pool_t); - DEQ_INIT((*tpool)->free_list); - } - - dx_alloc_pool_t *pool = *tpool; - - // - // Fast case: If there's an item on the local free list, take it off the - // list and return it. Since everything we've touched is thread-local, - // there is no need to acquire a lock. - // - dx_alloc_item_t *item = DEQ_HEAD(pool->free_list); - if (item) { - DEQ_REMOVE_HEAD(pool->free_list); - return &item[1]; - } - - // - // The local free list is empty, we need to either rebalance a batch - // of items from the global list or go to the heap to get new memory. - // - sys_mutex_lock(desc->lock); - if (DEQ_SIZE(desc->global_pool->free_list) >= desc->config->transfer_batch_size) { - // - // Rebalance a full batch from the global free list to the thread list. - // - desc->stats->batches_rebalanced_to_threads++; - desc->stats->held_by_threads += desc->config->transfer_batch_size; - for (idx = 0; idx < desc->config->transfer_batch_size; idx++) { - item = DEQ_HEAD(desc->global_pool->free_list); - DEQ_REMOVE_HEAD(desc->global_pool->free_list); - DEQ_INSERT_TAIL(pool->free_list, item); - } - } else { - // - // Allocate a full batch from the heap and put it on the thread list. - // - for (idx = 0; idx < desc->config->transfer_batch_size; idx++) { - item = (dx_alloc_item_t*) malloc(sizeof(dx_alloc_item_t) + desc->total_size); - if (item == 0) - break; - DEQ_ITEM_INIT(item); - DEQ_INSERT_TAIL(pool->free_list, item); - desc->stats->held_by_threads++; - desc->stats->total_alloc_from_heap++; - } - } - sys_mutex_unlock(desc->lock); - - item = DEQ_HEAD(pool->free_list); - if (item) { - DEQ_REMOVE_HEAD(pool->free_list); - return &item[1]; - } - - return 0; -} - - -void dx_dealloc(dx_alloc_type_desc_t *desc, dx_alloc_pool_t **tpool, void *p) -{ - dx_alloc_item_t *item = ((dx_alloc_item_t*) p) - 1; - int idx; - - // - // If this is the thread's first pass through here, allocate the - // thread-local pool for this type. - // - if (*tpool == 0) { - *tpool = NEW(dx_alloc_pool_t); - DEQ_INIT((*tpool)->free_list); - } - - dx_alloc_pool_t *pool = *tpool; - - DEQ_INSERT_TAIL(pool->free_list, item); - - if (DEQ_SIZE(pool->free_list) <= desc->config->local_free_list_max) - return; - - // - // We've exceeded the maximum size of the local free list. A batch must be - // rebalanced back to the global list. - // - sys_mutex_lock(desc->lock); - desc->stats->batches_rebalanced_to_global++; - desc->stats->held_by_threads -= desc->config->transfer_batch_size; - for (idx = 0; idx < desc->config->transfer_batch_size; idx++) { - item = DEQ_HEAD(pool->free_list); - DEQ_REMOVE_HEAD(pool->free_list); - DEQ_INSERT_TAIL(desc->global_pool->free_list, item); - } - - // - // If there's a global_free_list size limit, remove items until the limit is - // not exceeded. - // - if (desc->config->global_free_list_max != 0) { - while (DEQ_SIZE(desc->global_pool->free_list) > desc->config->global_free_list_max) { - item = DEQ_HEAD(desc->global_pool->free_list); - DEQ_REMOVE_HEAD(desc->global_pool->free_list); - free(item); - desc->stats->total_free_to_heap++; - } - } - - sys_mutex_unlock(desc->lock); -} - - -void dx_alloc_initialize(void) -{ - init_lock = sys_mutex(); - DEQ_INIT(type_list); -} - - -static void alloc_schema_handler(void *context, void *correlator) -{ -} - - -static void alloc_query_handler(void* context, const char *id, void *cor) -{ - dx_alloc_type_t *item = DEQ_HEAD(type_list); - - while (item) { - dx_agent_value_string(cor, "name", item->desc->type_name); - dx_agent_value_uint(cor, "type_size", item->desc->total_size); - dx_agent_value_uint(cor, "transfer_batch_size", item->desc->config->transfer_batch_size); - dx_agent_value_uint(cor, "local_free_list_max", item->desc->config->local_free_list_max); - dx_agent_value_uint(cor, "global_free_list_max", item->desc->config->global_free_list_max); - dx_agent_value_uint(cor, "total_alloc_from_heap", item->desc->stats->total_alloc_from_heap); - dx_agent_value_uint(cor, "total_free_to_heap", item->desc->stats->total_free_to_heap); - dx_agent_value_uint(cor, "held_by_threads", item->desc->stats->held_by_threads); - dx_agent_value_uint(cor, "batches_rebalanced_to_threads", item->desc->stats->batches_rebalanced_to_threads); - dx_agent_value_uint(cor, "batches_rebalanced_to_global", item->desc->stats->batches_rebalanced_to_global); - - item = DEQ_NEXT(item); - dx_agent_value_complete(cor, item != 0); - } -} - - -void dx_alloc_setup_agent(dx_dispatch_t *dx) -{ - dx_agent_register_class(dx, "org.apache.qpid.dispatch.allocator", 0, alloc_schema_handler, alloc_query_handler); -} - diff --git a/extras/dispatch/src/alloc_private.h b/extras/dispatch/src/alloc_private.h deleted file mode 100644 index da773fef25..0000000000 --- a/extras/dispatch/src/alloc_private.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __dispatch_alloc_private_h__ -#define __dispatch_alloc_private_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/dispatch.h> - -void dx_alloc_initialize(void); -void dx_alloc_setup_agent(dx_dispatch_t *dx); - -#endif diff --git a/extras/dispatch/src/amqp.c b/extras/dispatch/src/amqp.c deleted file mode 100644 index 6a8545b757..0000000000 --- a/extras/dispatch/src/amqp.c +++ /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/dispatch/amqp.h> - -const char * const DX_DA_INGRESS = "qdx.ingress"; -const char * const DX_DA_TRACE = "qdx.trace"; -const char * const DX_DA_TO = "qdx.to"; - -const char * const DX_CAPABILITY_ROUTER = "qdx.router"; - -const char * const DX_INTERNODE_LINK_NAME_1 = "qdx.internode.1"; -const char * const DX_INTERNODE_LINK_NAME_2 = "qdx.internode.2"; - diff --git a/extras/dispatch/src/bitmask.c b/extras/dispatch/src/bitmask.c deleted file mode 100644 index 88ba69dde1..0000000000 --- a/extras/dispatch/src/bitmask.c +++ /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/dispatch/bitmask.h> -#include <qpid/dispatch/alloc.h> -#include <assert.h> - -#define DX_BITMASK_LONGS 16 -#define DX_BITMASK_BITS (DX_BITMASK_LONGS * 64) - -struct dx_bitmask_t { - uint64_t array[DX_BITMASK_LONGS]; - int first_set; -}; - -ALLOC_DECLARE(dx_bitmask_t); -ALLOC_DEFINE(dx_bitmask_t); - -#define MASK_INDEX(num) (num / 64) -#define MASK_ONEHOT(num) (((uint64_t) 1) << (num % 64)) -#define FIRST_NONE -1 -#define FIRST_UNKNOWN -2 - - -int dx_bitmask_width() -{ - return DX_BITMASK_BITS; -} - - -dx_bitmask_t *dx_bitmask(int initial) -{ - dx_bitmask_t *b = new_dx_bitmask_t(); - if (initial) - dx_bitmask_set_all(b); - else - dx_bitmask_clear_all(b); - return b; -} - - -void dx_bitmask_free(dx_bitmask_t *b) -{ - free_dx_bitmask_t(b); -} - - -void dx_bitmask_set_all(dx_bitmask_t *b) -{ - for (int i = 0; i < DX_BITMASK_LONGS; i++) - b->array[i] = 0xFFFFFFFFFFFFFFFF; - b->first_set = 0; -} - - -void dx_bitmask_clear_all(dx_bitmask_t *b) -{ - for (int i = 0; i < DX_BITMASK_LONGS; i++) - b->array[i] = 0; - b->first_set = FIRST_NONE; -} - - -void dx_bitmask_set_bit(dx_bitmask_t *b, int bitnum) -{ - assert(bitnum < DX_BITMASK_BITS); - b->array[MASK_INDEX(bitnum)] |= MASK_ONEHOT(bitnum); - if (b->first_set > bitnum || b->first_set < 0) - b->first_set = bitnum; -} - - -void dx_bitmask_clear_bit(dx_bitmask_t *b, int bitnum) -{ - assert(bitnum < DX_BITMASK_BITS); - b->array[MASK_INDEX(bitnum)] &= ~(MASK_ONEHOT(bitnum)); - if (b->first_set == bitnum) - b->first_set = FIRST_UNKNOWN; -} - - -int dx_bitmask_value(dx_bitmask_t *b, int bitnum) -{ - return (b->array[MASK_INDEX(bitnum)] & MASK_ONEHOT(bitnum)) ? 1 : 0; -} - - -int dx_bitmask_first_set(dx_bitmask_t *b, int *bitnum) -{ - if (b->first_set == FIRST_UNKNOWN) { - b->first_set = FIRST_NONE; - for (int i = 0; i < DX_BITMASK_LONGS; i++) - if (b->array[i]) { - for (int j = 0; j < 64; j++) - if ((((uint64_t) 1) << j) & b->array[i]) { - b->first_set = i * 64 + j; - break; - } - break; - } - } - - if (b->first_set == FIRST_NONE) - return 0; - *bitnum = b->first_set; - return 1; -} - diff --git a/extras/dispatch/src/buffer.c b/extras/dispatch/src/buffer.c deleted file mode 100644 index d0bbd13cb3..0000000000 --- a/extras/dispatch/src/buffer.c +++ /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/dispatch/buffer.h> -#include <qpid/dispatch/alloc.h> - -static size_t buffer_size = 512; -static int size_locked = 0; - -ALLOC_DECLARE(dx_buffer_t); -ALLOC_DEFINE_CONFIG(dx_buffer_t, sizeof(dx_buffer_t), &buffer_size, 0); - - -void dx_buffer_set_size(size_t size) -{ - assert(!size_locked); - buffer_size = size; -} - - -dx_buffer_t *dx_buffer(void) -{ - size_locked = 1; - dx_buffer_t *buf = new_dx_buffer_t(); - - DEQ_ITEM_INIT(buf); - buf->size = 0; - return buf; -} - - -void dx_buffer_free(dx_buffer_t *buf) -{ - free_dx_buffer_t(buf); -} - - -unsigned char *dx_buffer_base(dx_buffer_t *buf) -{ - return (unsigned char*) &buf[1]; -} - - -unsigned char *dx_buffer_cursor(dx_buffer_t *buf) -{ - return ((unsigned char*) &buf[1]) + buf->size; -} - - -size_t dx_buffer_capacity(dx_buffer_t *buf) -{ - return buffer_size - buf->size; -} - - -size_t dx_buffer_size(dx_buffer_t *buf) -{ - return buf->size; -} - - -void dx_buffer_insert(dx_buffer_t *buf, size_t len) -{ - buf->size += len; - assert(buf->size <= buffer_size); -} - diff --git a/extras/dispatch/src/compose.c b/extras/dispatch/src/compose.c deleted file mode 100644 index 66b2336e06..0000000000 --- a/extras/dispatch/src/compose.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/buffer.h> -#include <qpid/dispatch/amqp.h> -#include "compose_private.h" -#include <memory.h> - -ALLOC_DEFINE(dx_composite_t); -ALLOC_DEFINE(dx_composed_field_t); - - -static void bump_count(dx_composed_field_t *field) -{ - dx_composite_t *comp = DEQ_HEAD(field->fieldStack); - if (comp) - comp->count++; -} - - -static void dx_insert(dx_composed_field_t *field, const uint8_t *seq, size_t len) -{ - dx_buffer_t *buf = DEQ_TAIL(field->buffers); - dx_composite_t *comp = DEQ_HEAD(field->fieldStack); - - while (len > 0) { - if (buf == 0 || dx_buffer_capacity(buf) == 0) { - buf = dx_buffer(); - if (buf == 0) - return; - DEQ_INSERT_TAIL(field->buffers, buf); - } - - size_t to_copy = dx_buffer_capacity(buf); - if (to_copy > len) - to_copy = len; - memcpy(dx_buffer_cursor(buf), seq, to_copy); - dx_buffer_insert(buf, to_copy); - len -= to_copy; - seq += to_copy; - if (comp) - comp->length += to_copy; - } -} - - -static void dx_insert_8(dx_composed_field_t *field, uint8_t value) -{ - dx_insert(field, &value, 1); -} - - -static void dx_insert_32(dx_composed_field_t *field, uint32_t value) -{ - uint8_t buf[4]; - buf[0] = (uint8_t) ((value & 0xFF000000) >> 24); - buf[1] = (uint8_t) ((value & 0x00FF0000) >> 16); - buf[2] = (uint8_t) ((value & 0x0000FF00) >> 8); - buf[3] = (uint8_t) (value & 0x000000FF); - dx_insert(field, buf, 4); -} - - -static void dx_insert_64(dx_composed_field_t *field, uint64_t value) -{ - uint8_t buf[8]; - buf[0] = (uint8_t) ((value & 0xFF00000000000000L) >> 56); - buf[1] = (uint8_t) ((value & 0x00FF000000000000L) >> 48); - buf[2] = (uint8_t) ((value & 0x0000FF0000000000L) >> 40); - buf[3] = (uint8_t) ((value & 0x000000FF00000000L) >> 32); - buf[4] = (uint8_t) ((value & 0x00000000FF000000L) >> 24); - buf[5] = (uint8_t) ((value & 0x0000000000FF0000L) >> 16); - buf[6] = (uint8_t) ((value & 0x000000000000FF00L) >> 8); - buf[7] = (uint8_t) (value & 0x00000000000000FFL); - dx_insert(field, buf, 8); -} - - -static void dx_overwrite(dx_buffer_t **buf, size_t *cursor, uint8_t value) -{ - while (*buf) { - if (*cursor >= dx_buffer_size(*buf)) { - *buf = (*buf)->next; - *cursor = 0; - } else { - dx_buffer_base(*buf)[*cursor] = value; - (*cursor)++; - return; - } - } -} - - -static void dx_overwrite_32(dx_field_location_t *field, uint32_t value) -{ - dx_buffer_t *buf = field->buffer; - size_t cursor = field->offset; - - dx_overwrite(&buf, &cursor, (uint8_t) ((value & 0xFF000000) >> 24)); - dx_overwrite(&buf, &cursor, (uint8_t) ((value & 0x00FF0000) >> 16)); - dx_overwrite(&buf, &cursor, (uint8_t) ((value & 0x0000FF00) >> 8)); - dx_overwrite(&buf, &cursor, (uint8_t) (value & 0x000000FF)); -} - - -static void dx_compose_start_composite(dx_composed_field_t *field, int isMap) -{ - if (isMap) - dx_insert_8(field, DX_AMQP_MAP32); - else - dx_insert_8(field, DX_AMQP_LIST32); - - // - // Push a composite descriptor on the field stack - // - dx_composite_t *comp = new_dx_composite_t(); - DEQ_ITEM_INIT(comp); - comp->isMap = isMap; - - // - // Mark the current location to later overwrite the length - // - comp->length_location.buffer = DEQ_TAIL(field->buffers); - comp->length_location.offset = dx_buffer_size(comp->length_location.buffer); - comp->length_location.length = 4; - comp->length_location.parsed = 1; - - dx_insert(field, (const uint8_t*) "\x00\x00\x00\x00", 4); - - // - // Mark the current location to later overwrite the count - // - comp->count_location.buffer = DEQ_TAIL(field->buffers); - comp->count_location.offset = dx_buffer_size(comp->count_location.buffer); - comp->count_location.length = 4; - comp->count_location.parsed = 1; - - dx_insert(field, (const uint8_t*) "\x00\x00\x00\x00", 4); - - comp->length = 4; // Include the length of the count field - comp->count = 0; - - DEQ_INSERT_HEAD(field->fieldStack, comp); -} - - -static void dx_compose_end_composite(dx_composed_field_t *field) -{ - dx_composite_t *comp = DEQ_HEAD(field->fieldStack); - assert(comp); - - dx_overwrite_32(&comp->length_location, comp->length); - dx_overwrite_32(&comp->count_location, comp->count); - - DEQ_REMOVE_HEAD(field->fieldStack); - - // - // If there is an enclosing composite, update its length and count - // - dx_composite_t *enclosing = DEQ_HEAD(field->fieldStack); - if (enclosing) { - enclosing->length += (comp->length - 4); // the length and count were already accounted for - enclosing->count++; - } - - free_dx_composite_t(comp); -} - - -dx_composed_field_t *dx_compose(uint64_t performative, dx_composed_field_t *extend) -{ - dx_composed_field_t *field = extend; - - if (field) { - assert(DEQ_SIZE(field->fieldStack) == 0); - } else { - field = new_dx_composed_field_t(); - if (!field) - return 0; - - DEQ_INIT(field->buffers); - DEQ_INIT(field->fieldStack); - } - - dx_insert_8(field, 0x00); - dx_compose_insert_ulong(field, performative); - - return field; -} - - -void dx_compose_free(dx_composed_field_t *field) -{ - dx_buffer_t *buf = DEQ_HEAD(field->buffers); - while (buf) { - DEQ_REMOVE_HEAD(field->buffers); - dx_buffer_free(buf); - buf = DEQ_HEAD(field->buffers); - } - - dx_composite_t *comp = DEQ_HEAD(field->fieldStack); - while (comp) { - DEQ_REMOVE_HEAD(field->fieldStack); - free_dx_composite_t(comp); - comp = DEQ_HEAD(field->fieldStack); - } - - free_dx_composed_field_t(field); -} - - -void dx_compose_start_list(dx_composed_field_t *field) -{ - dx_compose_start_composite(field, 0); -} - - -void dx_compose_end_list(dx_composed_field_t *field) -{ - dx_compose_end_composite(field); -} - - -void dx_compose_start_map(dx_composed_field_t *field) -{ - dx_compose_start_composite(field, 1); -} - - -void dx_compose_end_map(dx_composed_field_t *field) -{ - dx_compose_end_composite(field); -} - - -void dx_compose_insert_null(dx_composed_field_t *field) -{ - dx_insert_8(field, DX_AMQP_NULL); - bump_count(field); -} - - -void dx_compose_insert_bool(dx_composed_field_t *field, int value) -{ - dx_insert_8(field, value ? DX_AMQP_TRUE : DX_AMQP_FALSE); - bump_count(field); -} - - -void dx_compose_insert_uint(dx_composed_field_t *field, uint32_t value) -{ - if (value == 0) { - dx_insert_8(field, DX_AMQP_UINT0); - } else if (value < 256) { - dx_insert_8(field, DX_AMQP_SMALLUINT); - dx_insert_8(field, (uint8_t) value); - } else { - dx_insert_8(field, DX_AMQP_UINT); - dx_insert_32(field, value); - } - bump_count(field); -} - - -void dx_compose_insert_ulong(dx_composed_field_t *field, uint64_t value) -{ - if (value == 0) { - dx_insert_8(field, DX_AMQP_ULONG0); - } else if (value < 256) { - dx_insert_8(field, DX_AMQP_SMALLULONG); - dx_insert_8(field, (uint8_t) value); - } else { - dx_insert_8(field, DX_AMQP_ULONG); - dx_insert_64(field, value); - } - bump_count(field); -} - - -void dx_compose_insert_int(dx_composed_field_t *field, int32_t value) -{ - if (value >= -128 && value <= 127) { - dx_insert_8(field, DX_AMQP_SMALLINT); - dx_insert_8(field, (uint8_t) value); - } else { - dx_insert_8(field, DX_AMQP_INT); - dx_insert_32(field, (uint32_t) value); - } - bump_count(field); -} - - -void dx_compose_insert_long(dx_composed_field_t *field, int64_t value) -{ - if (value >= -128 && value <= 127) { - dx_insert_8(field, DX_AMQP_SMALLLONG); - dx_insert_8(field, (uint8_t) value); - } else { - dx_insert_8(field, DX_AMQP_LONG); - dx_insert_64(field, (uint64_t) value); - } - bump_count(field); -} - - -void dx_compose_insert_timestamp(dx_composed_field_t *field, uint64_t value) -{ - dx_insert_8(field, DX_AMQP_TIMESTAMP); - dx_insert_64(field, value); - bump_count(field); -} - - -void dx_compose_insert_uuid(dx_composed_field_t *field, const uint8_t *value) -{ - dx_insert_8(field, DX_AMQP_UUID); - dx_insert(field, value, 16); - bump_count(field); -} - - -void dx_compose_insert_binary(dx_composed_field_t *field, const uint8_t *value, uint32_t len) -{ - if (len < 256) { - dx_insert_8(field, DX_AMQP_VBIN8); - dx_insert_8(field, (uint8_t) len); - } else { - dx_insert_8(field, DX_AMQP_VBIN32); - dx_insert_32(field, len); - } - dx_insert(field, value, len); - bump_count(field); -} - - -void dx_compose_insert_binary_buffers(dx_composed_field_t *field, dx_buffer_list_t *buffers) -{ - dx_buffer_t *buf = DEQ_HEAD(*buffers); - uint32_t len = 0; - - // - // Calculate the size of the binary field to be appended. - // - while (buf) { - len += dx_buffer_size(buf); - buf = DEQ_NEXT(buf); - } - - // - // Supply the appropriate binary tag for the length. - // - if (len < 256) { - dx_insert_8(field, DX_AMQP_VBIN8); - dx_insert_8(field, (uint8_t) len); - } else { - dx_insert_8(field, DX_AMQP_VBIN32); - dx_insert_32(field, len); - } - - // - // Move the supplied buffers to the tail of the field's buffer list. - // - buf = DEQ_HEAD(*buffers); - while (buf) { - DEQ_REMOVE_HEAD(*buffers); - DEQ_INSERT_TAIL(field->buffers, buf); - buf = DEQ_HEAD(*buffers); - } -} - - -void dx_compose_insert_string(dx_composed_field_t *field, const char *value) -{ - uint32_t len = strlen(value); - - if (len < 256) { - dx_insert_8(field, DX_AMQP_STR8_UTF8); - dx_insert_8(field, (uint8_t) len); - } else { - dx_insert_8(field, DX_AMQP_STR32_UTF8); - dx_insert_32(field, len); - } - dx_insert(field, (const uint8_t*) value, len); - bump_count(field); -} - - -void dx_compose_insert_string_iterator(dx_composed_field_t *field, dx_field_iterator_t *iter) -{ - uint32_t len = 0; - - while (!dx_field_iterator_end(iter)) { - dx_field_iterator_octet(iter); - len++; - } - - dx_field_iterator_reset(iter); - - if (len < 256) { - dx_insert_8(field, DX_AMQP_STR8_UTF8); - dx_insert_8(field, (uint8_t) len); - } else { - dx_insert_8(field, DX_AMQP_STR32_UTF8); - dx_insert_32(field, len); - } - - while (!dx_field_iterator_end(iter)) { - uint8_t octet = dx_field_iterator_octet(iter); - dx_insert_8(field, octet); - } - - bump_count(field); -} - - -void dx_compose_insert_symbol(dx_composed_field_t *field, const char *value) -{ - uint32_t len = strlen(value); - - if (len < 256) { - dx_insert_8(field, DX_AMQP_SYM8); - dx_insert_8(field, (uint8_t) len); - } else { - dx_insert_8(field, DX_AMQP_SYM32); - dx_insert_32(field, len); - } - dx_insert(field, (const uint8_t*) value, len); - bump_count(field); -} - - -dx_buffer_list_t *dx_compose_buffers(dx_composed_field_t *field) -{ - return &field->buffers; -} - diff --git a/extras/dispatch/src/compose_private.h b/extras/dispatch/src/compose_private.h deleted file mode 100644 index 6e72185f3c..0000000000 --- a/extras/dispatch/src/compose_private.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __compose_private_h__ -#define __compose_private_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/compose.h> -#include "message_private.h" - -dx_buffer_list_t *dx_compose_buffers(dx_composed_field_t *field); - -typedef struct dx_composite_t { - DEQ_LINKS(struct dx_composite_t); - int isMap; - uint32_t count; - uint32_t length; - dx_field_location_t length_location; - dx_field_location_t count_location; -} dx_composite_t; - -ALLOC_DECLARE(dx_composite_t); -DEQ_DECLARE(dx_composite_t, dx_field_stack_t); - - -struct dx_composed_field_t { - dx_buffer_list_t buffers; - dx_field_stack_t fieldStack; -}; - -ALLOC_DECLARE(dx_composed_field_t); - -#endif diff --git a/extras/dispatch/src/config.c b/extras/dispatch/src/config.c deleted file mode 100644 index 9390115251..0000000000 --- a/extras/dispatch/src/config.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/python_embedded.h> -#include "config_private.h" -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/log.h> - -#define PYTHON_MODULE "qpid.dispatch.config" - -static const char *log_module = "CONFIG"; - -struct dx_config_t { - PyObject *pModule; - PyObject *pClass; - PyObject *pObject; -}; - -ALLOC_DECLARE(dx_config_t); -ALLOC_DEFINE(dx_config_t); - -void dx_config_initialize() -{ - dx_python_start(); -} - - -void dx_config_finalize() -{ - dx_python_stop(); -} - - -dx_config_t *dx_config(const char *filename) -{ - dx_config_t *config = new_dx_config_t(); - - // - // Load the Python configuration module and get a reference to the config class. - // - PyObject *pName = PyString_FromString(PYTHON_MODULE); - config->pModule = PyImport_Import(pName); - Py_DECREF(pName); - - if (!config->pModule) { - PyErr_Print(); - free_dx_config_t(config); - dx_log(log_module, LOG_ERROR, "Unable to load configuration module: %s", PYTHON_MODULE); - return 0; - } - - config->pClass = PyObject_GetAttrString(config->pModule, "DXConfig"); - if (!config->pClass || !PyClass_Check(config->pClass)) { - PyErr_Print(); - Py_DECREF(config->pModule); - free_dx_config_t(config); - dx_log(log_module, LOG_ERROR, "Problem with configuration module: Missing DXConfig class"); - return 0; - } - - // - // Instantiate the DXConfig class, passing in the configuration file name. - // - PyObject *pArgs = PyTuple_New(1); - PyObject *fname = PyString_FromString(filename); - PyTuple_SetItem(pArgs, 0, fname); - config->pObject = PyInstance_New(config->pClass, pArgs, 0); - Py_DECREF(pArgs); - - if (config->pObject == 0) { - PyErr_Print(); - Py_DECREF(config->pModule); - free_dx_config_t(config); - dx_log(log_module, LOG_ERROR, "Configuration file '%s' could not be read", filename); - return 0; - } - - return config; -} - - -void dx_config_read(dx_config_t *config) -{ - PyObject *pMethod; - PyObject *pArgs; - PyObject *pResult; - - if (!config) - return; - - pMethod = PyObject_GetAttrString(config->pObject, "read_file"); - if (!pMethod || !PyCallable_Check(pMethod)) { - dx_log(log_module, LOG_ERROR, "Problem with configuration module: No callable 'item_count'"); - if (pMethod) { - Py_DECREF(pMethod); - } - return; - } - - pArgs = PyTuple_New(0); - pResult = PyObject_CallObject(pMethod, pArgs); - Py_DECREF(pArgs); - if (pResult) { - Py_DECREF(pResult); - } else { - PyErr_Print(); - } - Py_DECREF(pMethod); -} - - -void dx_config_free(dx_config_t *config) -{ - if (config) { - Py_DECREF(config->pClass); - Py_DECREF(config->pModule); - free_dx_config_t(config); - } -} - - -int dx_config_item_count(const dx_config_t *config, const char *section) -{ - PyObject *pSection; - PyObject *pMethod; - PyObject *pArgs; - PyObject *pResult; - int result = 0; - - if (!config) - return 0; - - pMethod = PyObject_GetAttrString(config->pObject, "item_count"); - if (!pMethod || !PyCallable_Check(pMethod)) { - dx_log(log_module, LOG_ERROR, "Problem with configuration module: No callable 'item_count'"); - if (pMethod) { - Py_DECREF(pMethod); - } - return 0; - } - - pSection = PyString_FromString(section); - pArgs = PyTuple_New(1); - PyTuple_SetItem(pArgs, 0, pSection); - pResult = PyObject_CallObject(pMethod, pArgs); - Py_DECREF(pArgs); - if (pResult && PyInt_Check(pResult)) - result = (int) PyInt_AsLong(pResult); - if (pResult) { - Py_DECREF(pResult); - } - Py_DECREF(pMethod); - - return result; -} - - -static PyObject *item_value(const dx_config_t *config, const char *section, int index, const char* key, const char* method) -{ - PyObject *pSection; - PyObject *pIndex; - PyObject *pKey; - PyObject *pMethod; - PyObject *pArgs; - PyObject *pResult; - - if (!config) - return 0; - - pMethod = PyObject_GetAttrString(config->pObject, method); - if (!pMethod || !PyCallable_Check(pMethod)) { - dx_log(log_module, LOG_ERROR, "Problem with configuration module: No callable '%s'", method); - if (pMethod) { - Py_DECREF(pMethod); - } - return 0; - } - - pSection = PyString_FromString(section); - pIndex = PyInt_FromLong((long) index); - pKey = PyString_FromString(key); - pArgs = PyTuple_New(3); - PyTuple_SetItem(pArgs, 0, pSection); - PyTuple_SetItem(pArgs, 1, pIndex); - PyTuple_SetItem(pArgs, 2, pKey); - pResult = PyObject_CallObject(pMethod, pArgs); - Py_DECREF(pArgs); - Py_DECREF(pMethod); - - return pResult; -} - - -const char *dx_config_item_value_string(const dx_config_t *config, const char *section, int index, const char* key) -{ - PyObject *pResult = item_value(config, section, index, key, "value_string"); - char *value = 0; - - if (pResult && PyString_Check(pResult)) { - Py_ssize_t size = PyString_Size(pResult); - value = (char*) malloc(size + 1); - strncpy(value, PyString_AsString(pResult), size + 1); - } - - if (pResult) { - Py_DECREF(pResult); - } - - return value; -} - - -uint32_t dx_config_item_value_int(const dx_config_t *config, const char *section, int index, const char* key) -{ - PyObject *pResult = item_value(config, section, index, key, "value_int"); - uint32_t value = 0; - - if (pResult && PyLong_Check(pResult)) - value = (uint32_t) PyLong_AsLong(pResult); - - if (pResult) { - Py_DECREF(pResult); - } - - return value; -} - - -int dx_config_item_value_bool(const dx_config_t *config, const char *section, int index, const char* key) -{ - PyObject *pResult = item_value(config, section, index, key, "value_bool"); - int value = 0; - - if (pResult && pResult != Py_None) - value = 1; - - if (pResult) { - Py_DECREF(pResult); - } - - return value; -} - - diff --git a/extras/dispatch/src/config_private.h b/extras/dispatch/src/config_private.h deleted file mode 100644 index f4ecc64e4c..0000000000 --- a/extras/dispatch/src/config_private.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __config_private_h__ -#define __config_private_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/config.h> - -void dx_config_initialize(); -void dx_config_finalize(); -dx_config_t *dx_config(const char *filename); -void dx_config_read(dx_config_t *config); -void dx_config_free(dx_config_t *config); - -#endif diff --git a/extras/dispatch/src/container.c b/extras/dispatch/src/container.c deleted file mode 100644 index 3ae24d81b0..0000000000 --- a/extras/dispatch/src/container.c +++ /dev/null @@ -1,868 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 <string.h> -#include "dispatch_private.h" -#include <qpid/dispatch/container.h> -#include <qpid/dispatch/server.h> -#include <qpid/dispatch/message.h> -#include <proton/engine.h> -#include <proton/message.h> -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/hash.h> -#include <qpid/dispatch/threading.h> -#include <qpid/dispatch/iterator.h> -#include <qpid/dispatch/log.h> -#include <qpid/dispatch/agent.h> - -static char *module="CONTAINER"; - -struct dx_node_t { - dx_container_t *container; - const dx_node_type_t *ntype; - char *name; - void *context; - dx_dist_mode_t supported_dist; - dx_lifetime_policy_t life_policy; -}; - -ALLOC_DECLARE(dx_node_t); -ALLOC_DEFINE(dx_node_t); -ALLOC_DEFINE(dx_link_item_t); - - -struct dx_link_t { - pn_link_t *pn_link; - void *context; - dx_node_t *node; -}; - -ALLOC_DECLARE(dx_link_t); -ALLOC_DEFINE(dx_link_t); - - -struct dx_delivery_t { - pn_delivery_t *pn_delivery; - dx_delivery_t *peer; - void *context; - uint64_t disposition; - dx_link_t *link; -}; - -ALLOC_DECLARE(dx_delivery_t); -ALLOC_DEFINE(dx_delivery_t); - - -typedef struct dxc_node_type_t { - DEQ_LINKS(struct dxc_node_type_t); - const dx_node_type_t *ntype; -} dxc_node_type_t; -DEQ_DECLARE(dxc_node_type_t, dxc_node_type_list_t); - -static int DX_CONTAINER_CLASS_CONTAINER = 1; -static int DX_CONTAINER_CLASS_NODE_TYPE = 2; -static int DX_CONTAINER_CLASS_NODE = 3; - -typedef struct container_class_t { - dx_container_t *container; - int class_id; -} container_class_t; - -struct dx_container_t { - dx_dispatch_t *dx; - dx_server_t *server; - dx_hash_t *node_type_map; - dx_hash_t *node_map; - sys_mutex_t *lock; - dx_node_t *default_node; - dxc_node_type_list_t node_type_list; - dx_agent_class_t *class_container; - dx_agent_class_t *class_node_type; - dx_agent_class_t *class_node; -}; - -static void setup_outgoing_link(dx_container_t *container, pn_link_t *pn_link) -{ - sys_mutex_lock(container->lock); - dx_node_t *node = 0; - const char *source = pn_terminus_get_address(pn_link_remote_source(pn_link)); - dx_field_iterator_t *iter; - // TODO - Extract the name from the structured source - - if (source) { - iter = dx_field_iterator_string(source, ITER_VIEW_NODE_ID); - dx_hash_retrieve(container->node_map, iter, (void*) &node); - dx_field_iterator_free(iter); - } - sys_mutex_unlock(container->lock); - - if (node == 0) { - if (container->default_node) - node = container->default_node; - else { - // Reject the link - // TODO - When the API allows, add an error message for "no available node" - pn_link_close(pn_link); - return; - } - } - - dx_link_t *link = new_dx_link_t(); - if (!link) { - pn_link_close(pn_link); - return; - } - - link->pn_link = pn_link; - link->context = 0; - link->node = node; - - pn_link_set_context(pn_link, link); - node->ntype->outgoing_handler(node->context, link); -} - - -static void setup_incoming_link(dx_container_t *container, pn_link_t *pn_link) -{ - sys_mutex_lock(container->lock); - dx_node_t *node = 0; - const char *target = pn_terminus_get_address(pn_link_remote_target(pn_link)); - dx_field_iterator_t *iter; - // TODO - Extract the name from the structured target - - if (target) { - iter = dx_field_iterator_string(target, ITER_VIEW_NODE_ID); - dx_hash_retrieve(container->node_map, iter, (void*) &node); - dx_field_iterator_free(iter); - } - sys_mutex_unlock(container->lock); - - if (node == 0) { - if (container->default_node) - node = container->default_node; - else { - // Reject the link - // TODO - When the API allows, add an error message for "no available node" - pn_link_close(pn_link); - return; - } - } - - dx_link_t *link = new_dx_link_t(); - if (!link) { - pn_link_close(pn_link); - return; - } - - link->pn_link = pn_link; - link->context = 0; - link->node = node; - - pn_link_set_context(pn_link, link); - node->ntype->incoming_handler(node->context, link); -} - - -static int do_writable(pn_link_t *pn_link) -{ - dx_link_t *link = (dx_link_t*) pn_link_get_context(pn_link); - if (!link) - return 0; - - dx_node_t *node = link->node; - if (!node) - return 0; - - return node->ntype->writable_handler(node->context, link); -} - - -static void do_receive(pn_delivery_t *pnd) -{ - pn_link_t *pn_link = pn_delivery_link(pnd); - dx_link_t *link = (dx_link_t*) pn_link_get_context(pn_link); - dx_delivery_t *delivery = (dx_delivery_t*) pn_delivery_get_context(pnd); - - if (link) { - dx_node_t *node = link->node; - if (node) { - if (!delivery) { - delivery = new_dx_delivery_t(); - delivery->pn_delivery = pnd; - delivery->peer = 0; - delivery->context = 0; - delivery->disposition = 0; - delivery->link = link; - pn_delivery_set_context(pnd, delivery); - } - - node->ntype->rx_handler(node->context, link, delivery); - return; - } - } - - // - // Reject the delivery if we couldn't find a node to handle it - // - pn_link_advance(pn_link); - pn_link_flow(pn_link, 1); - pn_delivery_update(pnd, PN_REJECTED); - pn_delivery_settle(pnd); -} - - -static void do_updated(pn_delivery_t *pnd) -{ - pn_link_t *pn_link = pn_delivery_link(pnd); - dx_link_t *link = (dx_link_t*) pn_link_get_context(pn_link); - dx_delivery_t *delivery = (dx_delivery_t*) pn_delivery_get_context(pnd); - - if (link && delivery) { - dx_node_t *node = link->node; - if (node) - node->ntype->disp_handler(node->context, link, delivery); - } -} - - -static int close_handler(void* unused, pn_connection_t *conn) -{ - // - // Close all links, passing False as the 'closed' argument. These links are not - // being properly 'detached'. They are being orphaned. - // - pn_link_t *pn_link = pn_link_head(conn, PN_LOCAL_ACTIVE); - while (pn_link) { - dx_link_t *link = (dx_link_t*) pn_link_get_context(pn_link); - dx_node_t *node = link->node; - if (node && link) - node->ntype->link_detach_handler(node->context, link, 0); - pn_link_close(pn_link); - free_dx_link_t(link); - pn_link = pn_link_next(pn_link, PN_LOCAL_ACTIVE); - } - - // teardown all sessions - pn_session_t *ssn = pn_session_head(conn, 0); - while (ssn) { - pn_session_close(ssn); - ssn = pn_session_next(ssn, 0); - } - - // teardown the connection - pn_connection_close(conn); - return 0; -} - - -static int process_handler(dx_container_t *container, void* unused, pn_connection_t *conn) -{ - pn_session_t *ssn; - pn_link_t *pn_link; - pn_delivery_t *delivery; - int event_count = 0; - - // Step 1: setup the engine's connection, and any sessions and links - // that may be pending. - - // initialize the connection if it's new - if (pn_connection_state(conn) & PN_LOCAL_UNINIT) { - pn_connection_open(conn); - event_count++; - } - - // open all pending sessions - ssn = pn_session_head(conn, PN_LOCAL_UNINIT); - while (ssn) { - pn_session_open(ssn); - ssn = pn_session_next(ssn, PN_LOCAL_UNINIT); - event_count++; - } - - // configure and open any pending links - pn_link = pn_link_head(conn, PN_LOCAL_UNINIT); - while (pn_link) { - if (pn_link_is_sender(pn_link)) - setup_outgoing_link(container, pn_link); - else - setup_incoming_link(container, pn_link); - pn_link = pn_link_next(pn_link, PN_LOCAL_UNINIT); - event_count++; - } - - - // Step 2: Now drain all the pending deliveries from the connection's - // work queue and process them - - delivery = pn_work_head(conn); - while (delivery) { - if (pn_delivery_readable(delivery)) - do_receive(delivery); - - if (pn_delivery_updated(delivery)) { - do_updated(delivery); - pn_delivery_clear(delivery); - } - delivery = pn_work_next(delivery); - event_count++; - } - - // - // Step 2.5: Call the attached node's writable handler for all active links - // on the connection. Note that in Dispatch, links are considered - // bidirectional. Incoming and outgoing only pertains to deliveries and - // deliveries are a subset of the traffic that flows both directions on links. - // - pn_link = pn_link_head(conn, PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE); - while (pn_link) { - assert(pn_session_connection(pn_link_session(pn_link)) == conn); - event_count += do_writable(pn_link); - pn_link = pn_link_next(pn_link, PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE); - } - - // Step 3: Clean up any links or sessions that have been closed by the - // remote. If the connection has been closed remotely, clean that up - // also. - - // teardown any terminating links - pn_link = pn_link_head(conn, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED); - while (pn_link) { - dx_link_t *link = (dx_link_t*) pn_link_get_context(pn_link); - dx_node_t *node = link->node; - if (node) - node->ntype->link_detach_handler(node->context, link, 1); // TODO - get 'closed' from detach message - pn_link_close(pn_link); - pn_link = pn_link_next(pn_link, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED); - event_count++; - } - - // teardown any terminating sessions - ssn = pn_session_head(conn, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED); - while (ssn) { - pn_session_close(ssn); - ssn = pn_session_next(ssn, PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED); - event_count++; - } - - // teardown the connection if it's terminating - if (pn_connection_state(conn) == (PN_LOCAL_ACTIVE | PN_REMOTE_CLOSED)) { - pn_connection_close(conn); - event_count++; - } - - return event_count; -} - - -static void open_handler(dx_container_t *container, dx_connection_t *conn, dx_direction_t dir) -{ - const dx_node_type_t *nt; - - // - // Note the locking structure in this function. Generally this would be unsafe, but since - // this particular list is only ever appended to and never has items inserted or deleted, - // this usage is safe in this case. - // - sys_mutex_lock(container->lock); - dxc_node_type_t *nt_item = DEQ_HEAD(container->node_type_list); - sys_mutex_unlock(container->lock); - - pn_connection_open(dx_connection_pn(conn)); - - while (nt_item) { - nt = nt_item->ntype; - if (dir == DX_INCOMING) { - if (nt->inbound_conn_open_handler) - nt->inbound_conn_open_handler(nt->type_context, conn); - } else { - if (nt->outbound_conn_open_handler) - nt->outbound_conn_open_handler(nt->type_context, conn); - } - - sys_mutex_lock(container->lock); - nt_item = DEQ_NEXT(nt_item); - sys_mutex_unlock(container->lock); - } -} - - -static int handler(void *handler_context, void *conn_context, dx_conn_event_t event, dx_connection_t *dx_conn) -{ - dx_container_t *container = (dx_container_t*) handler_context; - pn_connection_t *conn = dx_connection_pn(dx_conn); - - switch (event) { - case DX_CONN_EVENT_LISTENER_OPEN: open_handler(container, dx_conn, DX_INCOMING); break; - case DX_CONN_EVENT_CONNECTOR_OPEN: open_handler(container, dx_conn, DX_OUTGOING); break; - case DX_CONN_EVENT_CLOSE: return close_handler(conn_context, conn); - case DX_CONN_EVENT_PROCESS: return process_handler(container, conn_context, conn); - } - - return 0; -} - - -static void container_schema_handler(void *context, void *correlator) -{ -} - - -static void container_query_handler(void* context, const char *id, void *correlator) -{ - container_class_t *cls = (container_class_t*) context; - - if (cls->class_id == DX_CONTAINER_CLASS_CONTAINER) { - dx_agent_value_uint(correlator, "node_type_count", dx_hash_size(cls->container->node_type_map)); - dx_agent_value_uint(correlator, "node_count", dx_hash_size(cls->container->node_map)); - if (cls->container->default_node) - dx_agent_value_string(correlator, "default_node_type", cls->container->default_node->ntype->type_name); - else - dx_agent_value_null(correlator, "default_node_type"); - dx_agent_value_complete(correlator, false); - - } else if (cls->class_id == DX_CONTAINER_CLASS_NODE_TYPE) { - - } else if (cls->class_id == DX_CONTAINER_CLASS_NODE) { - - } -} - - -dx_agent_class_t *setup_class(dx_container_t *container, const char *fqname, int id) -{ - container_class_t *cls = NEW(container_class_t); - cls->container = container; - cls->class_id = id; - - return dx_agent_register_class(container->dx, fqname, cls, - container_schema_handler, - container_query_handler); -} - - -dx_container_t *dx_container(dx_dispatch_t *dx) -{ - dx_container_t *container = NEW(dx_container_t); - - container->dx = dx; - container->server = dx->server; - container->node_type_map = dx_hash(6, 4, 1); // 64 buckets, item batches of 4 - container->node_map = dx_hash(10, 32, 0); // 1K buckets, item batches of 32 - container->lock = sys_mutex(); - container->default_node = 0; - DEQ_INIT(container->node_type_list); - - dx_log(module, LOG_TRACE, "Container Initializing"); - dx_server_set_conn_handler(dx, handler, container); - - return container; -} - - -void dx_container_setup_agent(dx_dispatch_t *dx) -{ - dx->container->class_container = - setup_class(dx->container, "org.apache.qpid.dispatch.container", DX_CONTAINER_CLASS_CONTAINER); - dx->container->class_node_type = - setup_class(dx->container, "org.apache.qpid.dispatch.container.node_type", DX_CONTAINER_CLASS_NODE_TYPE); - dx->container->class_node = - setup_class(dx->container, "org.apache.qpid.dispatch.container.node", DX_CONTAINER_CLASS_NODE); -} - - -void dx_container_free(dx_container_t *container) -{ - // TODO - Free the nodes - // TODO - Free the node types - sys_mutex_free(container->lock); - free(container); -} - - -int dx_container_register_node_type(dx_dispatch_t *dx, const dx_node_type_t *nt) -{ - dx_container_t *container = dx->container; - - int result; - dx_field_iterator_t *iter = dx_field_iterator_string(nt->type_name, ITER_VIEW_ALL); - dxc_node_type_t *nt_item = NEW(dxc_node_type_t); - DEQ_ITEM_INIT(nt_item); - nt_item->ntype = nt; - - sys_mutex_lock(container->lock); - result = dx_hash_insert_const(container->node_type_map, iter, nt, 0); - DEQ_INSERT_TAIL(container->node_type_list, nt_item); - sys_mutex_unlock(container->lock); - - dx_field_iterator_free(iter); - if (result < 0) - return result; - dx_log(module, LOG_TRACE, "Node Type Registered - %s", nt->type_name); - - return 0; -} - - -dx_node_t *dx_container_set_default_node_type(dx_dispatch_t *dx, - const dx_node_type_t *nt, - void *context, - dx_dist_mode_t supported_dist) -{ - dx_container_t *container = dx->container; - - if (container->default_node) - dx_container_destroy_node(container->default_node); - - if (nt) { - container->default_node = dx_container_create_node(dx, nt, 0, context, supported_dist, DX_LIFE_PERMANENT); - dx_log(module, LOG_TRACE, "Node of type '%s' installed as default node", nt->type_name); - } else { - container->default_node = 0; - dx_log(module, LOG_TRACE, "Default node removed"); - } - - return container->default_node; -} - - -dx_node_t *dx_container_create_node(dx_dispatch_t *dx, - const dx_node_type_t *nt, - const char *name, - void *context, - dx_dist_mode_t supported_dist, - dx_lifetime_policy_t life_policy) -{ - dx_container_t *container = dx->container; - int result; - dx_node_t *node = new_dx_node_t(); - if (!node) - return 0; - - node->container = container; - node->ntype = nt; - node->name = 0; - node->context = context; - node->supported_dist = supported_dist; - node->life_policy = life_policy; - - if (name) { - dx_field_iterator_t *iter = dx_field_iterator_string(name, ITER_VIEW_ALL); - sys_mutex_lock(container->lock); - result = dx_hash_insert(container->node_map, iter, node, 0); - sys_mutex_unlock(container->lock); - dx_field_iterator_free(iter); - if (result < 0) { - free_dx_node_t(node); - return 0; - } - - node->name = (char*) malloc(strlen(name) + 1); - strcpy(node->name, name); - } - - if (name) - dx_log(module, LOG_TRACE, "Node of type '%s' created with name '%s'", nt->type_name, name); - - return node; -} - - -void dx_container_destroy_node(dx_node_t *node) -{ - dx_container_t *container = node->container; - - if (node->name) { - dx_field_iterator_t *iter = dx_field_iterator_string(node->name, ITER_VIEW_ALL); - sys_mutex_lock(container->lock); - dx_hash_remove(container->node_map, iter); - sys_mutex_unlock(container->lock); - dx_field_iterator_free(iter); - free(node->name); - } - - free_dx_node_t(node); -} - - -void dx_container_node_set_context(dx_node_t *node, void *node_context) -{ - node->context = node_context; -} - - -dx_dist_mode_t dx_container_node_get_dist_modes(const dx_node_t *node) -{ - return node->supported_dist; -} - - -dx_lifetime_policy_t dx_container_node_get_life_policy(const dx_node_t *node) -{ - return node->life_policy; -} - - -dx_link_t *dx_link(dx_node_t *node, dx_connection_t *conn, dx_direction_t dir, const char* name) -{ - pn_session_t *sess = pn_session(dx_connection_pn(conn)); - dx_link_t *link = new_dx_link_t(); - - if (dir == DX_OUTGOING) - link->pn_link = pn_sender(sess, name); - else - link->pn_link = pn_receiver(sess, name); - link->context = node->context; - link->node = node; - - pn_link_set_context(link->pn_link, link); - - pn_session_open(sess); - - return link; -} - - -void dx_link_set_context(dx_link_t *link, void *context) -{ - link->context = context; -} - - -void *dx_link_get_context(dx_link_t *link) -{ - return link->context; -} - - -void dx_link_set_conn_context(dx_link_t *link, void *context) -{ - pn_session_t *pn_sess = pn_link_session(link->pn_link); - if (!pn_sess) - return; - pn_connection_t *pn_conn = pn_session_connection(pn_sess); - if (!pn_conn) - return; - dx_connection_t *conn = (dx_connection_t*) pn_connection_get_context(pn_conn); - if (!conn) - return; - dx_connection_set_link_context(conn, context); -} - - -void *dx_link_get_conn_context(dx_link_t *link) -{ - pn_session_t *pn_sess = pn_link_session(link->pn_link); - if (!pn_sess) - return 0; - pn_connection_t *pn_conn = pn_session_connection(pn_sess); - if (!pn_conn) - return 0; - dx_connection_t *conn = (dx_connection_t*) pn_connection_get_context(pn_conn); - if (!conn) - return 0; - return dx_connection_get_link_context(conn); -} - - -pn_link_t *dx_link_pn(dx_link_t *link) -{ - return link->pn_link; -} - - -dx_connection_t *dx_link_connection(dx_link_t *link) -{ - if (!link || !link->pn_link) - return 0; - - pn_session_t *sess = pn_link_session(link->pn_link); - if (!sess) - return 0; - - pn_connection_t *conn = pn_session_connection(sess); - if (!conn) - return 0; - - dx_connection_t *ctx = pn_connection_get_context(conn); - if (!ctx) - return 0; - - return ctx; -} - - -pn_terminus_t *dx_link_source(dx_link_t *link) -{ - return pn_link_source(link->pn_link); -} - - -pn_terminus_t *dx_link_target(dx_link_t *link) -{ - return pn_link_target(link->pn_link); -} - - -pn_terminus_t *dx_link_remote_source(dx_link_t *link) -{ - return pn_link_remote_source(link->pn_link); -} - - -pn_terminus_t *dx_link_remote_target(dx_link_t *link) -{ - return pn_link_remote_target(link->pn_link); -} - - -void dx_link_activate(dx_link_t *link) -{ - if (!link || !link->pn_link) - return; - - pn_session_t *sess = pn_link_session(link->pn_link); - if (!sess) - return; - - pn_connection_t *conn = pn_session_connection(sess); - if (!conn) - return; - - dx_connection_t *ctx = pn_connection_get_context(conn); - if (!ctx) - return; - - dx_server_activate(ctx); -} - - -void dx_link_close(dx_link_t *link) -{ - pn_link_close(link->pn_link); -} - - -dx_delivery_t *dx_delivery(dx_link_t *link, pn_delivery_tag_t tag) -{ - pn_link_t *pnl = dx_link_pn(link); - - // - // If there is a current delivery on this outgoing link, something - // is wrong with the delivey algorithm. We assume that the current - // delivery ('pnd' below) is the one created by pn_delivery. If it is - // not, then my understanding of how proton works is incorrect. - // - assert(!pn_link_current(pnl)); - - pn_delivery(pnl, tag); - pn_delivery_t *pnd = pn_link_current(pnl); - - if (!pnd) - return 0; - - dx_delivery_t *delivery = new_dx_delivery_t(); - delivery->pn_delivery = pnd; - delivery->peer = 0; - delivery->context = 0; - delivery->disposition = 0; - delivery->link = link; - pn_delivery_set_context(pnd, delivery); - - return delivery; -} - - -void dx_delivery_free(dx_delivery_t *delivery, uint64_t final_disposition) -{ - if (delivery->pn_delivery) { - if (final_disposition > 0) - pn_delivery_update(delivery->pn_delivery, final_disposition); - pn_delivery_set_context(delivery->pn_delivery, 0); - pn_delivery_settle(delivery->pn_delivery); - } - if (delivery->peer) - delivery->peer->peer = 0; - free_dx_delivery_t(delivery); -} - - -void dx_delivery_set_peer(dx_delivery_t *delivery, dx_delivery_t *peer) -{ - delivery->peer = peer; -} - - -void dx_delivery_set_context(dx_delivery_t *delivery, void *context) -{ - delivery->context = context; -} - - -void *dx_delivery_context(dx_delivery_t *delivery) -{ - return delivery->context; -} - - -dx_delivery_t *dx_delivery_peer(dx_delivery_t *delivery) -{ - return delivery->peer; -} - - -pn_delivery_t *dx_delivery_pn(dx_delivery_t *delivery) -{ - return delivery->pn_delivery; -} - - -void dx_delivery_settle(dx_delivery_t *delivery) -{ - if (delivery->pn_delivery) { - pn_delivery_settle(delivery->pn_delivery); - delivery->pn_delivery = 0; - } -} - - -bool dx_delivery_settled(dx_delivery_t *delivery) -{ - return pn_delivery_settled(delivery->pn_delivery); -} - - -bool dx_delivery_disp_changed(dx_delivery_t *delivery) -{ - return delivery->disposition != pn_delivery_remote_state(delivery->pn_delivery); -} - - -uint64_t dx_delivery_disp(dx_delivery_t *delivery) -{ - delivery->disposition = pn_delivery_remote_state(delivery->pn_delivery); - return delivery->disposition; -} - - -dx_link_t *dx_delivery_link(dx_delivery_t *delivery) -{ - return delivery->link; -} - diff --git a/extras/dispatch/src/dispatch.c b/extras/dispatch/src/dispatch.c deleted file mode 100644 index 46c256a603..0000000000 --- a/extras/dispatch/src/dispatch.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/python_embedded.h> -#include <qpid/dispatch.h> -#include <qpid/dispatch/server.h> -#include <qpid/dispatch/ctools.h> -#include "dispatch_private.h" -#include "alloc_private.h" -#include "log_private.h" -#include "router_private.h" - -/** - * Private Function Prototypes - */ -dx_server_t *dx_server(int tc, const char *container_name); -void dx_server_setup_agent(dx_dispatch_t *dx); -void dx_server_free(dx_server_t *server); -dx_container_t *dx_container(dx_dispatch_t *dx); -void dx_container_setup_agent(dx_dispatch_t *dx); -void dx_container_free(dx_container_t *container); -dx_router_t *dx_router(dx_dispatch_t *dx, dx_router_mode_t mode, const char *area, const char *id); -void dx_router_setup_late(dx_dispatch_t *dx); -void dx_router_free(dx_router_t *router); -dx_agent_t *dx_agent(dx_dispatch_t *dx); -void dx_agent_free(dx_agent_t *agent); - -ALLOC_DEFINE(dx_config_listener_t); -ALLOC_DEFINE(dx_config_connector_t); - -static const char *CONF_CONTAINER = "container"; -static const char *CONF_ROUTER = "router"; -static const char *CONF_LISTENER = "listener"; -static const char *CONF_CONNECTOR = "connector"; - - -dx_dispatch_t *dx_dispatch(const char *config_path) -{ - dx_dispatch_t *dx = NEW(dx_dispatch_t); - - int thread_count = 0; - const char *container_name = 0; - const char *router_mode_str = 0; - const char *router_area = "0"; - const char *router_id = 0; - - dx_router_mode_t router_mode = DX_ROUTER_MODE_STANDALONE; - - DEQ_INIT(dx->config_listeners); - DEQ_INIT(dx->config_connectors); - - dx_python_initialize(dx); - dx_log_initialize(); - dx_alloc_initialize(); - - dx_config_initialize(); - dx->config = dx_config(config_path); - dx_config_read(dx->config); - - if (dx->config) { - int count = dx_config_item_count(dx->config, CONF_CONTAINER); - if (count == 1) { - thread_count = dx_config_item_value_int(dx->config, CONF_CONTAINER, 0, "worker-threads"); - container_name = dx_config_item_value_string(dx->config, CONF_CONTAINER, 0, "container-name"); - } - - count = dx_config_item_count(dx->config, CONF_ROUTER); - if (count == 1) { - router_mode_str = dx_config_item_value_string(dx->config, CONF_ROUTER, 0, "mode"); - //router_area = dx_config_item_value_string(dx->config, CONF_ROUTER, 0, "0"); - router_id = dx_config_item_value_string(dx->config, CONF_ROUTER, 0, "router-id"); - } - } - - if (thread_count == 0) - thread_count = 1; - - if (!container_name) - container_name = "00000000-0000-0000-0000-000000000000"; // TODO - gen a real uuid - - if (router_mode_str && strcmp(router_mode_str, "interior") == 0) - router_mode = DX_ROUTER_MODE_INTERIOR; - - if (router_mode_str && strcmp(router_mode_str, "edge") == 0) - router_mode = DX_ROUTER_MODE_EDGE; - - if (!router_area) - router_area = "area"; - - if (!router_id) - router_id = container_name; - - dx->server = dx_server(thread_count, container_name); - dx->container = dx_container(dx); - dx->router = dx_router(dx, router_mode, router_area, router_id); - dx->agent = dx_agent(dx); - - dx_alloc_setup_agent(dx); - dx_server_setup_agent(dx); - dx_container_setup_agent(dx); - dx_router_setup_late(dx); - - return dx; -} - - -void dx_dispatch_free(dx_dispatch_t *dx) -{ - dx_config_free(dx->config); - dx_config_finalize(); - dx_agent_free(dx->agent); - dx_router_free(dx->router); - dx_container_free(dx->container); - dx_server_free(dx->server); - dx_log_finalize(); - dx_python_finalize(); -} - - -static void load_server_config(dx_dispatch_t *dx, dx_server_config_t *config, const char *section, int i) -{ - config->host = dx_config_item_value_string(dx->config, section, i, "addr"); - config->port = dx_config_item_value_string(dx->config, section, i, "port"); - config->role = dx_config_item_value_string(dx->config, section, i, "role"); - config->sasl_mechanisms = - dx_config_item_value_string(dx->config, section, i, "sasl-mechanisms"); - config->ssl_enabled = - dx_config_item_value_bool(dx->config, section, i, "ssl-profile"); - if (config->ssl_enabled) { - config->ssl_server = 1; - config->ssl_allow_unsecured_client = - dx_config_item_value_bool(dx->config, section, i, "allow-unsecured"); - config->ssl_certificate_file = - dx_config_item_value_string(dx->config, section, i, "cert-file"); - config->ssl_private_key_file = - dx_config_item_value_string(dx->config, section, i, "key-file"); - config->ssl_password = - dx_config_item_value_string(dx->config, section, i, "password"); - config->ssl_trusted_certificate_db = - dx_config_item_value_string(dx->config, section, i, "cert-db"); - config->ssl_require_peer_authentication = - dx_config_item_value_bool(dx->config, section, i, "require-peer-auth"); - } -} - - -static void configure_listeners(dx_dispatch_t *dx) -{ - int count; - - if (!dx->config) - return; - - count = dx_config_item_count(dx->config, CONF_LISTENER); - for (int i = 0; i < count; i++) { - dx_config_listener_t *cl = new_dx_config_listener_t(); - load_server_config(dx, &cl->configuration, CONF_LISTENER, i); - - printf("\nListener : %s:%s\n", cl->configuration.host, cl->configuration.port); - printf(" SASL: %s\n", cl->configuration.sasl_mechanisms); - printf(" SSL: %d\n", cl->configuration.ssl_enabled); - if (cl->configuration.ssl_enabled) { - printf(" unsec: %d\n", cl->configuration.ssl_allow_unsecured_client); - printf(" cert-file: %s\n", cl->configuration.ssl_certificate_file); - printf(" key-file: %s\n", cl->configuration.ssl_private_key_file); - printf(" cert-db: %s\n", cl->configuration.ssl_trusted_certificate_db); - printf(" peer-auth: %d\n", cl->configuration.ssl_require_peer_authentication); - } - - cl->listener = dx_server_listen(dx, &cl->configuration, cl); - DEQ_ITEM_INIT(cl); - DEQ_INSERT_TAIL(dx->config_listeners, cl); - } -} - - -static void configure_connectors(dx_dispatch_t *dx) -{ - int count; - - if (!dx->config) - return; - - count = dx_config_item_count(dx->config, CONF_CONNECTOR); - for (int i = 0; i < count; i++) { - dx_config_connector_t *cc = new_dx_config_connector_t(); - load_server_config(dx, &cc->configuration, CONF_CONNECTOR, i); - - printf("\nConnector : %s:%s\n", cc->configuration.host, cc->configuration.port); - printf(" SASL: %s\n", cc->configuration.sasl_mechanisms); - printf(" SSL: %d\n", cc->configuration.ssl_enabled); - if (cc->configuration.ssl_enabled) { - printf(" cert-file: %s\n", cc->configuration.ssl_certificate_file); - printf(" key-file: %s\n", cc->configuration.ssl_private_key_file); - printf(" cert-db: %s\n", cc->configuration.ssl_trusted_certificate_db); - printf(" peer-auth: %d\n", cc->configuration.ssl_require_peer_authentication); - } - - cc->connector = dx_server_connect(dx, &cc->configuration, cc); - DEQ_ITEM_INIT(cc); - DEQ_INSERT_TAIL(dx->config_connectors, cc); - } -} - - -void dx_dispatch_configure(dx_dispatch_t *dx) -{ - configure_listeners(dx); - configure_connectors(dx); -} - diff --git a/extras/dispatch/src/dispatch_private.h b/extras/dispatch/src/dispatch_private.h deleted file mode 100644 index d96eb59afe..0000000000 --- a/extras/dispatch/src/dispatch_private.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef __dispatch_private_h__ -#define __dispatch_private_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 "server_private.h" -#include "config_private.h" -#include <qpid/dispatch/ctools.h> - -typedef struct dx_container_t dx_container_t; -typedef struct dx_router_t dx_router_t; -typedef struct dx_agent_t dx_agent_t; - -typedef struct dx_config_listener_t { - DEQ_LINKS(struct dx_config_listener_t); - dx_listener_t *listener; - dx_server_config_t configuration; -} dx_config_listener_t; - -DEQ_DECLARE(dx_config_listener_t, dx_config_listener_list_t); -ALLOC_DECLARE(dx_config_listener_t); - - -typedef struct dx_config_connector_t { - DEQ_LINKS(struct dx_config_connector_t); - dx_connector_t *connector; - dx_server_config_t configuration; -} dx_config_connector_t; - -DEQ_DECLARE(dx_config_connector_t, dx_config_connector_list_t); -ALLOC_DECLARE(dx_config_connector_t); - -struct dx_dispatch_t { - dx_server_t *server; - dx_container_t *container; - dx_router_t *router; - dx_agent_t *agent; - dx_config_t *config; - - dx_config_listener_list_t config_listeners; - dx_config_connector_list_t config_connectors; -}; - -#endif - diff --git a/extras/dispatch/src/hash.c b/extras/dispatch/src/hash.c deleted file mode 100644 index 0cb32acd05..0000000000 --- a/extras/dispatch/src/hash.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/hash.h> -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/alloc.h> -#include <stdio.h> -#include <string.h> - -typedef struct dx_hash_item_t { - DEQ_LINKS(struct dx_hash_item_t); - unsigned char *key; - union { - void *val; - const void *val_const; - } v; -} dx_hash_item_t; - -ALLOC_DECLARE(dx_hash_item_t); -ALLOC_DEFINE(dx_hash_item_t); -DEQ_DECLARE(dx_hash_item_t, items_t); - - -typedef struct bucket_t { - items_t items; -} bucket_t; - - -struct dx_hash_t { - bucket_t *buckets; - unsigned int bucket_count; - unsigned int bucket_mask; - int batch_size; - size_t size; - int is_const; -}; - - -struct dx_hash_handle_t { - bucket_t *bucket; - dx_hash_item_t *item; -}; - -ALLOC_DECLARE(dx_hash_handle_t); -ALLOC_DEFINE(dx_hash_handle_t); - - -// djb2 hash algorithm -static unsigned long dx_hash_function(dx_field_iterator_t *iter) -{ - unsigned long hash = 5381; - int c; - - dx_field_iterator_reset(iter); - while (!dx_field_iterator_end(iter)) { - c = (int) dx_field_iterator_octet(iter); - hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ - } - - return hash; -} - - -dx_hash_t *dx_hash(int bucket_exponent, int batch_size, int value_is_const) -{ - int i; - dx_hash_t *h = NEW(dx_hash_t); - - if (!h) - return 0; - - h->bucket_count = 1 << bucket_exponent; - h->bucket_mask = h->bucket_count - 1; - h->batch_size = batch_size; - h->size = 0; - h->is_const = value_is_const; - h->buckets = NEW_ARRAY(bucket_t, h->bucket_count); - for (i = 0; i < h->bucket_count; i++) { - DEQ_INIT(h->buckets[i].items); - } - - return h; -} - - -void dx_hash_free(dx_hash_t *h) -{ - // TODO - Implement this -} - - -size_t dx_hash_size(dx_hash_t *h) -{ - return h ? h->size : 0; -} - - -static dx_hash_item_t *dx_hash_internal_insert(dx_hash_t *h, dx_field_iterator_t *key, int *exists, dx_hash_handle_t **handle) -{ - unsigned long idx = dx_hash_function(key) & h->bucket_mask; - dx_hash_item_t *item = DEQ_HEAD(h->buckets[idx].items); - - while (item) { - if (dx_field_iterator_equal(key, item->key)) - break; - item = item->next; - } - - if (item) { - *exists = 1; - if (handle) - *handle = 0; - return item; - } - - item = new_dx_hash_item_t(); - if (!item) - return 0; - - DEQ_ITEM_INIT(item); - item->key = dx_field_iterator_copy(key); - - DEQ_INSERT_TAIL(h->buckets[idx].items, item); - h->size++; - *exists = 0; - - // - // If a pointer to a handle-pointer was supplied, create a handle for this item. - // - if (handle) { - *handle = new_dx_hash_handle_t(); - (*handle)->bucket = &h->buckets[idx]; - (*handle)->item = item; - } - - return item; -} - - -dx_error_t dx_hash_insert(dx_hash_t *h, dx_field_iterator_t *key, void *val, dx_hash_handle_t **handle) -{ - int exists = 0; - dx_hash_item_t *item = dx_hash_internal_insert(h, key, &exists, handle); - - if (!item) - return DX_ERROR_ALLOC; - - if (exists) - return DX_ERROR_ALREADY_EXISTS; - - item->v.val = val; - - return DX_ERROR_NONE; -} - - -dx_error_t dx_hash_insert_const(dx_hash_t *h, dx_field_iterator_t *key, const void *val, dx_hash_handle_t **handle) -{ - assert(h->is_const); - - int error = 0; - dx_hash_item_t *item = dx_hash_internal_insert(h, key, &error, handle); - - if (item) - item->v.val_const = val; - return error; -} - - -static dx_hash_item_t *dx_hash_internal_retrieve(dx_hash_t *h, dx_field_iterator_t *key) -{ - unsigned long idx = dx_hash_function(key) & h->bucket_mask; - dx_hash_item_t *item = DEQ_HEAD(h->buckets[idx].items); - - while (item) { - if (dx_field_iterator_equal(key, item->key)) - break; - item = item->next; - } - - return item; -} - - -dx_error_t dx_hash_retrieve(dx_hash_t *h, dx_field_iterator_t *key, void **val) -{ - dx_hash_item_t *item = dx_hash_internal_retrieve(h, key); - if (item) - *val = item->v.val; - else - *val = 0; - - return DX_ERROR_NONE; -} - - -dx_error_t dx_hash_retrieve_const(dx_hash_t *h, dx_field_iterator_t *key, const void **val) -{ - assert(h->is_const); - - dx_hash_item_t *item = dx_hash_internal_retrieve(h, key); - if (item) - *val = item->v.val_const; - else - *val = 0; - - return DX_ERROR_NONE; -} - - -dx_error_t dx_hash_remove(dx_hash_t *h, dx_field_iterator_t *key) -{ - unsigned long idx = dx_hash_function(key) & h->bucket_mask; - dx_hash_item_t *item = DEQ_HEAD(h->buckets[idx].items); - - while (item) { - if (dx_field_iterator_equal(key, item->key)) - break; - item = item->next; - } - - if (item) { - free(item->key); - DEQ_REMOVE(h->buckets[idx].items, item); - free_dx_hash_item_t(item); - h->size--; - return DX_ERROR_NONE; - } - - return DX_ERROR_NOT_FOUND; -} - - -void dx_hash_handle_free(dx_hash_handle_t *handle) -{ - if (handle) - free_dx_hash_handle_t(handle); -} - - -const unsigned char *dx_hash_key_by_handle(const dx_hash_handle_t *handle) -{ - if (handle) - return handle->item->key; - return 0; -} - - -dx_error_t dx_hash_remove_by_handle(dx_hash_t *h, dx_hash_handle_t *handle) -{ - unsigned char *key = 0; - dx_error_t error = dx_hash_remove_by_handle2(h, handle, &key); - if (key) - free(key); - return error; -} - - -dx_error_t dx_hash_remove_by_handle2(dx_hash_t *h, dx_hash_handle_t *handle, unsigned char **key) -{ - if (!handle) - return DX_ERROR_NOT_FOUND; - *key = handle->item->key; - DEQ_REMOVE(handle->bucket->items, handle->item); - free_dx_hash_item_t(handle->item); - h->size--; - return DX_ERROR_NONE; -} - diff --git a/extras/dispatch/src/iovec.c b/extras/dispatch/src/iovec.c deleted file mode 100644 index a4ce937333..0000000000 --- a/extras/dispatch/src/iovec.c +++ /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/dispatch/iovec.h> -#include <qpid/dispatch/alloc.h> -#include <string.h> - -#define DX_IOVEC_MAX 64 - -struct dx_iovec_t { - struct iovec iov_array[DX_IOVEC_MAX]; - struct iovec *iov; - int iov_count; -}; - - -ALLOC_DECLARE(dx_iovec_t); -ALLOC_DEFINE(dx_iovec_t); - - -dx_iovec_t *dx_iovec(int vector_count) -{ - dx_iovec_t *iov = new_dx_iovec_t(); - if (!iov) - return 0; - - memset(iov, 0, sizeof(dx_iovec_t)); - - iov->iov_count = vector_count; - if (vector_count > DX_IOVEC_MAX) - iov->iov = (struct iovec*) malloc(sizeof(struct iovec) * vector_count); - else - iov->iov = &iov->iov_array[0]; - - return iov; -} - - -void dx_iovec_free(dx_iovec_t *iov) -{ - if (!iov) - return; - - if (iov->iov && iov->iov != &iov->iov_array[0]) - free(iov->iov); - - free_dx_iovec_t(iov); -} - - -struct iovec *dx_iovec_array(dx_iovec_t *iov) -{ - if (!iov) - return 0; - return iov->iov; -} - - -int dx_iovec_count(dx_iovec_t *iov) -{ - if (!iov) - return 0; - return iov->iov_count; -} - diff --git a/extras/dispatch/src/iterator.c b/extras/dispatch/src/iterator.c deleted file mode 100644 index 7898e04cc9..0000000000 --- a/extras/dispatch/src/iterator.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/iterator.h> -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/log.h> -#include "message_private.h" -#include <stdio.h> -#include <string.h> - -//static const char *log_module = "FIELD"; - -typedef enum { - MODE_TO_END, - MODE_TO_SLASH -} parse_mode_t; - -typedef struct { - dx_buffer_t *buffer; - unsigned char *cursor; - int length; -} pointer_t; - -struct dx_field_iterator_t { - pointer_t start_pointer; - pointer_t view_start_pointer; - pointer_t pointer; - dx_iterator_view_t view; - parse_mode_t mode; - unsigned char prefix; - int at_prefix; - int view_prefix; -}; - -ALLOC_DECLARE(dx_field_iterator_t); -ALLOC_DEFINE(dx_field_iterator_t); - - -typedef enum { - STATE_START, - STATE_SLASH_LEFT, - STATE_SKIPPING_TO_NEXT_SLASH, - STATE_SCANNING, - STATE_COLON, - STATE_COLON_SLASH, - STATE_AT_NODE_ID -} state_t; - - -static char *my_area = ""; -static char *my_router = ""; - - -static void parse_address_view(dx_field_iterator_t *iter) -{ - // - // This function starts with an iterator view that is identical to - // ITER_VIEW_NO_HOST. We will now further refine the view in order - // to aid the router in looking up addresses. - // - - if (dx_field_iterator_prefix(iter, "_")) { - if (dx_field_iterator_prefix(iter, "local/")) { - iter->prefix = 'L'; - iter->at_prefix = 1; - iter->view_prefix = 1; - return; - } - - if (dx_field_iterator_prefix(iter, "topo/")) { - if (dx_field_iterator_prefix(iter, "all/") || dx_field_iterator_prefix(iter, my_area)) { - if (dx_field_iterator_prefix(iter, "all/") || dx_field_iterator_prefix(iter, my_router)) { - iter->prefix = 'L'; - iter->at_prefix = 1; - iter->view_prefix = 1; - return; - } - - iter->prefix = 'R'; - iter->at_prefix = 1; - iter->view_prefix = 1; - iter->mode = MODE_TO_SLASH; - return; - } - - iter->prefix = 'A'; - iter->at_prefix = 1; - iter->view_prefix = 1; - iter->mode = MODE_TO_SLASH; - return; - } - } - - iter->prefix = 'M'; - iter->at_prefix = 1; - iter->view_prefix = 1; -} - - -static void parse_node_view(dx_field_iterator_t *iter) -{ - // - // This function starts with an iterator view that is identical to - // ITER_VIEW_NO_HOST. We will now further refine the view in order - // to aid the router in looking up nodes. - // - - if (dx_field_iterator_prefix(iter, my_area)) { - iter->prefix = 'R'; - iter->at_prefix = 1; - iter->view_prefix = 1; - iter->mode = MODE_TO_END; - return; - } - - iter->prefix = 'A'; - iter->at_prefix = 1; - iter->view_prefix = 1; - iter->mode = MODE_TO_SLASH; -} - - -static void view_initialize(dx_field_iterator_t *iter) -{ - // - // The default behavior is for the view to *not* have a prefix. - // We'll add one if it's needed later. - // - iter->at_prefix = 0; - iter->view_prefix = 0; - iter->mode = MODE_TO_END; - - if (iter->view == ITER_VIEW_ALL) - return; - - // - // Advance to the node-id. - // - state_t state = STATE_START; - unsigned int octet; - pointer_t save_pointer = {0,0,0}; - - while (!dx_field_iterator_end(iter) && state != STATE_AT_NODE_ID) { - octet = dx_field_iterator_octet(iter); - switch (state) { - case STATE_START : - if (octet == '/') - state = STATE_SLASH_LEFT; - else - state = STATE_SCANNING; - break; - - case STATE_SLASH_LEFT : - if (octet == '/') - state = STATE_SKIPPING_TO_NEXT_SLASH; - else - state = STATE_AT_NODE_ID; - break; - - case STATE_SKIPPING_TO_NEXT_SLASH : - if (octet == '/') - state = STATE_AT_NODE_ID; - break; - - case STATE_SCANNING : - if (octet == ':') - state = STATE_COLON; - break; - - case STATE_COLON : - if (octet == '/') { - state = STATE_COLON_SLASH; - save_pointer = iter->pointer; - } else - state = STATE_SCANNING; - break; - - case STATE_COLON_SLASH : - if (octet == '/') - state = STATE_SKIPPING_TO_NEXT_SLASH; - else { - state = STATE_AT_NODE_ID; - iter->pointer = save_pointer; - } - break; - - case STATE_AT_NODE_ID : - break; - } - } - - if (state != STATE_AT_NODE_ID) { - // - // The address string was relative, not absolute. The node-id - // is at the beginning of the string. - // - iter->pointer = iter->start_pointer; - } - - // - // Cursor is now on the first octet of the node-id - // - if (iter->view == ITER_VIEW_NODE_ID) { - iter->mode = MODE_TO_SLASH; - return; - } - - if (iter->view == ITER_VIEW_NO_HOST) { - iter->mode = MODE_TO_END; - return; - } - - if (iter->view == ITER_VIEW_ADDRESS_HASH) { - iter->mode = MODE_TO_END; - parse_address_view(iter); - return; - } - - if (iter->view == ITER_VIEW_NODE_HASH) { - iter->mode = MODE_TO_END; - parse_node_view(iter); - return; - } - - if (iter->view == ITER_VIEW_NODE_SPECIFIC) { - iter->mode = MODE_TO_END; - while (!dx_field_iterator_end(iter)) { - octet = dx_field_iterator_octet(iter); - if (octet == '/') - break; - } - return; - } -} - - -void dx_field_iterator_set_address(const char *area, const char *router) -{ - my_area = (char*) malloc(strlen(area) + 2); - strcpy(my_area, area); - strcat(my_area, "/"); - - my_router = (char*) malloc(strlen(router) + 2); - strcpy(my_router, router); - strcat(my_router, "/"); -} - - -dx_field_iterator_t* dx_field_iterator_string(const char *text, dx_iterator_view_t view) -{ - dx_field_iterator_t *iter = new_dx_field_iterator_t(); - if (!iter) - return 0; - - iter->start_pointer.buffer = 0; - iter->start_pointer.cursor = (unsigned char*) text; - iter->start_pointer.length = strlen(text); - - dx_field_iterator_reset_view(iter, view); - - return iter; -} - - -dx_field_iterator_t* dx_field_iterator_binary(const char *text, int length, dx_iterator_view_t view) -{ - dx_field_iterator_t *iter = new_dx_field_iterator_t(); - if (!iter) - return 0; - - iter->start_pointer.buffer = 0; - iter->start_pointer.cursor = (unsigned char*) text; - iter->start_pointer.length = length; - - dx_field_iterator_reset_view(iter, view); - - return iter; -} - - -dx_field_iterator_t *dx_field_iterator_buffer(dx_buffer_t *buffer, int offset, int length, dx_iterator_view_t view) -{ - dx_field_iterator_t *iter = new_dx_field_iterator_t(); - if (!iter) - return 0; - - iter->start_pointer.buffer = buffer; - iter->start_pointer.cursor = dx_buffer_base(buffer) + offset; - iter->start_pointer.length = length; - - dx_field_iterator_reset_view(iter, view); - - return iter; -} - - -void dx_field_iterator_free(dx_field_iterator_t *iter) -{ - free_dx_field_iterator_t(iter); -} - - -void dx_field_iterator_reset(dx_field_iterator_t *iter) -{ - iter->pointer = iter->view_start_pointer; - iter->at_prefix = iter->view_prefix; -} - - -void dx_field_iterator_reset_view(dx_field_iterator_t *iter, dx_iterator_view_t view) -{ - iter->pointer = iter->start_pointer; - iter->view = view; - - view_initialize(iter); - - iter->view_start_pointer = iter->pointer; -} - - -unsigned char dx_field_iterator_octet(dx_field_iterator_t *iter) -{ - if (iter->at_prefix) { - iter->at_prefix = 0; - return iter->prefix; - } - - if (iter->pointer.length == 0) - return (unsigned char) 0; - - unsigned char result = *(iter->pointer.cursor); - - iter->pointer.cursor++; - iter->pointer.length--; - - if (iter->pointer.length > 0) { - if (iter->pointer.buffer) { - if (iter->pointer.cursor - dx_buffer_base(iter->pointer.buffer) == dx_buffer_size(iter->pointer.buffer)) { - iter->pointer.buffer = iter->pointer.buffer->next; - if (iter->pointer.buffer == 0) - iter->pointer.length = 0; - iter->pointer.cursor = dx_buffer_base(iter->pointer.buffer); - } - } - } - - if (iter->pointer.length && iter->mode == MODE_TO_SLASH && *(iter->pointer.cursor) == '/') - iter->pointer.length = 0; - - return result; -} - - -int dx_field_iterator_end(dx_field_iterator_t *iter) -{ - return iter->pointer.length == 0; -} - - -dx_field_iterator_t *dx_field_iterator_sub(dx_field_iterator_t *iter, uint32_t length) -{ - dx_field_iterator_t *sub = new_dx_field_iterator_t(); - if (!sub) - return 0; - - sub->start_pointer = iter->pointer; - sub->start_pointer.length = length; - sub->view_start_pointer = sub->start_pointer; - sub->pointer = sub->start_pointer; - sub->view = iter->view; - sub->mode = iter->mode; - sub->at_prefix = 0; - sub->view_prefix = 0; - - return sub; -} - - -void dx_field_iterator_advance(dx_field_iterator_t *iter, uint32_t length) -{ - // TODO - Make this more efficient. - for (uint8_t idx = 0; idx < length && !dx_field_iterator_end(iter); idx++) - dx_field_iterator_octet(iter); -} - - -uint32_t dx_field_iterator_remaining(dx_field_iterator_t *iter) -{ - return iter->pointer.length; -} - - -int dx_field_iterator_equal(dx_field_iterator_t *iter, const unsigned char *string) -{ - dx_field_iterator_reset(iter); - while (!dx_field_iterator_end(iter) && *string) { - if (*string != dx_field_iterator_octet(iter)) - return 0; - string++; - } - - return (dx_field_iterator_end(iter) && (*string == 0)); -} - - -int dx_field_iterator_prefix(dx_field_iterator_t *iter, const char *prefix) -{ - pointer_t save_pointer = iter->pointer; - unsigned char *c = (unsigned char*) prefix; - - while(*c) { - if (*c != dx_field_iterator_octet(iter)) - break; - c++; - } - - if (*c) { - iter->pointer = save_pointer; - return 0; - } - - return 1; -} - - -unsigned char *dx_field_iterator_copy(dx_field_iterator_t *iter) -{ - int length = 0; - int idx = 0; - unsigned char *copy; - - dx_field_iterator_reset(iter); - while (!dx_field_iterator_end(iter)) { - dx_field_iterator_octet(iter); - length++; - } - - dx_field_iterator_reset(iter); - copy = (unsigned char*) malloc(length + 1); - while (!dx_field_iterator_end(iter)) - copy[idx++] = dx_field_iterator_octet(iter); - copy[idx] = '\0'; - - return copy; -} - - -dx_iovec_t *dx_field_iterator_iovec(const dx_field_iterator_t *iter) -{ - assert(!iter->view_prefix); // Not supported for views with a prefix - - // - // Count the number of buffers this field straddles - // - pointer_t pointer = iter->view_start_pointer; - int bufcnt = 1; - dx_buffer_t *buf = pointer.buffer; - size_t bufsize = dx_buffer_size(buf) - (pointer.cursor - dx_buffer_base(pointer.buffer)); - ssize_t remaining = pointer.length - bufsize; - - while (remaining > 0) { - bufcnt++; - buf = buf->next; - if (!buf) - return 0; - remaining -= dx_buffer_size(buf); - } - - // - // Allocate an iovec object big enough to hold the number of buffers - // - dx_iovec_t *iov = dx_iovec(bufcnt); - if (!iov) - return 0; - - // - // Build out the io vectors with pointers to the segments of the field in buffers - // - bufcnt = 0; - buf = pointer.buffer; - bufsize = dx_buffer_size(buf) - (pointer.cursor - dx_buffer_base(pointer.buffer)); - void *base = pointer.cursor; - remaining = pointer.length; - - while (remaining > 0) { - if (bufsize > remaining) - bufsize = remaining; - dx_iovec_array(iov)[bufcnt].iov_base = base; - dx_iovec_array(iov)[bufcnt].iov_len = bufsize; - bufcnt++; - remaining -= bufsize; - if (remaining > 0) { - buf = buf->next; - base = dx_buffer_base(buf); - bufsize = dx_buffer_size(buf); - } - } - - return iov; -} - - diff --git a/extras/dispatch/src/log.c b/extras/dispatch/src/log.c deleted file mode 100644 index 281603255d..0000000000 --- a/extras/dispatch/src/log.c +++ /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 "log_private.h" -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/threading.h> -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <sys/time.h> - -#define TEXT_MAX 512 -#define LIST_MAX 1000 - -typedef struct dx_log_entry_t dx_log_entry_t; - -struct dx_log_entry_t { - DEQ_LINKS(dx_log_entry_t); - const char *module; - int cls; - const char *file; - int line; - struct timeval tv; - char text[TEXT_MAX]; -}; - -ALLOC_DECLARE(dx_log_entry_t); -ALLOC_DEFINE(dx_log_entry_t); - -DEQ_DECLARE(dx_log_entry_t, dx_log_list_t); - -static int mask = LOG_INFO; -static dx_log_list_t entries; -static sys_mutex_t *log_lock = 0; - - -static const char *cls_prefix(int cls) -{ - switch (cls) { - case LOG_TRACE : return "TRACE"; - case LOG_DEBUG : return "DEBUG"; - case LOG_INFO : return "INFO"; - case LOG_NOTICE : return "NOTICE"; - case LOG_WARNING : return "WARNING"; - case LOG_ERROR : return "ERROR"; - case LOG_CRITICAL : return "CRITICAL"; - } - - return ""; -} - -void dx_log_impl(const char *module, int cls, const char *file, int line, const char *fmt, ...) -{ - if (!(cls & mask)) - return; - - dx_log_entry_t *entry = new_dx_log_entry_t(); - DEQ_ITEM_INIT(entry); - entry->module = module; - entry->cls = cls; - entry->file = file; - entry->line = line; - gettimeofday(&entry->tv, 0); - - va_list ap; - - va_start(ap, fmt); - vsnprintf(entry->text, TEXT_MAX, fmt, ap); - va_end(ap); - fprintf(stderr, "%s (%s) %s\n", module, cls_prefix(cls), entry->text); - - sys_mutex_lock(log_lock); - DEQ_INSERT_TAIL(entries, entry); - if (DEQ_SIZE(entries) > LIST_MAX) { - entry = DEQ_HEAD(entries); - DEQ_REMOVE_HEAD(entries); - free_dx_log_entry_t(entry); - } - sys_mutex_unlock(log_lock); -} - -void dx_log_set_mask(int _mask) -{ - mask = _mask; -} - - -void dx_log_initialize(void) -{ - DEQ_INIT(entries); - log_lock = sys_mutex(); -} - - -void dx_log_finalize(void) -{ -} - - diff --git a/extras/dispatch/src/log_private.h b/extras/dispatch/src/log_private.h deleted file mode 100644 index 0b36bbc9a9..0000000000 --- a/extras/dispatch/src/log_private.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __log_private_h__ -#define __log_private_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/log.h> - -void dx_log_initialize(void); -void dx_log_finalize(void); - -#endif diff --git a/extras/dispatch/src/message.c b/extras/dispatch/src/message.c deleted file mode 100644 index 86ffcefcee..0000000000 --- a/extras/dispatch/src/message.c +++ /dev/null @@ -1,879 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/amqp.h> -#include <qpid/dispatch/threading.h> -#include "message_private.h" -#include "compose_private.h" -#include <string.h> -#include <stdio.h> - -static const unsigned char * const MSG_HDR_LONG = (unsigned char*) "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x70"; -static const unsigned char * const MSG_HDR_SHORT = (unsigned char*) "\x00\x53\x70"; -static const unsigned char * const DELIVERY_ANNOTATION_LONG = (unsigned char*) "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x71"; -static const unsigned char * const DELIVERY_ANNOTATION_SHORT = (unsigned char*) "\x00\x53\x71"; -static const unsigned char * const MESSAGE_ANNOTATION_LONG = (unsigned char*) "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x72"; -static const unsigned char * const MESSAGE_ANNOTATION_SHORT = (unsigned char*) "\x00\x53\x72"; -static const unsigned char * const PROPERTIES_LONG = (unsigned char*) "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x73"; -static const unsigned char * const PROPERTIES_SHORT = (unsigned char*) "\x00\x53\x73"; -static const unsigned char * const APPLICATION_PROPERTIES_LONG = (unsigned char*) "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x74"; -static const unsigned char * const APPLICATION_PROPERTIES_SHORT = (unsigned char*) "\x00\x53\x74"; -static const unsigned char * const BODY_DATA_LONG = (unsigned char*) "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x75"; -static const unsigned char * const BODY_DATA_SHORT = (unsigned char*) "\x00\x53\x75"; -static const unsigned char * const BODY_SEQUENCE_LONG = (unsigned char*) "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x76"; -static const unsigned char * const BODY_SEQUENCE_SHORT = (unsigned char*) "\x00\x53\x76"; -static const unsigned char * const BODY_VALUE_LONG = (unsigned char*) "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x77"; -static const unsigned char * const BODY_VALUE_SHORT = (unsigned char*) "\x00\x53\x77"; -static const unsigned char * const FOOTER_LONG = (unsigned char*) "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x78"; -static const unsigned char * const FOOTER_SHORT = (unsigned char*) "\x00\x53\x78"; -static const unsigned char * const TAGS_LIST = (unsigned char*) "\x45\xc0\xd0"; -static const unsigned char * const TAGS_MAP = (unsigned char*) "\xc1\xd1"; -static const unsigned char * const TAGS_BINARY = (unsigned char*) "\xa0\xb0"; -static const unsigned char * const TAGS_ANY = (unsigned char*) "\x45\xc0\xd0\xc1\xd1\xa0\xb0"; - -ALLOC_DEFINE_CONFIG(dx_message_t, sizeof(dx_message_pvt_t), 0, 0); -ALLOC_DEFINE(dx_message_content_t); - -typedef void (*buffer_process_t) (void *context, const unsigned char *base, int length); - -static void advance(unsigned char **cursor, dx_buffer_t **buffer, int consume, buffer_process_t handler, void *context) -{ - unsigned char *local_cursor = *cursor; - dx_buffer_t *local_buffer = *buffer; - - int remaining = dx_buffer_size(local_buffer) - (local_cursor - dx_buffer_base(local_buffer)); - while (consume > 0) { - if (consume < remaining) { - if (handler) - handler(context, local_cursor, consume); - local_cursor += consume; - consume = 0; - } else { - if (handler) - handler(context, local_cursor, remaining); - consume -= remaining; - local_buffer = local_buffer->next; - if (local_buffer == 0){ - local_cursor = 0; - break; - } - local_cursor = dx_buffer_base(local_buffer); - remaining = dx_buffer_size(local_buffer) - (local_cursor - dx_buffer_base(local_buffer)); - } - } - - *cursor = local_cursor; - *buffer = local_buffer; -} - - -static unsigned char next_octet(unsigned char **cursor, dx_buffer_t **buffer) -{ - unsigned char result = **cursor; - advance(cursor, buffer, 1, 0, 0); - return result; -} - - -static int traverse_field(unsigned char **cursor, dx_buffer_t **buffer, dx_field_location_t *field) -{ - unsigned char tag = next_octet(cursor, buffer); - if (!(*cursor)) return 0; - - int consume = 0; - size_t hdr_length = 1; - - switch (tag & 0xF0) { - case 0x40 : consume = 0; break; - case 0x50 : consume = 1; break; - case 0x60 : consume = 2; break; - case 0x70 : consume = 4; break; - case 0x80 : consume = 8; break; - case 0x90 : consume = 16; break; - - case 0xB0 : - case 0xD0 : - case 0xF0 : - hdr_length += 3; - consume |= ((int) next_octet(cursor, buffer)) << 24; - if (!(*cursor)) return 0; - consume |= ((int) next_octet(cursor, buffer)) << 16; - if (!(*cursor)) return 0; - consume |= ((int) next_octet(cursor, buffer)) << 8; - if (!(*cursor)) return 0; - // Fall through to the next case... - - case 0xA0 : - case 0xC0 : - case 0xE0 : - hdr_length++; - consume |= (int) next_octet(cursor, buffer); - if (!(*cursor)) return 0; - break; - } - - if (field && !field->parsed) { - field->buffer = *buffer; - field->offset = *cursor - dx_buffer_base(*buffer); - field->length = consume; - field->hdr_length = hdr_length; - field->parsed = 1; - } - - advance(cursor, buffer, consume, 0, 0); - return 1; -} - - -static int start_list(unsigned char **cursor, dx_buffer_t **buffer) -{ - unsigned char tag = next_octet(cursor, buffer); - if (!(*cursor)) return 0; - int length = 0; - int count = 0; - - switch (tag) { - case 0x45 : // list0 - break; - case 0xd0 : // list32 - length |= ((int) next_octet(cursor, buffer)) << 24; - if (!(*cursor)) return 0; - length |= ((int) next_octet(cursor, buffer)) << 16; - if (!(*cursor)) return 0; - length |= ((int) next_octet(cursor, buffer)) << 8; - if (!(*cursor)) return 0; - length |= (int) next_octet(cursor, buffer); - if (!(*cursor)) return 0; - - count |= ((int) next_octet(cursor, buffer)) << 24; - if (!(*cursor)) return 0; - count |= ((int) next_octet(cursor, buffer)) << 16; - if (!(*cursor)) return 0; - count |= ((int) next_octet(cursor, buffer)) << 8; - if (!(*cursor)) return 0; - count |= (int) next_octet(cursor, buffer); - if (!(*cursor)) return 0; - - break; - - case 0xc0 : // list8 - length |= (int) next_octet(cursor, buffer); - if (!(*cursor)) return 0; - - count |= (int) next_octet(cursor, buffer); - if (!(*cursor)) return 0; - break; - } - - return count; -} - - -// -// Check the buffer chain, starting at cursor to see if it matches the pattern. -// If the pattern matches, check the next tag to see if it's in the set of expected -// tags. If not, return zero. If so, set the location descriptor to the good -// tag and advance the cursor (and buffer, if needed) to the end of the matched section. -// -// If there is no match, don't advance the cursor. -// -// Return 0 if the pattern matches but the following tag is unexpected -// Return 0 if the pattern matches and the location already has a pointer (duplicate section) -// Return 1 if the pattern matches and we've advanced the cursor/buffer -// Return 1 if the pattern does not match -// -static int dx_check_and_advance(dx_buffer_t **buffer, - unsigned char **cursor, - const unsigned char *pattern, - int pattern_length, - const unsigned char *expected_tags, - dx_field_location_t *location) -{ - dx_buffer_t *test_buffer = *buffer; - unsigned char *test_cursor = *cursor; - - if (!test_cursor) - return 1; // no match - - unsigned char *end_of_buffer = dx_buffer_base(test_buffer) + dx_buffer_size(test_buffer); - int idx = 0; - - while (idx < pattern_length && *test_cursor == pattern[idx]) { - idx++; - test_cursor++; - if (test_cursor == end_of_buffer) { - test_buffer = test_buffer->next; - if (test_buffer == 0) - return 1; // Pattern didn't match - test_cursor = dx_buffer_base(test_buffer); - end_of_buffer = test_cursor + dx_buffer_size(test_buffer); - } - } - - if (idx < pattern_length) - return 1; // Pattern didn't match - - // - // Pattern matched, check the tag - // - while (*expected_tags && *test_cursor != *expected_tags) - expected_tags++; - if (*expected_tags == 0) - return 0; // Unexpected tag - - if (location->parsed) - return 0; // Duplicate section - - // - // Pattern matched and tag is expected. Mark the beginning of the section. - // - location->parsed = 1; - location->buffer = test_buffer; - location->offset = test_cursor - dx_buffer_base(test_buffer); - location->length = 0; - location->hdr_length = pattern_length; - - // - // Advance the pointers to consume the whole section. - // - int pre_consume = 1; // Count the already extracted tag - int consume = 0; - unsigned char tag = next_octet(&test_cursor, &test_buffer); - if (!test_cursor) return 0; - switch (tag) { - case 0x45 : // list0 - break; - - case 0xd0 : // list32 - case 0xd1 : // map32 - case 0xb0 : // vbin32 - pre_consume += 3; - consume |= ((int) next_octet(&test_cursor, &test_buffer)) << 24; - if (!test_cursor) return 0; - consume |= ((int) next_octet(&test_cursor, &test_buffer)) << 16; - if (!test_cursor) return 0; - consume |= ((int) next_octet(&test_cursor, &test_buffer)) << 8; - if (!test_cursor) return 0; - // Fall through to the next case... - - case 0xc0 : // list8 - case 0xc1 : // map8 - case 0xa0 : // vbin8 - pre_consume += 1; - consume |= (int) next_octet(&test_cursor, &test_buffer); - if (!test_cursor) return 0; - break; - } - - location->length = pre_consume + consume; - if (consume) - advance(&test_cursor, &test_buffer, consume, 0, 0); - - *cursor = test_cursor; - *buffer = test_buffer; - return 1; -} - - -static dx_field_location_t *dx_message_field_location(dx_message_t *msg, dx_message_field_t field) -{ - dx_message_content_t *content = MSG_CONTENT(msg); - - switch (field) { - case DX_FIELD_TO: - while (1) { - if (content->field_to.parsed) - return &content->field_to; - - if (content->section_message_properties.parsed == 0) - break; - - dx_buffer_t *buffer = content->section_message_properties.buffer; - unsigned char *cursor = dx_buffer_base(buffer) + content->section_message_properties.offset; - - int count = start_list(&cursor, &buffer); - int result; - - if (count < 3) - break; - - result = traverse_field(&cursor, &buffer, 0); // message_id - if (!result) return 0; - result = traverse_field(&cursor, &buffer, &content->field_user_id); // user_id - if (!result) return 0; - result = traverse_field(&cursor, &buffer, &content->field_to); // to - if (!result) return 0; - } - break; - - case DX_FIELD_REPLY_TO: - while (1) { - if (content->field_reply_to.parsed) - return &content->field_reply_to; - - if (content->section_message_properties.parsed == 0) - break; - - dx_buffer_t *buffer = content->section_message_properties.buffer; - unsigned char *cursor = dx_buffer_base(buffer) + content->section_message_properties.offset; - - int count = start_list(&cursor, &buffer); - int result; - - if (count < 5) - break; - - result = traverse_field(&cursor, &buffer, 0); // message_id - if (!result) return 0; - result = traverse_field(&cursor, &buffer, &content->field_user_id); // user_id - if (!result) return 0; - result = traverse_field(&cursor, &buffer, &content->field_to); // to - if (!result) return 0; - result = traverse_field(&cursor, &buffer, 0); // subject - if (!result) return 0; - result = traverse_field(&cursor, &buffer, &content->field_reply_to); // reply_to - if (!result) return 0; - } - break; - - case DX_FIELD_DELIVERY_ANNOTATION: - if (content->section_delivery_annotation.parsed) - return &content->section_delivery_annotation; - break; - - case DX_FIELD_APPLICATION_PROPERTIES: - if (content->section_application_properties.parsed) - return &content->section_application_properties; - break; - - case DX_FIELD_BODY: - if (content->section_body.parsed) - return &content->section_body; - break; - - default: - break; - } - - return 0; -} - - -dx_message_t *dx_message() -{ - dx_message_pvt_t *msg = (dx_message_pvt_t*) new_dx_message_t(); - if (!msg) - return 0; - - DEQ_ITEM_INIT(msg); - msg->content = new_dx_message_content_t(); - - if (msg->content == 0) { - free_dx_message_t((dx_message_t*) msg); - return 0; - } - - memset(msg->content, 0, sizeof(dx_message_content_t)); - msg->content->lock = sys_mutex(); - msg->content->ref_count = 1; - msg->content->parse_depth = DX_DEPTH_NONE; - msg->content->parsed_delivery_annotations = 0; - - return (dx_message_t*) msg; -} - - -void dx_message_free(dx_message_t *in_msg) -{ - uint32_t rc; - dx_message_pvt_t *msg = (dx_message_pvt_t*) in_msg; - dx_message_content_t *content = msg->content; - - sys_mutex_lock(content->lock); - rc = --content->ref_count; - sys_mutex_unlock(content->lock); - - if (rc == 0) { - if (content->parsed_delivery_annotations) - dx_parse_free(content->parsed_delivery_annotations); - - dx_buffer_t *buf = DEQ_HEAD(content->buffers); - while (buf) { - DEQ_REMOVE_HEAD(content->buffers); - dx_buffer_free(buf); - buf = DEQ_HEAD(content->buffers); - } - - buf = DEQ_HEAD(content->new_delivery_annotations); - while (buf) { - DEQ_REMOVE_HEAD(content->new_delivery_annotations); - dx_buffer_free(buf); - buf = DEQ_HEAD(content->new_delivery_annotations); - } - - sys_mutex_free(content->lock); - free_dx_message_content_t(content); - } - - free_dx_message_t((dx_message_t*) msg); -} - - -dx_message_t *dx_message_copy(dx_message_t *in_msg) -{ - dx_message_pvt_t *msg = (dx_message_pvt_t*) in_msg; - dx_message_content_t *content = msg->content; - dx_message_pvt_t *copy = (dx_message_pvt_t*) new_dx_message_t(); - - if (!copy) - return 0; - - DEQ_ITEM_INIT(copy); - copy->content = content; - - sys_mutex_lock(content->lock); - content->ref_count++; - sys_mutex_unlock(content->lock); - - return (dx_message_t*) copy; -} - - -dx_parsed_field_t *dx_message_delivery_annotations(dx_message_t *in_msg) -{ - dx_message_pvt_t *msg = (dx_message_pvt_t*) in_msg; - dx_message_content_t *content = msg->content; - - if (content->parsed_delivery_annotations) - return content->parsed_delivery_annotations; - - dx_field_iterator_t *da = dx_message_field_iterator(in_msg, DX_FIELD_DELIVERY_ANNOTATION); - if (da == 0) - return 0; - - content->parsed_delivery_annotations = dx_parse(da); - if (content->parsed_delivery_annotations == 0 || - !dx_parse_ok(content->parsed_delivery_annotations) || - !dx_parse_is_map(content->parsed_delivery_annotations)) { - dx_field_iterator_free(da); - dx_parse_free(content->parsed_delivery_annotations); - content->parsed_delivery_annotations = 0; - return 0; - } - - dx_field_iterator_free(da); - return content->parsed_delivery_annotations; -} - - -void dx_message_set_delivery_annotations(dx_message_t *msg, dx_composed_field_t *da) -{ - dx_message_content_t *content = MSG_CONTENT(msg); - dx_buffer_list_t *field_buffers = dx_compose_buffers(da); - - assert(DEQ_SIZE(content->new_delivery_annotations) == 0); - content->new_delivery_annotations = *field_buffers; - DEQ_INIT(*field_buffers); // Zero out the linkage to the now moved buffers. -} - - -dx_message_t *dx_message_receive(dx_delivery_t *delivery) -{ - pn_delivery_t *pnd = dx_delivery_pn(delivery); - dx_message_pvt_t *msg = (dx_message_pvt_t*) dx_delivery_context(delivery); - pn_link_t *link = pn_delivery_link(pnd); - ssize_t rc; - dx_buffer_t *buf; - - // - // If there is no message associated with the delivery, this is the first time - // we've received anything on this delivery. Allocate a message descriptor and - // link it and the delivery together. - // - if (!msg) { - msg = (dx_message_pvt_t*) dx_message(); - dx_delivery_set_context(delivery, (void*) msg); - } - - // - // Get a reference to the tail buffer on the message. This is the buffer into which - // we will store incoming message data. If there is no buffer in the message, allocate - // an empty one and add it to the message. - // - buf = DEQ_TAIL(msg->content->buffers); - if (!buf) { - buf = dx_buffer(); - DEQ_INSERT_TAIL(msg->content->buffers, buf); - } - - while (1) { - // - // Try to receive enough data to fill the remaining space in the tail buffer. - // - rc = pn_link_recv(link, (char*) dx_buffer_cursor(buf), dx_buffer_capacity(buf)); - - // - // If we receive PN_EOS, we have come to the end of the message. - // - if (rc == PN_EOS) { - // - // If the last buffer in the list is empty, remove it and free it. This - // will only happen if the size of the message content is an exact multiple - // of the buffer size. - // - if (dx_buffer_size(buf) == 0) { - DEQ_REMOVE_TAIL(msg->content->buffers); - dx_buffer_free(buf); - } - dx_delivery_set_context(delivery, 0); - return (dx_message_t*) msg; - } - - if (rc > 0) { - // - // We have received a positive number of bytes for the message. Advance - // the cursor in the buffer. - // - dx_buffer_insert(buf, rc); - - // - // If the buffer is full, allocate a new empty buffer and append it to the - // tail of the message's list. - // - if (dx_buffer_capacity(buf) == 0) { - buf = dx_buffer(); - DEQ_INSERT_TAIL(msg->content->buffers, buf); - } - } else - // - // We received zero bytes, and no PN_EOS. This means that we've received - // all of the data available up to this point, but it does not constitute - // the entire message. We'll be back later to finish it up. - // - break; - } - - return 0; -} - - -static void send_handler(void *context, const unsigned char *start, int length) -{ - pn_link_t *pnl = (pn_link_t*) context; - pn_link_send(pnl, (const char*) start, length); -} - - -void dx_message_send(dx_message_t *in_msg, dx_link_t *link) -{ - dx_message_pvt_t *msg = (dx_message_pvt_t*) in_msg; - dx_message_content_t *content = msg->content; - dx_buffer_t *buf = DEQ_HEAD(content->buffers); - unsigned char *cursor; - pn_link_t *pnl = dx_link_pn(link); - - if (DEQ_SIZE(content->new_delivery_annotations) > 0) { - // - // This is the case where the delivery annotations have been modified. - // The message send must be divided into sections: The existing header; - // the new delivery annotations; the rest of the existing message. - // Note that the original delivery annotations that are still in the - // buffer chain must not be sent. - // - // Start by making sure that we've parsed the message sections through - // the delivery annotations - // - if (!dx_message_check(in_msg, DX_DEPTH_DELIVERY_ANNOTATIONS)) - return; - - // - // Send header if present - // - cursor = dx_buffer_base(buf); - if (content->section_message_header.length > 0) { - pn_link_send(pnl, (const char*) MSG_HDR_SHORT, 3); - buf = content->section_message_header.buffer; - cursor = content->section_message_header.offset + dx_buffer_base(buf); - advance(&cursor, &buf, content->section_message_header.length, send_handler, (void*) pnl); - } - - // - // Send new delivery annotations - // - dx_buffer_t *da_buf = DEQ_HEAD(content->new_delivery_annotations); - while (da_buf) { - pn_link_send(pnl, (char*) dx_buffer_base(da_buf), dx_buffer_size(da_buf)); - da_buf = DEQ_NEXT(da_buf); - } - - // - // Skip over replaced delivery annotations - // - if (content->section_delivery_annotation.length > 0) - advance(&cursor, &buf, - content->section_delivery_annotation.hdr_length + content->section_delivery_annotation.length, - 0, 0); - - // - // Send remaining partial buffer - // - if (buf) { - size_t len = dx_buffer_size(buf) - (cursor - dx_buffer_base(buf)); - advance(&cursor, &buf, len, send_handler, (void*) pnl); - } - - // Fall through to process the remaining buffers normally - } - - while (buf) { - pn_link_send(pnl, (char*) dx_buffer_base(buf), dx_buffer_size(buf)); - buf = DEQ_NEXT(buf); - } -} - - -static int dx_check_field_LH(dx_message_content_t *content, - dx_message_depth_t depth, - const unsigned char *long_pattern, - const unsigned char *short_pattern, - const unsigned char *expected_tags, - dx_field_location_t *location, - int more) -{ -#define LONG 10 -#define SHORT 3 - if (depth > content->parse_depth) { - if (0 == dx_check_and_advance(&content->parse_buffer, &content->parse_cursor, long_pattern, LONG, expected_tags, location)) - return 0; - if (0 == dx_check_and_advance(&content->parse_buffer, &content->parse_cursor, short_pattern, SHORT, expected_tags, location)) - return 0; - if (!more) - content->parse_depth = depth; - } - return 1; -} - - -static int dx_message_check_LH(dx_message_content_t *content, dx_message_depth_t depth) -{ - dx_buffer_t *buffer = DEQ_HEAD(content->buffers); - - if (!buffer) - return 0; // Invalid - No data in the message - - if (depth <= content->parse_depth) - return 1; // We've already parsed at least this deep - - if (content->parse_buffer == 0) { - content->parse_buffer = buffer; - content->parse_cursor = dx_buffer_base(content->parse_buffer); - } - - if (depth == DX_DEPTH_NONE) - return 1; - - // - // MESSAGE HEADER - // - if (0 == dx_check_field_LH(content, DX_DEPTH_HEADER, - MSG_HDR_LONG, MSG_HDR_SHORT, TAGS_LIST, &content->section_message_header, 0)) - return 0; - if (depth == DX_DEPTH_HEADER) - return 1; - - // - // DELIVERY ANNOTATION - // - if (0 == dx_check_field_LH(content, DX_DEPTH_DELIVERY_ANNOTATIONS, - DELIVERY_ANNOTATION_LONG, DELIVERY_ANNOTATION_SHORT, TAGS_MAP, &content->section_delivery_annotation, 0)) - return 0; - if (depth == DX_DEPTH_DELIVERY_ANNOTATIONS) - return 1; - - // - // MESSAGE ANNOTATION - // - if (0 == dx_check_field_LH(content, DX_DEPTH_MESSAGE_ANNOTATIONS, - MESSAGE_ANNOTATION_LONG, MESSAGE_ANNOTATION_SHORT, TAGS_MAP, &content->section_message_annotation, 0)) - return 0; - if (depth == DX_DEPTH_MESSAGE_ANNOTATIONS) - return 1; - - // - // PROPERTIES - // - if (0 == dx_check_field_LH(content, DX_DEPTH_PROPERTIES, - PROPERTIES_LONG, PROPERTIES_SHORT, TAGS_LIST, &content->section_message_properties, 0)) - return 0; - if (depth == DX_DEPTH_PROPERTIES) - return 1; - - // - // APPLICATION PROPERTIES - // - if (0 == dx_check_field_LH(content, DX_DEPTH_APPLICATION_PROPERTIES, - APPLICATION_PROPERTIES_LONG, APPLICATION_PROPERTIES_SHORT, TAGS_MAP, &content->section_application_properties, 0)) - return 0; - if (depth == DX_DEPTH_APPLICATION_PROPERTIES) - return 1; - - // - // BODY - // Note that this function expects a limited set of types in a VALUE section. This is - // not a problem for messages passing through Dispatch because through-only messages won't - // be parsed to BODY-depth. - // - if (0 == dx_check_field_LH(content, DX_DEPTH_BODY, - BODY_DATA_LONG, BODY_DATA_SHORT, TAGS_BINARY, &content->section_body, 1)) - return 0; - if (0 == dx_check_field_LH(content, DX_DEPTH_BODY, - BODY_SEQUENCE_LONG, BODY_SEQUENCE_SHORT, TAGS_LIST, &content->section_body, 1)) - return 0; - if (0 == dx_check_field_LH(content, DX_DEPTH_BODY, - BODY_VALUE_LONG, BODY_VALUE_SHORT, TAGS_ANY, &content->section_body, 0)) - return 0; - if (depth == DX_DEPTH_BODY) - return 1; - - // - // FOOTER - // - if (0 == dx_check_field_LH(content, DX_DEPTH_ALL, - FOOTER_LONG, FOOTER_SHORT, TAGS_MAP, &content->section_footer, 0)) - return 0; - - return 1; -} - - -int dx_message_check(dx_message_t *in_msg, dx_message_depth_t depth) -{ - dx_message_pvt_t *msg = (dx_message_pvt_t*) in_msg; - dx_message_content_t *content = msg->content; - int result; - - sys_mutex_lock(content->lock); - result = dx_message_check_LH(content, depth); - sys_mutex_unlock(content->lock); - - return result; -} - - -dx_field_iterator_t *dx_message_field_iterator(dx_message_t *msg, dx_message_field_t field) -{ - dx_field_location_t *loc = dx_message_field_location(msg, field); - if (!loc) - return 0; - - return dx_field_iterator_buffer(loc->buffer, loc->offset, loc->length, ITER_VIEW_ALL); -} - - -ssize_t dx_message_field_length(dx_message_t *msg, dx_message_field_t field) -{ - dx_field_location_t *loc = dx_message_field_location(msg, field); - if (!loc) - return -1; - - return loc->length; -} - - -ssize_t dx_message_field_copy(dx_message_t *msg, dx_message_field_t field, void *buffer) -{ - dx_field_location_t *loc = dx_message_field_location(msg, field); - if (!loc) - return -1; - - dx_buffer_t *buf = loc->buffer; - size_t bufsize = dx_buffer_size(buf) - loc->offset; - void *base = dx_buffer_base(buf) + loc->offset; - size_t remaining = loc->length; - - while (remaining > 0) { - if (bufsize > remaining) - bufsize = remaining; - memcpy(buffer, base, bufsize); - buffer += bufsize; - remaining -= bufsize; - if (remaining > 0) { - buf = buf->next; - base = dx_buffer_base(buf); - bufsize = dx_buffer_size(buf); - } - } - - return loc->length; -} - - -void dx_message_compose_1(dx_message_t *msg, const char *to, dx_buffer_list_t *buffers) -{ - dx_composed_field_t *field = dx_compose(DX_PERFORMATIVE_HEADER, 0); - dx_message_content_t *content = MSG_CONTENT(msg); - - dx_compose_start_list(field); - dx_compose_insert_bool(field, 0); // durable - //dx_compose_insert_null(field); // priority - //dx_compose_insert_null(field); // ttl - //dx_compose_insert_boolean(field, 0); // first-acquirer - //dx_compose_insert_uint(field, 0); // delivery-count - dx_compose_end_list(field); - - field = dx_compose(DX_PERFORMATIVE_PROPERTIES, field); - dx_compose_start_list(field); - dx_compose_insert_null(field); // message-id - dx_compose_insert_null(field); // user-id - dx_compose_insert_string(field, to); // to - //dx_compose_insert_null(field); // subject - //dx_compose_insert_null(field); // reply-to - //dx_compose_insert_null(field); // correlation-id - //dx_compose_insert_null(field); // content-type - //dx_compose_insert_null(field); // content-encoding - //dx_compose_insert_timestamp(field, 0); // absolute-expiry-time - //dx_compose_insert_timestamp(field, 0); // creation-time - //dx_compose_insert_null(field); // group-id - //dx_compose_insert_uint(field, 0); // group-sequence - //dx_compose_insert_null(field); // reply-to-group-id - dx_compose_end_list(field); - - if (buffers) { - field = dx_compose(DX_PERFORMATIVE_BODY_DATA, field); - dx_compose_insert_binary_buffers(field, buffers); - } - - dx_buffer_list_t *field_buffers = dx_compose_buffers(field); - content->buffers = *field_buffers; - DEQ_INIT(*field_buffers); // Zero out the linkage to the now moved buffers. - - dx_compose_free(field); -} - - -void dx_message_compose_2(dx_message_t *msg, dx_composed_field_t *field) -{ - dx_message_content_t *content = MSG_CONTENT(msg); - dx_buffer_list_t *field_buffers = dx_compose_buffers(field); - - content->buffers = *field_buffers; - DEQ_INIT(*field_buffers); // Zero out the linkage to the now moved buffers. -} - diff --git a/extras/dispatch/src/message_private.h b/extras/dispatch/src/message_private.h deleted file mode 100644 index c57cea5f0d..0000000000 --- a/extras/dispatch/src/message_private.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef __message_private_h__ -#define __message_private_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/message.h> -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/threading.h> - -/** - * Architecture of the message module: - * - * +--------------+ +----------------------+ - * | | | | - * | dx_message_t |----------->| dx_message_content_t | - * | | +----->| | - * +--------------+ | +----------------------+ - * | | - * +--------------+ | | +-------------+ +-------------+ +-------------+ - * | | | +--->| dx_buffer_t |-->| dx_buffer_t |-->| dx_buffer_t |--/ - * | dx_message_t |-----+ +-------------+ +-------------+ +-------------+ - * | | - * +--------------+ - * - * The message module provides chained-fixed-sized-buffer storage of message content with multiple - * references. If a message is received and is to be queued for multiple destinations, there is only - * one copy of the message content in memory but multiple lightweight references to the content. - * - */ - -typedef struct { - dx_buffer_t *buffer; // Buffer that contains the first octet of the field, null if the field is not present - size_t offset; // Offset in the buffer to the first octet - size_t length; // Length of the field or zero if unneeded - size_t hdr_length; // Length of the field's header (not included in the length of the field) - int parsed; // non-zero iff the buffer chain has been parsed to find this field -} dx_field_location_t; - - -// TODO - consider using pointers to dx_field_location_t below to save memory -// TODO - we need a second buffer list for modified annotations and header -// There are three message scenarios: -// 1) Received message is held and forwarded unmodified - single buffer list -// 2) Received message is held and modified before forwarding - two buffer lists -// 3) Message is composed internally - single buffer list -// TODO - provide a way to allocate a message without a lock for the link-routing case. -// It's likely that link-routing will cause no contention for the message content. -// - -typedef struct { - sys_mutex_t *lock; - uint32_t ref_count; // The number of messages referencing this - dx_buffer_list_t buffers; // The buffer chain containing the message - dx_buffer_list_t new_delivery_annotations; // The buffer chain containing the new delivery annotations (MOVE TO MSG_PVT) - dx_field_location_t section_message_header; // The message header list - dx_field_location_t section_delivery_annotation; // The delivery annotation map - dx_field_location_t section_message_annotation; // The message annotation map - dx_field_location_t section_message_properties; // The message properties list - dx_field_location_t section_application_properties; // The application properties list - dx_field_location_t section_body; // The message body: Data - dx_field_location_t section_footer; // The footer - dx_field_location_t field_user_id; // The string value of the user-id - dx_field_location_t field_to; // The string value of the to field - dx_field_location_t field_reply_to; // The string value of the reply_to field - dx_field_location_t body; // The body of the message - dx_buffer_t *parse_buffer; - unsigned char *parse_cursor; - dx_message_depth_t parse_depth; - dx_parsed_field_t *parsed_delivery_annotations; -} dx_message_content_t; - -typedef struct { - DEQ_LINKS(dx_message_t); // Deque linkage that overlays the dx_message_t - dx_message_content_t *content; -} dx_message_pvt_t; - -ALLOC_DECLARE(dx_message_t); -ALLOC_DECLARE(dx_message_content_t); - -#define MSG_CONTENT(m) (((dx_message_pvt_t*) m)->content) - -#endif diff --git a/extras/dispatch/src/parse.c b/extras/dispatch/src/parse.c deleted file mode 100644 index c5ecc4e498..0000000000 --- a/extras/dispatch/src/parse.c +++ /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/dispatch/alloc.h> -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/parse.h> -#include <qpid/dispatch/amqp.h> - -DEQ_DECLARE(dx_parsed_field_t, dx_parsed_field_list_t); - -struct dx_parsed_field_t { - DEQ_LINKS(dx_parsed_field_t); - dx_parsed_field_t *parent; - dx_parsed_field_list_t children; - uint8_t tag; - dx_field_iterator_t *raw_iter; - const char *parse_error; -}; - -ALLOC_DECLARE(dx_parsed_field_t); -ALLOC_DEFINE(dx_parsed_field_t); - - -static char *get_type_info(dx_field_iterator_t *iter, uint8_t *tag, uint32_t *length, uint32_t *count, uint32_t *clen) -{ - if (dx_field_iterator_end(iter)) - return "Insufficient Data to Determine Tag"; - *tag = dx_field_iterator_octet(iter); - *count = 0; - *length = 0; - *clen = 0; - - switch (*tag & 0xF0) { - case 0x40: *length = 0; break; - case 0x50: *length = 1; break; - case 0x60: *length = 2; break; - case 0x70: *length = 4; break; - case 0x80: *length = 8; break; - case 0x90: *length = 16; break; - case 0xB0: - case 0xD0: - case 0xF0: - *length += ((unsigned int) dx_field_iterator_octet(iter)) << 24; - *length += ((unsigned int) dx_field_iterator_octet(iter)) << 16; - *length += ((unsigned int) dx_field_iterator_octet(iter)) << 8; - // fall through to the next case - - case 0xA0: - case 0xC0: - case 0xE0: - if (dx_field_iterator_end(iter)) - return "Insufficient Data to Determine Length"; - *length += (unsigned int) dx_field_iterator_octet(iter); - break; - - default: - return "Invalid Tag - No Length Information"; - } - - switch (*tag & 0xF0) { - case 0xD0: - case 0xF0: - *count += ((unsigned int) dx_field_iterator_octet(iter)) << 24; - *count += ((unsigned int) dx_field_iterator_octet(iter)) << 16; - *count += ((unsigned int) dx_field_iterator_octet(iter)) << 8; - *clen = 3; - // fall through to the next case - - case 0xC0: - case 0xE0: - if (dx_field_iterator_end(iter)) - return "Insufficient Data to Determine Count"; - *count += (unsigned int) dx_field_iterator_octet(iter); - *clen += 1; - break; - } - - if ((*tag == DX_AMQP_MAP8 || *tag == DX_AMQP_MAP32) && (*count & 1)) - return "Odd Number of Elements in a Map"; - - if (*clen > *length) - return "Insufficient Length to Determine Count"; - - return 0; -} - - -static dx_parsed_field_t *dx_parse_internal(dx_field_iterator_t *iter, dx_parsed_field_t *p) -{ - dx_parsed_field_t *field = new_dx_parsed_field_t(); - if (!field) - return 0; - - DEQ_ITEM_INIT(field); - DEQ_INIT(field->children); - field->parent = p; - field->raw_iter = 0; - - uint32_t length; - uint32_t count; - uint32_t length_of_count; - - field->parse_error = get_type_info(iter, &field->tag, &length, &count, &length_of_count); - - if (!field->parse_error) { - field->raw_iter = dx_field_iterator_sub(iter, length); - dx_field_iterator_advance(iter, length - length_of_count); - for (uint32_t idx = 0; idx < count; idx++) { - dx_parsed_field_t *child = dx_parse_internal(field->raw_iter, field); - DEQ_INSERT_TAIL(field->children, child); - if (!dx_parse_ok(child)) { - field->parse_error = child->parse_error; - break; - } - } - } - - return field; -} - - -dx_parsed_field_t *dx_parse(dx_field_iterator_t *iter) -{ - return dx_parse_internal(iter, 0); -} - - -void dx_parse_free(dx_parsed_field_t *field) -{ - if (!field) - return; - - assert(field->parent == 0); - if (field->raw_iter) - dx_field_iterator_free(field->raw_iter); - - dx_parsed_field_t *sub_field = DEQ_HEAD(field->children); - while (sub_field) { - dx_parsed_field_t *next = DEQ_NEXT(sub_field); - DEQ_REMOVE_HEAD(field->children); - sub_field->parent = 0; - dx_parse_free(sub_field); - sub_field = next; - } - - free_dx_parsed_field_t(field); -} - - -int dx_parse_ok(dx_parsed_field_t *field) -{ - return field->parse_error == 0; -} - - -const char *dx_parse_error(dx_parsed_field_t *field) -{ - return field->parse_error; -} - - -uint8_t dx_parse_tag(dx_parsed_field_t *field) -{ - return field->tag; -} - - -dx_field_iterator_t *dx_parse_raw(dx_parsed_field_t *field) -{ - return field->raw_iter; -} - - -uint32_t dx_parse_as_uint(dx_parsed_field_t *field) -{ - uint32_t result = 0; - - dx_field_iterator_reset(field->raw_iter); - - switch (field->tag) { - case DX_AMQP_UINT: - result |= ((uint32_t) dx_field_iterator_octet(field->raw_iter)) << 24; - result |= ((uint32_t) dx_field_iterator_octet(field->raw_iter)) << 16; - - case DX_AMQP_USHORT: - result |= ((uint32_t) dx_field_iterator_octet(field->raw_iter)) << 8; - // Fall Through... - - case DX_AMQP_UBYTE: - case DX_AMQP_SMALLUINT: - case DX_AMQP_BOOLEAN: - result |= (uint32_t) dx_field_iterator_octet(field->raw_iter); - break; - - case DX_AMQP_TRUE: - result = 1; - break; - } - - return result; -} - - -uint64_t dx_parse_as_ulong(dx_parsed_field_t *field) -{ - uint64_t result = 0; - - dx_field_iterator_reset(field->raw_iter); - - switch (field->tag) { - case DX_AMQP_ULONG: - case DX_AMQP_TIMESTAMP: - result |= ((uint64_t) dx_field_iterator_octet(field->raw_iter)) << 56; - result |= ((uint64_t) dx_field_iterator_octet(field->raw_iter)) << 48; - result |= ((uint64_t) dx_field_iterator_octet(field->raw_iter)) << 40; - result |= ((uint64_t) dx_field_iterator_octet(field->raw_iter)) << 32; - result |= ((uint64_t) dx_field_iterator_octet(field->raw_iter)) << 24; - result |= ((uint64_t) dx_field_iterator_octet(field->raw_iter)) << 16; - result |= ((uint64_t) dx_field_iterator_octet(field->raw_iter)) << 8; - // Fall Through... - - case DX_AMQP_SMALLULONG: - result |= (uint64_t) dx_field_iterator_octet(field->raw_iter); - // Fall Through... - - case DX_AMQP_ULONG0: - break; - } - - return result; -} - - -int32_t dx_parse_as_int(dx_parsed_field_t *field) -{ - int32_t result = 0; - - dx_field_iterator_reset(field->raw_iter); - - switch (field->tag) { - case DX_AMQP_INT: - result |= ((int32_t) dx_field_iterator_octet(field->raw_iter)) << 24; - result |= ((int32_t) dx_field_iterator_octet(field->raw_iter)) << 16; - - case DX_AMQP_SHORT: - result |= ((int32_t) dx_field_iterator_octet(field->raw_iter)) << 8; - // Fall Through... - - case DX_AMQP_BYTE: - case DX_AMQP_SMALLINT: - case DX_AMQP_BOOLEAN: - result |= (int32_t) dx_field_iterator_octet(field->raw_iter); - break; - - case DX_AMQP_TRUE: - result = 1; - break; - } - - return result; -} - - -int64_t dx_parse_as_long(dx_parsed_field_t *field) -{ - int64_t result = 0; - - dx_field_iterator_reset(field->raw_iter); - - switch (field->tag) { - case DX_AMQP_LONG: - result |= ((int64_t) dx_field_iterator_octet(field->raw_iter)) << 56; - result |= ((int64_t) dx_field_iterator_octet(field->raw_iter)) << 48; - result |= ((int64_t) dx_field_iterator_octet(field->raw_iter)) << 40; - result |= ((int64_t) dx_field_iterator_octet(field->raw_iter)) << 32; - result |= ((int64_t) dx_field_iterator_octet(field->raw_iter)) << 24; - result |= ((int64_t) dx_field_iterator_octet(field->raw_iter)) << 16; - result |= ((int64_t) dx_field_iterator_octet(field->raw_iter)) << 8; - // Fall Through... - - case DX_AMQP_SMALLLONG: - result |= (uint64_t) dx_field_iterator_octet(field->raw_iter); - break; - } - - return result; -} - - -uint32_t dx_parse_sub_count(dx_parsed_field_t *field) -{ - uint32_t count = DEQ_SIZE(field->children); - - if (field->tag == DX_AMQP_MAP8 || field->tag == DX_AMQP_MAP32) - count = count >> 1; - - return count; -} - - -dx_parsed_field_t *dx_parse_sub_key(dx_parsed_field_t *field, uint32_t idx) -{ - if (field->tag != DX_AMQP_MAP8 && field->tag != DX_AMQP_MAP32) - return 0; - - idx = idx << 1; - dx_parsed_field_t *key = DEQ_HEAD(field->children); - while (idx && key) { - idx--; - key = DEQ_NEXT(key); - } - - return key; -} - - -dx_parsed_field_t *dx_parse_sub_value(dx_parsed_field_t *field, uint32_t idx) -{ - if (field->tag == DX_AMQP_MAP8 || field->tag == DX_AMQP_MAP32) - idx = (idx << 1) + 1; - - dx_parsed_field_t *key = DEQ_HEAD(field->children); - while (idx && key) { - idx--; - key = DEQ_NEXT(key); - } - - return key; -} - - -int dx_parse_is_map(dx_parsed_field_t *field) -{ - return field->tag == DX_AMQP_MAP8 || field->tag == DX_AMQP_MAP32; -} - - -int dx_parse_is_list(dx_parsed_field_t *field) -{ - return field->tag == DX_AMQP_LIST8 || field->tag == DX_AMQP_LIST32; -} - - -int dx_parse_is_scalar(dx_parsed_field_t *field) -{ - return DEQ_SIZE(field->children) == 0; -} - - -dx_parsed_field_t *dx_parse_value_by_key(dx_parsed_field_t *field, const char *key) -{ - uint32_t count = dx_parse_sub_count(field); - - for (uint32_t idx = 0; idx < count; idx++) { - dx_parsed_field_t *sub = dx_parse_sub_key(field, idx); - if (!sub) - return 0; - - dx_field_iterator_t *iter = dx_parse_raw(sub); - if (!iter) - return 0; - - if (dx_field_iterator_equal(iter, (const unsigned char*) key)) { - return dx_parse_sub_value(field, idx); - } - } - - return 0; -} diff --git a/extras/dispatch/src/posix/threading.c b/extras/dispatch/src/posix/threading.c deleted file mode 100644 index 1d7760ca88..0000000000 --- a/extras/dispatch/src/posix/threading.c +++ /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/dispatch/threading.h> -#include <qpid/dispatch/ctools.h> -#include <stdio.h> -#include <pthread.h> - -struct sys_mutex_t { - pthread_mutex_t mutex; - int acquired; -}; - -sys_mutex_t *sys_mutex(void) -{ - sys_mutex_t *mutex = NEW(sys_mutex_t); - pthread_mutex_init(&(mutex->mutex), 0); - mutex->acquired = 0; - return mutex; -} - - -void sys_mutex_free(sys_mutex_t *mutex) -{ - assert(!mutex->acquired); - pthread_mutex_destroy(&(mutex->mutex)); - free(mutex); -} - - -void sys_mutex_lock(sys_mutex_t *mutex) -{ - pthread_mutex_lock(&(mutex->mutex)); - assert(!mutex->acquired); - mutex->acquired++; -} - - -void sys_mutex_unlock(sys_mutex_t *mutex) -{ - mutex->acquired--; - assert(!mutex->acquired); - pthread_mutex_unlock(&(mutex->mutex)); -} - - -struct sys_cond_t { - pthread_cond_t cond; -}; - - -sys_cond_t *sys_cond(void) -{ - sys_cond_t *cond = NEW(sys_cond_t); - pthread_cond_init(&(cond->cond), 0); - return cond; -} - - -void sys_cond_free(sys_cond_t *cond) -{ - pthread_cond_destroy(&(cond->cond)); - free(cond); -} - - -void sys_cond_wait(sys_cond_t *cond, sys_mutex_t *held_mutex) -{ - assert(held_mutex->acquired); - held_mutex->acquired--; - pthread_cond_wait(&(cond->cond), &(held_mutex->mutex)); - held_mutex->acquired++; -} - - -void sys_cond_signal(sys_cond_t *cond) -{ - pthread_cond_signal(&(cond->cond)); -} - - -void sys_cond_signal_all(sys_cond_t *cond) -{ - pthread_cond_broadcast(&(cond->cond)); -} - - -struct sys_thread_t { - pthread_t thread; -}; - -sys_thread_t *sys_thread(void *(*run_function) (void *), void *arg) -{ - sys_thread_t *thread = NEW(sys_thread_t); - pthread_create(&(thread->thread), 0, run_function, arg); - return thread; -} - - -void sys_thread_free(sys_thread_t *thread) -{ - free(thread); -} - - -void sys_thread_join(sys_thread_t *thread) -{ - pthread_join(thread->thread, 0); -} diff --git a/extras/dispatch/src/python_embedded.c b/extras/dispatch/src/python_embedded.c deleted file mode 100644 index a6e35018c6..0000000000 --- a/extras/dispatch/src/python_embedded.c +++ /dev/null @@ -1,678 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/python_embedded.h> -#include <qpid/dispatch/threading.h> -#include <qpid/dispatch/log.h> -#include <qpid/dispatch/amqp.h> -#include <qpid/dispatch/alloc.h> -#include <qpid/dispatch/router.h> - - -//=============================================================================== -// Control Functions -//=============================================================================== - -static dx_dispatch_t *dispatch = 0; -static uint32_t ref_count = 0; -static sys_mutex_t *lock = 0; -static char *log_module = "PYTHON"; -static PyObject *dispatch_module = 0; - -static void dx_python_setup(); - - -void dx_python_initialize(dx_dispatch_t *dx) -{ - dispatch = dx; - lock = sys_mutex(); -} - - -void dx_python_finalize() -{ - assert(ref_count == 0); - sys_mutex_free(lock); -} - - -void dx_python_start() -{ - sys_mutex_lock(lock); - if (ref_count == 0) { - Py_Initialize(); - dx_python_setup(); - dx_log(log_module, LOG_TRACE, "Embedded Python Interpreter Initialized"); - } - ref_count++; - sys_mutex_unlock(lock); -} - - -void dx_python_stop() -{ - sys_mutex_lock(lock); - ref_count--; - if (ref_count == 0) { - Py_DECREF(dispatch_module); - dispatch_module = 0; - Py_Finalize(); - dx_log(log_module, LOG_TRACE, "Embedded Python Interpreter Shut Down"); - } - sys_mutex_unlock(lock); -} - - -PyObject *dx_python_module() -{ - assert(dispatch_module); - return dispatch_module; -} - - -//=============================================================================== -// Data Conversion Functions -//=============================================================================== - -static PyObject *parsed_to_py_string(dx_parsed_field_t *field) -{ - switch (dx_parse_tag(field)) { - case DX_AMQP_VBIN8: - case DX_AMQP_VBIN32: - case DX_AMQP_STR8_UTF8: - case DX_AMQP_STR32_UTF8: - case DX_AMQP_SYM8: - case DX_AMQP_SYM32: - break; - default: - return Py_None; - } - -#define SHORT_BUF 1024 - uint8_t short_buf[SHORT_BUF]; - PyObject *result; - dx_field_iterator_t *raw = dx_parse_raw(field); - dx_field_iterator_reset(raw); - uint32_t length = dx_field_iterator_remaining(raw); - uint8_t *buffer = short_buf; - uint8_t *ptr; - int alloc = 0; - - if (length > SHORT_BUF) { - alloc = 1; - buffer = (uint8_t*) malloc(length); - } - - ptr = buffer; - while (!dx_field_iterator_end(raw)) - *(ptr++) = dx_field_iterator_octet(raw); - result = PyString_FromStringAndSize((char*) buffer, ptr - buffer); - if (alloc) - free(buffer); - - return result; -} - - -void dx_py_to_composed(PyObject *value, dx_composed_field_t *field) -{ - if (PyBool_Check(value)) - dx_compose_insert_bool(field, PyInt_AS_LONG(value) ? 1 : 0); - - //else if (PyFloat_Check(value)) - // dx_compose_insert_double(field, PyFloat_AS_DOUBLE(value)); - - else if (PyInt_Check(value)) - dx_compose_insert_long(field, (int64_t) PyInt_AS_LONG(value)); - - else if (PyLong_Check(value)) - dx_compose_insert_long(field, (int64_t) PyLong_AsLongLong(value)); - - else if (PyString_Check(value)) - dx_compose_insert_string(field, PyString_AS_STRING(value)); - - else if (PyDict_Check(value)) { - Py_ssize_t iter = 0; - PyObject *key; - PyObject *val; - dx_compose_start_map(field); - while (PyDict_Next(value, &iter, &key, &val)) { - dx_py_to_composed(key, field); - dx_py_to_composed(val, field); - } - dx_compose_end_map(field); - } - - else if (PyList_Check(value)) { - Py_ssize_t count = PyList_Size(value); - dx_compose_start_list(field); - for (Py_ssize_t idx = 0; idx < count; idx++) { - PyObject *item = PyList_GetItem(value, idx); - dx_py_to_composed(item, field); - } - dx_compose_end_list(field); - } - - else if (PyTuple_Check(value)) { - Py_ssize_t count = PyTuple_Size(value); - dx_compose_start_list(field); - for (Py_ssize_t idx = 0; idx < count; idx++) { - PyObject *item = PyTuple_GetItem(value, idx); - dx_py_to_composed(item, field); - } - dx_compose_end_list(field); - } -} - - -PyObject *dx_field_to_py(dx_parsed_field_t *field) -{ - PyObject *result = Py_None; - uint8_t tag = dx_parse_tag(field); - - switch (tag) { - case DX_AMQP_NULL: - result = Py_None; - break; - - case DX_AMQP_BOOLEAN: - case DX_AMQP_TRUE: - case DX_AMQP_FALSE: - result = dx_parse_as_uint(field) ? Py_True : Py_False; - break; - - case DX_AMQP_UBYTE: - case DX_AMQP_USHORT: - case DX_AMQP_UINT: - case DX_AMQP_SMALLUINT: - case DX_AMQP_UINT0: - result = PyInt_FromLong((long) dx_parse_as_uint(field)); - break; - - case DX_AMQP_ULONG: - case DX_AMQP_SMALLULONG: - case DX_AMQP_ULONG0: - case DX_AMQP_TIMESTAMP: - result = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) dx_parse_as_ulong(field)); - break; - - case DX_AMQP_BYTE: - case DX_AMQP_SHORT: - case DX_AMQP_INT: - case DX_AMQP_SMALLINT: - result = PyInt_FromLong((long) dx_parse_as_int(field)); - break; - - case DX_AMQP_LONG: - case DX_AMQP_SMALLLONG: - result = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) dx_parse_as_long(field)); - break; - - case DX_AMQP_FLOAT: - case DX_AMQP_DOUBLE: - case DX_AMQP_DECIMAL32: - case DX_AMQP_DECIMAL64: - case DX_AMQP_DECIMAL128: - case DX_AMQP_UTF32: - case DX_AMQP_UUID: - break; - - case DX_AMQP_VBIN8: - case DX_AMQP_VBIN32: - case DX_AMQP_STR8_UTF8: - case DX_AMQP_STR32_UTF8: - case DX_AMQP_SYM8: - case DX_AMQP_SYM32: - result = parsed_to_py_string(field); - break; - - case DX_AMQP_LIST0: - case DX_AMQP_LIST8: - case DX_AMQP_LIST32: { - uint32_t count = dx_parse_sub_count(field); - result = PyList_New(count); - for (uint32_t idx = 0; idx < count; idx++) { - dx_parsed_field_t *sub = dx_parse_sub_value(field, idx); - PyObject *pysub = dx_field_to_py(sub); - if (pysub == 0) - return 0; - PyList_SetItem(result, idx, pysub); - } - break; - } - case DX_AMQP_MAP8: - case DX_AMQP_MAP32: { - uint32_t count = dx_parse_sub_count(field); - result = PyDict_New(); - for (uint32_t idx = 0; idx < count; idx++) { - dx_parsed_field_t *key = dx_parse_sub_key(field, idx); - dx_parsed_field_t *val = dx_parse_sub_value(field, idx); - PyObject *pykey = parsed_to_py_string(key); - PyObject *pyval = dx_field_to_py(val); - if (pyval == 0) - return 0; - PyDict_SetItem(result, pykey, pyval); - Py_DECREF(pykey); - Py_DECREF(pyval); - } - break; - } - case DX_AMQP_ARRAY8: - case DX_AMQP_ARRAY32: - break; - } - - return result; -} - - -//=============================================================================== -// Logging Object -//=============================================================================== - -typedef struct { - PyObject_HEAD - PyObject *module_name; -} LogAdapter; - - -static int LogAdapter_init(LogAdapter *self, PyObject *args, PyObject *kwds) -{ - const char *text; - if (!PyArg_ParseTuple(args, "s", &text)) - return -1; - - self->module_name = PyString_FromString(text); - return 0; -} - - -static void LogAdapter_dealloc(LogAdapter* self) -{ - Py_XDECREF(self->module_name); - self->ob_type->tp_free((PyObject*)self); -} - - -static PyObject* dx_python_log(PyObject *self, PyObject *args) -{ - int level; - const char* text; - - if (!PyArg_ParseTuple(args, "is", &level, &text)) - return 0; - - LogAdapter *self_ptr = (LogAdapter*) self; - char *logmod = PyString_AS_STRING(self_ptr->module_name); - - dx_log(logmod, level, text); - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyMethodDef LogAdapter_methods[] = { - {"log", dx_python_log, METH_VARARGS, "Emit a Log Line"}, - {0, 0, 0, 0} -}; - -static PyMethodDef empty_methods[] = { - {0, 0, 0, 0} -}; - -static PyTypeObject LogAdapterType = { - PyObject_HEAD_INIT(0) - 0, /* ob_size*/ - "dispatch.LogAdapter", /* tp_name*/ - sizeof(LogAdapter), /* tp_basicsize*/ - 0, /* tp_itemsize*/ - (destructor)LogAdapter_dealloc, /* tp_dealloc*/ - 0, /* tp_print*/ - 0, /* tp_getattr*/ - 0, /* tp_setattr*/ - 0, /* tp_compare*/ - 0, /* tp_repr*/ - 0, /* tp_as_number*/ - 0, /* tp_as_sequence*/ - 0, /* tp_as_mapping*/ - 0, /* tp_hash */ - 0, /* tp_call*/ - 0, /* tp_str*/ - 0, /* tp_getattro*/ - 0, /* tp_setattro*/ - 0, /* tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /* tp_flags*/ - "Dispatch Log Adapter", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - LogAdapter_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)LogAdapter_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0 /* tp_version_tag */ -}; - - -//=============================================================================== -// Message IO Object -//=============================================================================== - -typedef struct { - PyObject_HEAD - PyObject *handler; - PyObject *handler_rx_call; - dx_dispatch_t *dx; - Py_ssize_t addr_count; - dx_address_t **addrs; -} IoAdapter; - - -static void dx_io_rx_handler(void *context, dx_message_t *msg, int link_id) -{ - IoAdapter *self = (IoAdapter*) context; - - // - // Parse the message through the body and exit if the message is not well formed. - // - if (!dx_message_check(msg, DX_DEPTH_BODY)) - return; - - // - // Get an iterator for the application-properties. Exit if the message has none. - // - dx_field_iterator_t *ap = dx_message_field_iterator(msg, DX_FIELD_APPLICATION_PROPERTIES); - if (ap == 0) - return; - - // - // Try to get a map-view of the application-properties. - // - dx_parsed_field_t *ap_map = dx_parse(ap); - if (ap_map == 0 || !dx_parse_ok(ap_map) || !dx_parse_is_map(ap_map)) { - dx_field_iterator_free(ap); - dx_parse_free(ap_map); - return; - } - - // - // Get an iterator for the body. Exit if the message has none. - // - dx_field_iterator_t *body = dx_message_field_iterator(msg, DX_FIELD_BODY); - if (body == 0) { - dx_field_iterator_free(ap); - dx_parse_free(ap_map); - return; - } - - // - // Try to get a map-view of the body. - // - dx_parsed_field_t *body_map = dx_parse(body); - if (body_map == 0 || !dx_parse_ok(body_map) || !dx_parse_is_map(body_map)) { - dx_field_iterator_free(ap); - dx_field_iterator_free(body); - dx_parse_free(ap_map); - dx_parse_free(body_map); - return; - } - - sys_mutex_lock(lock); - PyObject *pAP = dx_field_to_py(ap_map); - PyObject *pBody = dx_field_to_py(body_map); - - PyObject *pArgs = PyTuple_New(3); - PyTuple_SetItem(pArgs, 0, pAP); - PyTuple_SetItem(pArgs, 1, pBody); - PyTuple_SetItem(pArgs, 2, PyInt_FromLong((long) link_id)); - - PyObject *pValue = PyObject_CallObject(self->handler_rx_call, pArgs); - Py_DECREF(pArgs); - if (pValue) { - Py_DECREF(pValue); - } - sys_mutex_unlock(lock); - - dx_field_iterator_free(ap); - dx_field_iterator_free(body); - dx_parse_free(ap_map); - dx_parse_free(body_map); -} - - -static int IoAdapter_init(IoAdapter *self, PyObject *args, PyObject *kwds) -{ - PyObject *addrs; - if (!PyArg_ParseTuple(args, "OO", &self->handler, &addrs)) - return -1; - - self->handler_rx_call = PyObject_GetAttrString(self->handler, "receive"); - if (!self->handler_rx_call || !PyCallable_Check(self->handler_rx_call)) - return -1; - - if (!PyTuple_Check(addrs)) - return -1; - - Py_INCREF(self->handler); - Py_INCREF(self->handler_rx_call); - self->dx = dispatch; - self->addr_count = PyTuple_Size(addrs); - self->addrs = NEW_PTR_ARRAY(dx_address_t, self->addr_count); - for (Py_ssize_t idx = 0; idx < self->addr_count; idx++) - self->addrs[idx] = dx_router_register_address(self->dx, - PyString_AS_STRING(PyTuple_GetItem(addrs, idx)), - dx_io_rx_handler, self); - return 0; -} - - -static void IoAdapter_dealloc(IoAdapter* self) -{ - for (Py_ssize_t idx = 0; idx < self->addr_count; idx++) - dx_router_unregister_address(self->addrs[idx]); - free(self->addrs); - Py_DECREF(self->handler); - Py_DECREF(self->handler_rx_call); - self->ob_type->tp_free((PyObject*)self); -} - - -static PyObject* dx_python_send(PyObject *self, PyObject *args) -{ - IoAdapter *ioa = (IoAdapter*) self; - dx_composed_field_t *field = 0; - const char *address; - PyObject *app_properties; - PyObject *body; - - if (!PyArg_ParseTuple(args, "sOO", &address, &app_properties, &body)) - return 0; - - field = dx_compose(DX_PERFORMATIVE_DELIVERY_ANNOTATIONS, field); - dx_compose_start_map(field); - - dx_compose_insert_string(field, DX_DA_INGRESS); - dx_compose_insert_string(field, dx_router_id(ioa->dx)); - - dx_compose_insert_string(field, DX_DA_TRACE); - dx_compose_start_list(field); - dx_compose_insert_string(field, dx_router_id(ioa->dx)); - dx_compose_end_list(field); - - dx_compose_end_map(field); - - field = dx_compose(DX_PERFORMATIVE_PROPERTIES, field); - dx_compose_start_list(field); - dx_compose_insert_null(field); // message-id - dx_compose_insert_null(field); // user-id - dx_compose_insert_string(field, address); // to - dx_compose_end_list(field); - - field = dx_compose(DX_PERFORMATIVE_APPLICATION_PROPERTIES, field); - dx_py_to_composed(app_properties, field); - - field = dx_compose(DX_PERFORMATIVE_BODY_AMQP_VALUE, field); - dx_py_to_composed(body, field); - - dx_message_t *msg = dx_message(); - dx_message_compose_2(msg, field); - dx_router_send2(ioa->dx, address, msg); - dx_message_free(msg); - dx_compose_free(field); - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyMethodDef IoAdapter_methods[] = { - {"send", dx_python_send, METH_VARARGS, "Send a Message"}, - {0, 0, 0, 0} -}; - - -static PyTypeObject IoAdapterType = { - PyObject_HEAD_INIT(0) - 0, /* ob_size*/ - "dispatch.IoAdapter", /* tp_name*/ - sizeof(IoAdapter), /* tp_basicsize*/ - 0, /* tp_itemsize*/ - (destructor)IoAdapter_dealloc, /* tp_dealloc*/ - 0, /* tp_print*/ - 0, /* tp_getattr*/ - 0, /* tp_setattr*/ - 0, /* tp_compare*/ - 0, /* tp_repr*/ - 0, /* tp_as_number*/ - 0, /* tp_as_sequence*/ - 0, /* tp_as_mapping*/ - 0, /* tp_hash */ - 0, /* tp_call*/ - 0, /* tp_str*/ - 0, /* tp_getattro*/ - 0, /* tp_setattro*/ - 0, /* tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /* tp_flags*/ - "Dispatch IO Adapter", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - IoAdapter_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)IoAdapter_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0 /* tp_version_tag */ -}; - - -//=============================================================================== -// Initialization of Modules and Types -//=============================================================================== - -static void dx_register_log_constant(PyObject *module, const char *name, uint32_t value) -{ - PyObject *const_object = PyInt_FromLong((long) value); - Py_INCREF(const_object); - PyModule_AddObject(module, name, const_object); -} - - -static void dx_python_setup() -{ - LogAdapterType.tp_new = PyType_GenericNew; - IoAdapterType.tp_new = PyType_GenericNew; - if ((PyType_Ready(&LogAdapterType) < 0) || (PyType_Ready(&IoAdapterType) < 0)) { - PyErr_Print(); - dx_log(log_module, LOG_ERROR, "Unable to initialize Adapters"); - assert(0); - } else { - PyObject *m = Py_InitModule3("dispatch", empty_methods, "Dispatch Adapter Module"); - - // - // Add LogAdapter - // - PyTypeObject *laType = &LogAdapterType; - Py_INCREF(laType); - PyModule_AddObject(m, "LogAdapter", (PyObject*) &LogAdapterType); - - dx_register_log_constant(m, "LOG_TRACE", LOG_TRACE); - dx_register_log_constant(m, "LOG_DEBUG", LOG_DEBUG); - dx_register_log_constant(m, "LOG_INFO", LOG_INFO); - dx_register_log_constant(m, "LOG_NOTICE", LOG_NOTICE); - dx_register_log_constant(m, "LOG_WARNING", LOG_WARNING); - dx_register_log_constant(m, "LOG_ERROR", LOG_ERROR); - dx_register_log_constant(m, "LOG_CRITICAL", LOG_CRITICAL); - - // - PyTypeObject *ioaType = &IoAdapterType; - Py_INCREF(ioaType); - PyModule_AddObject(m, "IoAdapter", (PyObject*) &IoAdapterType); - - Py_INCREF(m); - dispatch_module = m; - } -} - -void dx_python_lock() -{ - sys_mutex_lock(lock); -} - -void dx_python_unlock() -{ - sys_mutex_unlock(lock); -} - diff --git a/extras/dispatch/src/router_agent.c b/extras/dispatch/src/router_agent.c deleted file mode 100644 index 4a70dc4ede..0000000000 --- a/extras/dispatch/src/router_agent.c +++ /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. - */ - -#include <qpid/dispatch/python_embedded.h> -#include <stdio.h> -#include <string.h> -#include <stdbool.h> -#include <stdlib.h> -#include <qpid/dispatch.h> -#include <qpid/dispatch/agent.h> -#include "dispatch_private.h" -#include "router_private.h" - -//static char *module = "router.agent"; - -#define DX_ROUTER_CLASS_ROUTER 1 -#define DX_ROUTER_CLASS_LINK 2 -#define DX_ROUTER_CLASS_NODE 3 -#define DX_ROUTER_CLASS_ADDRESS 4 - -typedef struct dx_router_class_t { - dx_router_t *router; - int class_id; -} dx_router_class_t; - - -static void dx_router_schema_handler(void *context, void *correlator) -{ -} - - -static const char *dx_router_addr_text(dx_address_t *addr) -{ - if (addr) { - const unsigned char *text = dx_hash_key_by_handle(addr->hash_handle); - if (text) - return (const char*) text; - } - return 0; -} - - -static void dx_router_query_router(dx_router_t *router, void *cor) -{ - dx_agent_value_string(cor, "area", router->router_area); - dx_agent_value_string(cor, "router_id", router->router_id); - - sys_mutex_lock(router->lock); - dx_agent_value_uint(cor, "addr_count", DEQ_SIZE(router->addrs)); - dx_agent_value_uint(cor, "link_count", DEQ_SIZE(router->links)); - dx_agent_value_uint(cor, "node_count", DEQ_SIZE(router->routers)); - sys_mutex_unlock(router->lock); - - dx_agent_value_complete(cor, 0); -} - - -static void dx_router_query_link(dx_router_t *router, void *cor) -{ - sys_mutex_lock(router->lock); - dx_router_link_t *link = DEQ_HEAD(router->links); - const char *link_type = "?"; - const char *link_dir; - - while (link) { - dx_agent_value_uint(cor, "index", link->mask_bit); - switch (link->link_type) { - case DX_LINK_ENDPOINT: link_type = "endpoint"; break; - case DX_LINK_ROUTER: link_type = "inter-router"; break; - case DX_LINK_AREA: link_type = "inter-area"; break; - } - dx_agent_value_string(cor, "link-type", link_type); - - if (link->link_direction == DX_INCOMING) - link_dir = "in"; - else - link_dir = "out"; - dx_agent_value_string(cor, "link-dir", link_dir); - - const char *text = dx_router_addr_text(link->owning_addr); - if (text) - dx_agent_value_string(cor, "owning-addr", text); - else - dx_agent_value_null(cor, "owning-addr"); - - link = DEQ_NEXT(link); - dx_agent_value_complete(cor, link != 0); - } - sys_mutex_unlock(router->lock); -} - - -static void dx_router_query_node(dx_router_t *router, void *cor) -{ - sys_mutex_lock(router->lock); - dx_router_node_t *node = DEQ_HEAD(router->routers); - while (node) { - dx_agent_value_uint(cor, "index", node->mask_bit); - dx_agent_value_string(cor, "addr", dx_router_addr_text(node->owning_addr)); - if (node->next_hop) - dx_agent_value_uint(cor, "next-hop", node->next_hop->mask_bit); - else - dx_agent_value_null(cor, "next-hop"); - if (node->peer_link) - dx_agent_value_uint(cor, "router-link", node->peer_link->mask_bit); - else - dx_agent_value_null(cor, "router-link"); - node = DEQ_NEXT(node); - dx_agent_value_complete(cor, node != 0); - } - sys_mutex_unlock(router->lock); -} - - -static void dx_router_query_address(dx_router_t *router, void *cor) -{ - sys_mutex_lock(router->lock); - dx_address_t *addr = DEQ_HEAD(router->addrs); - while (addr) { - dx_agent_value_string(cor, "addr", dx_router_addr_text(addr)); - dx_agent_value_boolean(cor, "in-process", addr->handler != 0); - dx_agent_value_uint(cor, "subscriber-count", DEQ_SIZE(addr->rlinks)); - dx_agent_value_uint(cor, "remote-count", DEQ_SIZE(addr->rnodes)); - dx_agent_value_uint(cor, "deliveries-ingress", addr->deliveries_ingress); - dx_agent_value_uint(cor, "deliveries-egress", addr->deliveries_egress); - dx_agent_value_uint(cor, "deliveries-transit", addr->deliveries_transit); - dx_agent_value_uint(cor, "deliveries-to-container", addr->deliveries_to_container); - dx_agent_value_uint(cor, "deliveries-from-container", addr->deliveries_from_container); - addr = DEQ_NEXT(addr); - dx_agent_value_complete(cor, addr != 0); - } - sys_mutex_unlock(router->lock); -} - - -static void dx_router_query_handler(void* context, const char *id, void *correlator) -{ - dx_router_class_t *cls = (dx_router_class_t*) context; - switch (cls->class_id) { - case DX_ROUTER_CLASS_ROUTER: dx_router_query_router(cls->router, correlator); break; - case DX_ROUTER_CLASS_LINK: dx_router_query_link(cls->router, correlator); break; - case DX_ROUTER_CLASS_NODE: dx_router_query_node(cls->router, correlator); break; - case DX_ROUTER_CLASS_ADDRESS: dx_router_query_address(cls->router, correlator); break; - } -} - - -static dx_agent_class_t *dx_router_setup_class(dx_router_t *router, const char *fqname, int id) -{ - dx_router_class_t *cls = NEW(dx_router_class_t); - cls->router = router; - cls->class_id = id; - - return dx_agent_register_class(router->dx, fqname, cls, - dx_router_schema_handler, - dx_router_query_handler); -} - - -void dx_router_agent_setup(dx_router_t *router) -{ - router->class_router = - dx_router_setup_class(router, "org.apache.qpid.dispatch.router", DX_ROUTER_CLASS_ROUTER); - router->class_link = - dx_router_setup_class(router, "org.apache.qpid.dispatch.router.link", DX_ROUTER_CLASS_LINK); - router->class_node = - dx_router_setup_class(router, "org.apache.qpid.dispatch.router.node", DX_ROUTER_CLASS_NODE); - router->class_address = - dx_router_setup_class(router, "org.apache.qpid.dispatch.router.address", DX_ROUTER_CLASS_ADDRESS); -} - - -void dx_router_build_node_list(dx_dispatch_t *dx, dx_composed_field_t *field) -{ - dx_router_t *router = dx->router; - char temp[1000]; // FIXME - - sys_mutex_lock(router->lock); - dx_router_node_t *rnode = DEQ_HEAD(router->routers); - while (rnode) { - strcpy(temp, "amqp:/_topo/"); - strcat(temp, router->router_area); - strcat(temp, "/"); - const unsigned char* addr = dx_hash_key_by_handle(rnode->owning_addr->hash_handle); - strcat(temp, &((char*) addr)[1]); - strcat(temp, "/$management"); - dx_compose_insert_string(field, temp); - rnode = DEQ_NEXT(rnode); - } - sys_mutex_unlock(router->lock); -} - diff --git a/extras/dispatch/src/router_node.c b/extras/dispatch/src/router_node.c deleted file mode 100644 index a810462f1b..0000000000 --- a/extras/dispatch/src/router_node.c +++ /dev/null @@ -1,1323 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/python_embedded.h> -#include <stdio.h> -#include <string.h> -#include <stdbool.h> -#include <stdlib.h> -#include <qpid/dispatch.h> -#include "dispatch_private.h" -#include "router_private.h" - -static char *module = "ROUTER"; - -static char *router_role = "inter-router"; -static char *local_prefix = "_local/"; -static char *topo_prefix = "_topo/"; -static char *direct_prefix; -static char *node_id; - -/** - * Address Types and Processing: - * - * Address Hash Key onReceive - * =================================================================== - * _local/<local> L<local> handler - * _topo/<area>/<router>/<local> A<area> forward - * _topo/<my-area>/<router>/<local> R<router> forward - * _topo/<my-area>/<my-router>/<local> L<local> handler - * _topo/<area>/all/<local> A<area> forward - * _topo/<my-area>/all/<local> L<local> forward handler - * _topo/all/all/<local> L<local> forward handler - * <mobile> M<mobile> forward handler - */ - -ALLOC_DEFINE(dx_routed_event_t); -ALLOC_DEFINE(dx_router_link_t); -ALLOC_DEFINE(dx_router_node_t); -ALLOC_DEFINE(dx_router_ref_t); -ALLOC_DEFINE(dx_router_link_ref_t); -ALLOC_DEFINE(dx_address_t); -ALLOC_DEFINE(dx_router_conn_t); - - -void dx_router_add_link_ref_LH(dx_router_link_ref_list_t *ref_list, dx_router_link_t *link) -{ - dx_router_link_ref_t *ref = new_dx_router_link_ref_t(); - DEQ_ITEM_INIT(ref); - ref->link = link; - link->ref = ref; - DEQ_INSERT_TAIL(*ref_list, ref); -} - - -void dx_router_del_link_ref_LH(dx_router_link_ref_list_t *ref_list, dx_router_link_t *link) -{ - if (link->ref) { - DEQ_REMOVE(*ref_list, link->ref); - free_dx_router_link_ref_t(link->ref); - link->ref = 0; - } -} - - -void dx_router_add_node_ref_LH(dx_router_ref_list_t *ref_list, dx_router_node_t *rnode) -{ - dx_router_ref_t *ref = new_dx_router_ref_t(); - DEQ_ITEM_INIT(ref); - ref->router = rnode; - rnode->ref_count++; - DEQ_INSERT_TAIL(*ref_list, ref); -} - - -void dx_router_del_node_ref_LH(dx_router_ref_list_t *ref_list, dx_router_node_t *rnode) -{ - dx_router_ref_t *ref = DEQ_HEAD(*ref_list); - while (ref) { - if (ref->router == rnode) { - DEQ_REMOVE(*ref_list, ref); - free_dx_router_ref_t(ref); - rnode->ref_count--; - break; - } - ref = DEQ_NEXT(ref); - } -} - - -/** - * Check an address to see if it no longer has any associated destinations. - * Depending on its policy, the address may be eligible for being closed out - * (i.e. Logging its terminal statistics and freeing its resources). - */ -void dx_router_check_addr(dx_router_t *router, dx_address_t *addr, int was_local) -{ - if (addr == 0) - return; - - unsigned char *key = 0; - int to_delete = 0; - int no_more_locals = 0; - - sys_mutex_lock(router->lock); - - // - // If the address has no handlers or destinations, it should be deleted. - // - if (addr->handler == 0 && DEQ_SIZE(addr->rlinks) == 0 && DEQ_SIZE(addr->rnodes) == 0) - to_delete = 1; - - // - // If we have just removed a local linkage and it was the last local linkage, - // we need to notify the router module that there is no longer a local - // presence of this address. - // - if (was_local && DEQ_SIZE(addr->rlinks) == 0) - no_more_locals = 1; - - if (to_delete) { - // - // Delete the address but grab the hash key so we can use it outside the - // critical section. - // - dx_hash_remove_by_handle2(router->addr_hash, addr->hash_handle, &key); - DEQ_REMOVE(router->addrs, addr); - dx_hash_handle_free(addr->hash_handle); - free_dx_address_t(addr); - } - - // - // If we're not deleting but there are no more locals, get a copy of the hash key. - // - if (!to_delete && no_more_locals) { - const unsigned char *key_const = dx_hash_key_by_handle(addr->hash_handle); - key = (unsigned char*) malloc(strlen((const char*) key_const) + 1); - strcpy((char*) key, (const char*) key_const); - } - - sys_mutex_unlock(router->lock); - - // - // If the address is mobile-class and it was just removed from a local link, - // tell the router module that it is no longer attached locally. - // - if (no_more_locals && key && key[0] == 'M') - dx_router_mobile_removed(router, (const char*) key); - - // - // Free the key that was not freed by the hash table. - // - if (key) - free(key); -} - - -/** - * Determine whether a connection is configured in the inter-router role. - */ -static int dx_router_connection_is_inter_router(const dx_connection_t *conn) -{ - if (!conn) - return 0; - - const dx_server_config_t *cf = dx_connection_config(conn); - if (cf && strcmp(cf->role, router_role) == 0) - return 1; - - return 0; -} - - -/** - * Determine whether a terminus has router capability - */ -static int dx_router_terminus_is_router(pn_terminus_t *term) -{ - pn_data_t *cap = pn_terminus_capabilities(term); - - pn_data_rewind(cap); - pn_data_next(cap); - if (cap && pn_data_type(cap) == PN_SYMBOL) { - pn_bytes_t sym = pn_data_get_symbol(cap); - if (sym.size == strlen(DX_CAPABILITY_ROUTER) && - strcmp(sym.start, DX_CAPABILITY_ROUTER) == 0) - return 1; - } - - return 0; -} - - -static void dx_router_generate_temp_addr(dx_router_t *router, char *buffer, size_t length) -{ - static const char *table = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+_"; - char discriminator[11]; - long int rnd = random(); - int idx; - - for (idx = 0; idx < 6; idx++) - discriminator[idx] = table[(rnd >> (idx * 6)) & 63]; - discriminator[idx] = '\0'; - - snprintf(buffer, length, "amqp:/%s%s/%s/temp.%s", topo_prefix, router->router_area, router->router_id, discriminator); -} - - -static int dx_router_find_mask_bit_LH(dx_router_t *router, dx_link_t *link) -{ - dx_router_conn_t *shared = (dx_router_conn_t*) dx_link_get_conn_context(link); - if (shared) - return shared->mask_bit; - - int mask_bit; - if (dx_bitmask_first_set(router->neighbor_free_mask, &mask_bit)) { - dx_bitmask_clear_bit(router->neighbor_free_mask, mask_bit); - } else { - dx_log(module, LOG_CRITICAL, "Exceeded maximum inter-router link count"); - return -1; - } - - shared = new_dx_router_conn_t(); - shared->mask_bit = mask_bit; - dx_link_set_conn_context(link, shared); - return mask_bit; -} - - -/** - * Outgoing Link Writable Handler - */ -static int router_writable_link_handler(void* context, dx_link_t *link) -{ - dx_router_t *router = (dx_router_t*) context; - dx_delivery_t *delivery; - dx_router_link_t *rlink = (dx_router_link_t*) dx_link_get_context(link); - pn_link_t *pn_link = dx_link_pn(link); - uint64_t tag; - int link_credit = pn_link_credit(pn_link); - dx_routed_event_list_t to_send; - dx_routed_event_list_t events; - dx_routed_event_t *re; - size_t offer; - int event_count = 0; - - DEQ_INIT(to_send); - DEQ_INIT(events); - - sys_mutex_lock(router->lock); - - // - // Pull the non-delivery events into a local list so they can be processed without - // the lock being held. - // - re = DEQ_HEAD(rlink->event_fifo); - while (re) { - DEQ_REMOVE_HEAD(rlink->event_fifo); - DEQ_INSERT_TAIL(events, re); - re = DEQ_HEAD(rlink->event_fifo); - } - - // - // Under lock, move available deliveries from the msg_fifo to the local to_send - // list. Don't move more than we have credit to send. - // - if (link_credit > 0) { - tag = router->dtag; - re = DEQ_HEAD(rlink->msg_fifo); - while (re) { - DEQ_REMOVE_HEAD(rlink->msg_fifo); - DEQ_INSERT_TAIL(to_send, re); - if (DEQ_SIZE(to_send) == link_credit) - break; - re = DEQ_HEAD(rlink->msg_fifo); - } - router->dtag += DEQ_SIZE(to_send); - } - - offer = DEQ_SIZE(rlink->msg_fifo); - sys_mutex_unlock(router->lock); - - // - // Deliver all the to_send messages downrange - // - re = DEQ_HEAD(to_send); - while (re) { - DEQ_REMOVE_HEAD(to_send); - - // - // Get a delivery for the send. This will be the current delivery on the link. - // - tag++; - delivery = dx_delivery(link, pn_dtag((char*) &tag, 8)); - - // - // Send the message - // - dx_message_send(re->message, link); - - // - // If there is an incoming delivery associated with this message, link it - // with the outgoing delivery. Otherwise, the message arrived pre-settled - // and should be sent presettled. - // - if (re->delivery) { - dx_delivery_set_peer(re->delivery, delivery); - dx_delivery_set_peer(delivery, re->delivery); - } else - dx_delivery_free(delivery, 0); // settle and free - - pn_link_advance(pn_link); - event_count++; - - dx_message_free(re->message); - free_dx_routed_event_t(re); - re = DEQ_HEAD(to_send); - } - - // - // Process the non-delivery events. - // - re = DEQ_HEAD(events); - while (re) { - DEQ_REMOVE_HEAD(events); - - if (re->delivery) { - if (re->disposition) { - pn_delivery_update(dx_delivery_pn(re->delivery), re->disposition); - event_count++; - } - if (re->settle) { - dx_delivery_free(re->delivery, 0); - event_count++; - } - } - - free_dx_routed_event_t(re); - re = DEQ_HEAD(events); - } - - // - // Set the offer to the number of messages remaining to be sent. - // - pn_link_offered(pn_link, offer); - return event_count; -} - - -static dx_field_iterator_t *router_annotate_message(dx_router_t *router, dx_message_t *msg, int *drop) -{ - dx_parsed_field_t *in_da = dx_message_delivery_annotations(msg); - dx_composed_field_t *out_da = dx_compose(DX_PERFORMATIVE_DELIVERY_ANNOTATIONS, 0); - dx_field_iterator_t *ingress_iter = 0; - - dx_parsed_field_t *trace = 0; - dx_parsed_field_t *ingress = 0; - - if (in_da) { - trace = dx_parse_value_by_key(in_da, DX_DA_TRACE); - ingress = dx_parse_value_by_key(in_da, DX_DA_INGRESS); - } - - dx_compose_start_map(out_da); - - // - // If there is a trace field, append this router's ID to the trace. - // - dx_compose_insert_string(out_da, DX_DA_TRACE); - dx_compose_start_list(out_da); - if (trace) { - if (dx_parse_is_list(trace)) { - uint32_t idx = 0; - dx_parsed_field_t *trace_item = dx_parse_sub_value(trace, idx); - while (trace_item) { - dx_field_iterator_t *iter = dx_parse_raw(trace_item); - if (dx_field_iterator_equal(iter, (unsigned char*) node_id)) - *drop = 1; - dx_field_iterator_reset(iter); - dx_compose_insert_string_iterator(out_da, iter); - idx++; - trace_item = dx_parse_sub_value(trace, idx); - } - } - } - - dx_compose_insert_string(out_da, node_id); - dx_compose_end_list(out_da); - - // - // If there is no ingress field, annotate the ingress as this router else - // keep the original field. - // - dx_compose_insert_string(out_da, DX_DA_INGRESS); - if (ingress && dx_parse_is_scalar(ingress)) { - ingress_iter = dx_parse_raw(ingress); - dx_compose_insert_string_iterator(out_da, ingress_iter); - } else - dx_compose_insert_string(out_da, node_id); - - dx_compose_end_map(out_da); - - dx_message_set_delivery_annotations(msg, out_da); - dx_compose_free(out_da); - - // - // Return the iterator to the ingress field _if_ it was present. - // If we added the ingress, return NULL. - // - return ingress_iter; -} - - -/** - * Inbound Delivery Handler - */ -static void router_rx_handler(void* context, dx_link_t *link, dx_delivery_t *delivery) -{ - dx_router_t *router = (dx_router_t*) context; - pn_link_t *pn_link = dx_link_pn(link); - dx_router_link_t *rlink = (dx_router_link_t*) dx_link_get_context(link); - dx_message_t *msg; - int valid_message = 0; - - // - // Receive the message into a local representation. If the returned message - // pointer is NULL, we have not yet received a complete message. - // - msg = dx_message_receive(delivery); - if (!msg) - return; - - // - // Consume the delivery and issue a replacement credit - // - pn_link_advance(pn_link); - pn_link_flow(pn_link, 1); - - sys_mutex_lock(router->lock); - - // - // Handle the Link-Routing case. If this incoming link is associated with a connected - // link, simply deliver the message to the outgoing link. There is no need to validate - // the message in this case. - // - if (rlink->connected_link) { - dx_router_link_t *clink = rlink->connected_link; - dx_routed_event_t *re = new_dx_routed_event_t(); - - DEQ_ITEM_INIT(re); - re->delivery = 0; - re->message = msg; - re->settle = false; - re->disposition = 0; - DEQ_INSERT_TAIL(clink->msg_fifo, re); - - // - // If the incoming delivery is settled (pre-settled), don't link it into the routed - // event. If it's not settled, link it into the event for later handling. - // - if (dx_delivery_settled(delivery)) - dx_delivery_free(delivery, 0); - else - re->delivery = delivery; - - sys_mutex_unlock(router->lock); - dx_link_activate(clink->link); - return; - } - - // - // We are performing Message-Routing, therefore we will need to validate the message - // through the Properties section so we can access the TO field. - // - dx_message_t *in_process_copy = 0; - dx_router_message_cb handler = 0; - void *handler_context = 0; - - valid_message = dx_message_check(msg, DX_DEPTH_PROPERTIES); - - if (valid_message) { - dx_field_iterator_t *iter = dx_message_field_iterator(msg, DX_FIELD_TO); - dx_address_t *addr; - int fanout = 0; - - if (iter) { - dx_field_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); - - // - // Note: This function is going to need to be refactored so we can put an - // asynchronous address lookup here. In the event there is a translation - // of the address (via namespace), it will have to be done here after - // obtaining the iterator and before doing the hash lookup. - // - // Note that this lookup is only done for global/mobile class addresses. - // - - dx_hash_retrieve(router->addr_hash, iter, (void*) &addr); - dx_field_iterator_reset_view(iter, ITER_VIEW_NO_HOST); - int is_local = dx_field_iterator_prefix(iter, local_prefix); - int is_direct = dx_field_iterator_prefix(iter, direct_prefix); - dx_field_iterator_free(iter); - - if (addr) { - // - // If the incoming link is an endpoint link, count this as an ingress delivery. - // - if (rlink->link_type == DX_LINK_ENDPOINT) - addr->deliveries_ingress++; - - // - // To field is valid and contains a known destination. Handle the various - // cases for forwarding. - // - - // - // Interpret and update the delivery annotations of the message. As a convenience, - // this function returns the iterator to the ingress field (if it exists). - // - int drop = 0; - dx_field_iterator_t *ingress_iter = router_annotate_message(router, msg, &drop); - - // - // Forward to the in-process handler for this message if there is one. The - // actual invocation of the handler will occur later after we've released - // the lock. - // - if (!drop && addr->handler) { - in_process_copy = dx_message_copy(msg); - handler = addr->handler; - handler_context = addr->handler_context; - addr->deliveries_to_container++; - } - - // - // If the address form is local (i.e. is prefixed by _local), don't forward - // outside of the router process. - // - if (!drop && !is_local) { - // - // Forward to all of the local links receiving this address. - // - dx_router_link_ref_t *dest_link_ref = DEQ_HEAD(addr->rlinks); - while (dest_link_ref) { - dx_routed_event_t *re = new_dx_routed_event_t(); - DEQ_ITEM_INIT(re); - re->delivery = 0; - re->message = dx_message_copy(msg); - re->settle = 0; - re->disposition = 0; - DEQ_INSERT_TAIL(dest_link_ref->link->msg_fifo, re); - - fanout++; - if (fanout == 1 && !dx_delivery_settled(delivery)) - re->delivery = delivery; - - addr->deliveries_egress++; - dx_link_activate(dest_link_ref->link->link); - dest_link_ref = DEQ_NEXT(dest_link_ref); - } - - // - // If the address form is direct to this router node, don't relay it on - // to any other part of the network. - // - if (!is_direct) { - // - // Get the mask bit associated with the ingress router for the message. - // This will be compared against the "valid_origin" masks for each - // candidate destination router. - // - int origin = -1; - if (ingress_iter) { - dx_field_iterator_reset_view(ingress_iter, ITER_VIEW_NODE_HASH); - dx_address_t *origin_addr; - dx_hash_retrieve(router->addr_hash, ingress_iter, (void*) &origin_addr); - if (origin_addr && DEQ_SIZE(origin_addr->rnodes) == 1) { - dx_router_ref_t *rref = DEQ_HEAD(origin_addr->rnodes); - origin = rref->router->mask_bit; - } - } else - origin = 0; - - // - // Forward to the next-hops for remote destinations. - // - if (origin >= 0) { - dx_router_ref_t *dest_node_ref = DEQ_HEAD(addr->rnodes); - dx_router_link_t *dest_link; - dx_bitmask_t *link_set = dx_bitmask(0); - - // - // Loop over the target nodes for this address. Build a set of outgoing links - // for which there are valid targets. We do this to avoid sending more than one - // message down a given link. It's possible that there are multiple destinations - // for this address that are all reachable over the same link. In this case, we - // will send only one copy of the message over the link and allow a downstream - // router to fan the message out. - // - while (dest_node_ref) { - if (dest_node_ref->router->next_hop) - dest_link = dest_node_ref->router->next_hop->peer_link; - else - dest_link = dest_node_ref->router->peer_link; - if (dest_link && dx_bitmask_value(dest_node_ref->router->valid_origins, origin)) - dx_bitmask_set_bit(link_set, dest_link->mask_bit); - dest_node_ref = DEQ_NEXT(dest_node_ref); - } - - // - // Send a copy of the message outbound on each identified link. - // - int link_bit; - while (dx_bitmask_first_set(link_set, &link_bit)) { - dx_bitmask_clear_bit(link_set, link_bit); - dest_link = router->out_links_by_mask_bit[link_bit]; - if (dest_link) { - dx_routed_event_t *re = new_dx_routed_event_t(); - DEQ_ITEM_INIT(re); - re->delivery = 0; - re->message = dx_message_copy(msg); - re->settle = 0; - re->disposition = 0; - DEQ_INSERT_TAIL(dest_link->msg_fifo, re); - - fanout++; - if (fanout == 1 && !dx_delivery_settled(delivery)) - re->delivery = delivery; - - addr->deliveries_transit++; - dx_link_activate(dest_link->link); - } - } - - dx_bitmask_free(link_set); - } - } - } - } - - // - // In message-routing mode, the handling of the incoming delivery depends on the - // number of copies of the received message that were forwarded. - // - if (handler) { - dx_delivery_free(delivery, PN_ACCEPTED); - } else if (fanout == 0) { - dx_delivery_free(delivery, PN_RELEASED); - } - } - } else { - // - // Message is invalid. Reject the message. - // - dx_delivery_free(delivery, PN_REJECTED); - } - - sys_mutex_unlock(router->lock); - dx_message_free(msg); - - // - // Invoke the in-process handler now that the lock is released. - // - if (handler) { - handler(handler_context, in_process_copy, rlink->mask_bit); - dx_message_free(in_process_copy); - } -} - - -/** - * Delivery Disposition Handler - */ -static void router_disp_handler(void* context, dx_link_t *link, dx_delivery_t *delivery) -{ - dx_router_t *router = (dx_router_t*) context; - bool changed = dx_delivery_disp_changed(delivery); - uint64_t disp = dx_delivery_disp(delivery); - bool settled = dx_delivery_settled(delivery); - dx_delivery_t *peer = dx_delivery_peer(delivery); - - if (peer) { - // - // The case where this delivery has a peer. - // - if (changed || settled) { - dx_link_t *peer_link = dx_delivery_link(peer); - dx_router_link_t *prl = (dx_router_link_t*) dx_link_get_context(peer_link); - dx_routed_event_t *re = new_dx_routed_event_t(); - DEQ_ITEM_INIT(re); - re->delivery = peer; - re->message = 0; - re->settle = settled; - re->disposition = changed ? disp : 0; - - sys_mutex_lock(router->lock); - DEQ_INSERT_TAIL(prl->event_fifo, re); - sys_mutex_unlock(router->lock); - - dx_link_activate(peer_link); - } - - } else { - // - // The no-peer case. Ignore status changes and echo settlement. - // - if (settled) - dx_delivery_free(delivery, 0); - } -} - - -/** - * New Incoming Link Handler - */ -static int router_incoming_link_handler(void* context, dx_link_t *link) -{ - dx_router_t *router = (dx_router_t*) context; - pn_link_t *pn_link = dx_link_pn(link); - int is_router = dx_router_terminus_is_router(dx_link_remote_source(link)); - - if (is_router && !dx_router_connection_is_inter_router(dx_link_connection(link))) { - dx_log(module, LOG_WARNING, "Incoming link claims router capability but is not on an inter-router connection"); - pn_link_close(pn_link); - return 0; - } - - dx_router_link_t *rlink = new_dx_router_link_t(); - DEQ_ITEM_INIT(rlink); - rlink->link_type = is_router ? DX_LINK_ROUTER : DX_LINK_ENDPOINT; - rlink->link_direction = DX_INCOMING; - rlink->owning_addr = 0; - rlink->link = link; - rlink->connected_link = 0; - rlink->peer_link = 0; - rlink->ref = 0; - DEQ_INIT(rlink->event_fifo); - DEQ_INIT(rlink->msg_fifo); - - dx_link_set_context(link, rlink); - - sys_mutex_lock(router->lock); - rlink->mask_bit = is_router ? dx_router_find_mask_bit_LH(router, link) : 0; - DEQ_INSERT_TAIL(router->links, rlink); - sys_mutex_unlock(router->lock); - - pn_terminus_copy(dx_link_source(link), dx_link_remote_source(link)); - pn_terminus_copy(dx_link_target(link), dx_link_remote_target(link)); - pn_link_flow(pn_link, 1000); - pn_link_open(pn_link); - - // - // TODO - If the address has link-route semantics, create all associated - // links needed to go with this one. - // - - return 0; -} - - -/** - * New Outgoing Link Handler - */ -static int router_outgoing_link_handler(void* context, dx_link_t *link) -{ - dx_router_t *router = (dx_router_t*) context; - pn_link_t *pn_link = dx_link_pn(link); - const char *r_src = pn_terminus_get_address(dx_link_remote_source(link)); - int is_dynamic = pn_terminus_is_dynamic(dx_link_remote_source(link)); - int is_router = dx_router_terminus_is_router(dx_link_remote_target(link)); - int propagate = 0; - dx_field_iterator_t *iter = 0; - - if (is_router && !dx_router_connection_is_inter_router(dx_link_connection(link))) { - dx_log(module, LOG_WARNING, "Outgoing link claims router capability but is not on an inter-router connection"); - pn_link_close(pn_link); - return 0; - } - - // - // If this link is not a router link and it has no source address, we can't - // accept it. - // - if (r_src == 0 && !is_router && !is_dynamic) { - pn_link_close(pn_link); - return 0; - } - - - // - // If this is an endpoint link with a source address, make sure the address is - // appropriate for endpoint links. If it is not mobile address, it cannot be - // bound to an endpoint link. - // - if(r_src && !is_router && !is_dynamic) { - iter = dx_field_iterator_string(r_src, ITER_VIEW_ADDRESS_HASH); - unsigned char prefix = dx_field_iterator_octet(iter); - dx_field_iterator_reset(iter); - - if (prefix != 'M') { - dx_field_iterator_free(iter); - pn_link_close(pn_link); - dx_log(module, LOG_WARNING, "Rejected an outgoing endpoint link with a router address: %s", r_src); - return 0; - } - } - - // - // Create a router_link record for this link. Some of the fields will be - // modified in the different cases below. - // - dx_router_link_t *rlink = new_dx_router_link_t(); - DEQ_ITEM_INIT(rlink); - rlink->link_type = is_router ? DX_LINK_ROUTER : DX_LINK_ENDPOINT; - rlink->link_direction = DX_OUTGOING; - rlink->owning_addr = 0; - rlink->link = link; - rlink->connected_link = 0; - rlink->peer_link = 0; - rlink->ref = 0; - DEQ_INIT(rlink->event_fifo); - DEQ_INIT(rlink->msg_fifo); - - dx_link_set_context(link, rlink); - pn_terminus_copy(dx_link_source(link), dx_link_remote_source(link)); - pn_terminus_copy(dx_link_target(link), dx_link_remote_target(link)); - - sys_mutex_lock(router->lock); - rlink->mask_bit = is_router ? dx_router_find_mask_bit_LH(router, link) : 0; - - if (is_router) { - // - // If this is a router link, put it in the hello_address link-list. - // - dx_router_add_link_ref_LH(&router->hello_addr->rlinks, rlink); - rlink->owning_addr = router->hello_addr; - router->out_links_by_mask_bit[rlink->mask_bit] = rlink; - - } else { - // - // If this is an endpoint link, check the source. If it is dynamic, we will - // assign it an ephemeral and routable address. If it has a non-dymanic - // address, that address needs to be set up in the address list. - // - char temp_addr[1000]; // FIXME - dx_address_t *addr; - - if (is_dynamic) { - dx_router_generate_temp_addr(router, temp_addr, 1000); - iter = dx_field_iterator_string(temp_addr, ITER_VIEW_ADDRESS_HASH); - pn_terminus_set_address(dx_link_source(link), temp_addr); - dx_log(module, LOG_INFO, "Assigned temporary routable address: %s", temp_addr); - } else - dx_log(module, LOG_INFO, "Registered local address: %s", r_src); - - dx_hash_retrieve(router->addr_hash, iter, (void**) &addr); - if (!addr) { - addr = new_dx_address_t(); - memset(addr, 0, sizeof(dx_address_t)); - DEQ_ITEM_INIT(addr); - DEQ_INIT(addr->rlinks); - DEQ_INIT(addr->rnodes); - dx_hash_insert(router->addr_hash, iter, addr, &addr->hash_handle); - DEQ_INSERT_TAIL(router->addrs, addr); - } - - rlink->owning_addr = addr; - dx_router_add_link_ref_LH(&addr->rlinks, rlink); - - // - // If this is not a dynamic address and it is the first local subscription - // to the address, supply the address to the router module for propagation - // to other nodes. - // - propagate = (!is_dynamic) && (DEQ_SIZE(addr->rlinks) == 1); - } - - DEQ_INSERT_TAIL(router->links, rlink); - sys_mutex_unlock(router->lock); - - if (propagate) - dx_router_mobile_added(router, iter); - - if (iter) - dx_field_iterator_free(iter); - pn_link_open(pn_link); - return 0; -} - - -/** - * Link Detached Handler - */ -static int router_link_detach_handler(void* context, dx_link_t *link, int closed) -{ - dx_router_t *router = (dx_router_t*) context; - dx_router_link_t *rlink = (dx_router_link_t*) dx_link_get_context(link); - dx_router_conn_t *shared = (dx_router_conn_t*) dx_link_get_conn_context(link); - dx_address_t *oaddr = 0; - - if (shared) { - dx_link_set_conn_context(link, 0); - free_dx_router_conn_t(shared); - } - - if (!rlink) - return 0; - - sys_mutex_lock(router->lock); - - // - // If the link is outgoing, we must disassociate it from its address. - // - if (rlink->link_direction == DX_OUTGOING && rlink->owning_addr) { - dx_router_del_link_ref_LH(&rlink->owning_addr->rlinks, rlink); - oaddr = rlink->owning_addr; - } - - // - // If this is an outgoing inter-router link, we must remove the by-mask-bit - // index reference to this link. - // - if (rlink->link_type == DX_LINK_ROUTER && rlink->link_direction == DX_OUTGOING) { - if (router->out_links_by_mask_bit[rlink->mask_bit] == rlink) - router->out_links_by_mask_bit[rlink->mask_bit] = 0; - else - dx_log(module, LOG_CRITICAL, "Outgoing router link closing but not in index: bit=%d", rlink->mask_bit); - } - - // - // If this is an incoming inter-router link, we must free the mask_bit. - // - if (rlink->link_type == DX_LINK_ROUTER && rlink->link_direction == DX_INCOMING) - dx_bitmask_set_bit(router->neighbor_free_mask, rlink->mask_bit); - - // - // Remove the link from the master list-of-links. - // - DEQ_REMOVE(router->links, rlink); - sys_mutex_unlock(router->lock); - - // - // Check to see if the owning address should be deleted - // - dx_router_check_addr(router, oaddr, 1); - - // TODO - wrap the free to handle the recursive items - free_dx_router_link_t(rlink); - - return 0; -} - - -static void router_inbound_open_handler(void *type_context, dx_connection_t *conn) -{ -} - - -static void router_outbound_open_handler(void *type_context, dx_connection_t *conn) -{ - // - // Check the configured role of this connection. If it is not the inter-router - // role, ignore it. - // - if (!dx_router_connection_is_inter_router(conn)) { - dx_log(module, LOG_WARNING, "Outbound connection set up without inter-router role"); - return; - } - - dx_router_t *router = (dx_router_t*) type_context; - dx_link_t *sender; - dx_link_t *receiver; - dx_router_link_t *rlink; - int mask_bit = 0; - size_t clen = strlen(DX_CAPABILITY_ROUTER); - - // - // Allocate a mask bit to designate the pair of links connected to the neighbor router - // - sys_mutex_lock(router->lock); - if (dx_bitmask_first_set(router->neighbor_free_mask, &mask_bit)) { - dx_bitmask_clear_bit(router->neighbor_free_mask, mask_bit); - } else { - sys_mutex_unlock(router->lock); - dx_log(module, LOG_CRITICAL, "Exceeded maximum inter-router link count"); - return; - } - - // - // Create an incoming link with router source capability - // - receiver = dx_link(router->node, conn, DX_INCOMING, DX_INTERNODE_LINK_NAME_1); - // TODO - We don't want to have to cast away the constness of the literal string here! - // See PROTON-429 - pn_data_put_symbol(pn_terminus_capabilities(dx_link_target(receiver)), pn_bytes(clen, (char*) DX_CAPABILITY_ROUTER)); - - rlink = new_dx_router_link_t(); - DEQ_ITEM_INIT(rlink); - rlink->mask_bit = mask_bit; - rlink->link_type = DX_LINK_ROUTER; - rlink->link_direction = DX_INCOMING; - rlink->owning_addr = 0; - rlink->link = receiver; - rlink->connected_link = 0; - rlink->peer_link = 0; - DEQ_INIT(rlink->event_fifo); - DEQ_INIT(rlink->msg_fifo); - - dx_link_set_context(receiver, rlink); - DEQ_INSERT_TAIL(router->links, rlink); - - // - // Create an outgoing link with router target capability - // - sender = dx_link(router->node, conn, DX_OUTGOING, DX_INTERNODE_LINK_NAME_2); - // TODO - We don't want to have to cast away the constness of the literal string here! - // See PROTON-429 - pn_data_put_symbol(pn_terminus_capabilities(dx_link_source(sender)), pn_bytes(clen, (char *) DX_CAPABILITY_ROUTER)); - - rlink = new_dx_router_link_t(); - DEQ_ITEM_INIT(rlink); - rlink->mask_bit = mask_bit; - rlink->link_type = DX_LINK_ROUTER; - rlink->link_direction = DX_OUTGOING; - rlink->owning_addr = router->hello_addr; - rlink->link = sender; - rlink->connected_link = 0; - rlink->peer_link = 0; - DEQ_INIT(rlink->event_fifo); - DEQ_INIT(rlink->msg_fifo); - - // - // Add the new outgoing link to the hello_address's list of links. - // - dx_router_add_link_ref_LH(&router->hello_addr->rlinks, rlink); - - // - // Index this link from the by-maskbit index so we can later find it quickly - // when provided with the mask bit. - // - router->out_links_by_mask_bit[mask_bit] = rlink; - - dx_link_set_context(sender, rlink); - DEQ_INSERT_TAIL(router->links, rlink); - sys_mutex_unlock(router->lock); - - pn_link_open(dx_link_pn(receiver)); - pn_link_open(dx_link_pn(sender)); - pn_link_flow(dx_link_pn(receiver), 1000); -} - - -static void dx_router_timer_handler(void *context) -{ - dx_router_t *router = (dx_router_t*) context; - - // - // Periodic processing. - // - dx_pyrouter_tick(router); - dx_timer_schedule(router->timer, 1000); -} - - -static dx_node_type_t router_node = {"router", 0, 0, - router_rx_handler, - router_disp_handler, - router_incoming_link_handler, - router_outgoing_link_handler, - router_writable_link_handler, - router_link_detach_handler, - 0, // node_created_handler - 0, // node_destroyed_handler - router_inbound_open_handler, - router_outbound_open_handler }; -static int type_registered = 0; - - -dx_router_t *dx_router(dx_dispatch_t *dx, dx_router_mode_t mode, const char *area, const char *id) -{ - if (!type_registered) { - type_registered = 1; - dx_container_register_node_type(dx, &router_node); - } - - size_t dplen = 9 + strlen(area) + strlen(id); - direct_prefix = (char*) malloc(dplen); - strcpy(direct_prefix, "_topo/"); - strcat(direct_prefix, area); - strcat(direct_prefix, "/"); - strcat(direct_prefix, id); - strcat(direct_prefix, "/"); - - node_id = (char*) malloc(dplen); - strcpy(node_id, area); - strcat(node_id, "/"); - strcat(node_id, id); - - dx_router_t *router = NEW(dx_router_t); - - router_node.type_context = router; - - dx->router = router; - router->dx = dx; - router->router_mode = mode; - router->router_area = area; - router->router_id = id; - router->node = dx_container_set_default_node_type(dx, &router_node, (void*) router, DX_DIST_BOTH); - DEQ_INIT(router->addrs); - router->addr_hash = dx_hash(10, 32, 0); - - DEQ_INIT(router->links); - DEQ_INIT(router->routers); - - router->out_links_by_mask_bit = NEW_PTR_ARRAY(dx_router_link_t, dx_bitmask_width()); - router->routers_by_mask_bit = NEW_PTR_ARRAY(dx_router_node_t, dx_bitmask_width()); - for (int idx = 0; idx < dx_bitmask_width(); idx++) { - router->out_links_by_mask_bit[idx] = 0; - router->routers_by_mask_bit[idx] = 0; - } - - router->neighbor_free_mask = dx_bitmask(1); - router->lock = sys_mutex(); - router->timer = dx_timer(dx, dx_router_timer_handler, (void*) router); - router->dtag = 1; - router->pyRouter = 0; - router->pyTick = 0; - router->pyAdded = 0; - router->pyRemoved = 0; - - // - // Create addresses for all of the routers in the topology. It will be registered - // locally later in the initialization sequence. - // - if (router->router_mode == DX_ROUTER_MODE_INTERIOR) { - router->router_addr = dx_router_register_address(dx, "qdxrouter", 0, 0); - router->hello_addr = dx_router_register_address(dx, "qdxhello", 0, 0); - } - - // - // Inform the field iterator module of this router's id and area. The field iterator - // uses this to offload some of the address-processing load from the router. - // - dx_field_iterator_set_address(area, id); - - // - // Set up the usage of the embedded python router module. - // - dx_python_start(); - - switch (router->router_mode) { - case DX_ROUTER_MODE_STANDALONE: dx_log(module, LOG_INFO, "Router started in Standalone mode"); break; - case DX_ROUTER_MODE_INTERIOR: dx_log(module, LOG_INFO, "Router started in Interior mode, area=%s id=%s", area, id); break; - case DX_ROUTER_MODE_EDGE: dx_log(module, LOG_INFO, "Router started in Edge mode"); break; - } - - return router; -} - - -void dx_router_setup_late(dx_dispatch_t *dx) -{ - dx_router_agent_setup(dx->router); - dx_router_python_setup(dx->router); - dx_timer_schedule(dx->router->timer, 1000); -} - - -void dx_router_free(dx_router_t *router) -{ - dx_container_set_default_node_type(router->dx, 0, 0, DX_DIST_BOTH); - sys_mutex_free(router->lock); - free(router); - dx_python_stop(); -} - - -const char *dx_router_id(const dx_dispatch_t *dx) -{ - return node_id; -} - - -dx_address_t *dx_router_register_address(dx_dispatch_t *dx, - const char *address, - dx_router_message_cb handler, - void *context) -{ - char addr_string[1000]; - dx_router_t *router = dx->router; - dx_address_t *addr; - dx_field_iterator_t *iter; - - strcpy(addr_string, "L"); // Local Hash-Key Space - strcat(addr_string, address); - iter = dx_field_iterator_string(addr_string, ITER_VIEW_NO_HOST); - - sys_mutex_lock(router->lock); - dx_hash_retrieve(router->addr_hash, iter, (void**) &addr); - if (!addr) { - addr = new_dx_address_t(); - memset(addr, 0, sizeof(dx_address_t)); - DEQ_ITEM_INIT(addr); - DEQ_INIT(addr->rlinks); - DEQ_INIT(addr->rnodes); - dx_hash_insert(router->addr_hash, iter, addr, &addr->hash_handle); - DEQ_ITEM_INIT(addr); - DEQ_INSERT_TAIL(router->addrs, addr); - } - dx_field_iterator_free(iter); - - addr->handler = handler; - addr->handler_context = context; - - sys_mutex_unlock(router->lock); - - if (handler) - dx_log(module, LOG_INFO, "In-Process Address Registered: %s", address); - return addr; -} - - -void dx_router_unregister_address(dx_address_t *ad) -{ - //free_dx_address_t(ad); -} - - -void dx_router_send(dx_dispatch_t *dx, - dx_field_iterator_t *address, - dx_message_t *msg) -{ - dx_router_t *router = dx->router; - dx_address_t *addr; - - dx_field_iterator_reset_view(address, ITER_VIEW_ADDRESS_HASH); - sys_mutex_lock(router->lock); - dx_hash_retrieve(router->addr_hash, address, (void*) &addr); - if (addr) { - // - // Forward to all of the local links receiving this address. - // - addr->deliveries_from_container++; - dx_router_link_ref_t *dest_link_ref = DEQ_HEAD(addr->rlinks); - while (dest_link_ref) { - dx_routed_event_t *re = new_dx_routed_event_t(); - DEQ_ITEM_INIT(re); - re->delivery = 0; - re->message = dx_message_copy(msg); - re->settle = 0; - re->disposition = 0; - DEQ_INSERT_TAIL(dest_link_ref->link->msg_fifo, re); - - dx_link_activate(dest_link_ref->link->link); - addr->deliveries_egress++; - - dest_link_ref = DEQ_NEXT(dest_link_ref); - } - - // - // Forward to the next-hops for remote destinations. - // - dx_router_ref_t *dest_node_ref = DEQ_HEAD(addr->rnodes); - dx_router_link_t *dest_link; - dx_bitmask_t *link_set = dx_bitmask(0); - - while (dest_node_ref) { - if (dest_node_ref->router->next_hop) - dest_link = dest_node_ref->router->next_hop->peer_link; - else - dest_link = dest_node_ref->router->peer_link; - if (dest_link) - dx_bitmask_set_bit(link_set, dest_link->mask_bit); - dest_node_ref = DEQ_NEXT(dest_node_ref); - } - - int link_bit; - while (dx_bitmask_first_set(link_set, &link_bit)) { - dx_bitmask_clear_bit(link_set, link_bit); - dest_link = router->out_links_by_mask_bit[link_bit]; - if (dest_link) { - dx_routed_event_t *re = new_dx_routed_event_t(); - DEQ_ITEM_INIT(re); - re->delivery = 0; - re->message = dx_message_copy(msg); - re->settle = 0; - re->disposition = 0; - DEQ_INSERT_TAIL(dest_link->msg_fifo, re); - dx_link_activate(dest_link->link); - addr->deliveries_transit++; - } - } - - dx_bitmask_free(link_set); - } - sys_mutex_unlock(router->lock); // TOINVESTIGATE Move this higher? -} - - -void dx_router_send2(dx_dispatch_t *dx, - const char *address, - dx_message_t *msg) -{ - dx_field_iterator_t *iter = dx_field_iterator_string(address, ITER_VIEW_ADDRESS_HASH); - dx_router_send(dx, iter, msg); - dx_field_iterator_free(iter); -} - diff --git a/extras/dispatch/src/router_private.h b/extras/dispatch/src/router_private.h deleted file mode 100644 index 066188b3f7..0000000000 --- a/extras/dispatch/src/router_private.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef __router_private_h__ -#define __router_private_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -typedef struct dx_router_link_t dx_router_link_t; -typedef struct dx_router_node_t dx_router_node_t; -typedef struct dx_router_ref_t dx_router_ref_t; -typedef struct dx_router_link_ref_t dx_router_link_ref_t; -typedef struct dx_router_conn_t dx_router_conn_t; - -void dx_router_python_setup(dx_router_t *router); -void dx_pyrouter_tick(dx_router_t *router); -void dx_router_agent_setup(dx_router_t *router); - -typedef enum { - DX_ROUTER_MODE_STANDALONE, // Standalone router. No routing protocol participation - DX_ROUTER_MODE_INTERIOR, // Interior router. Full participation in routing protocol. - DX_ROUTER_MODE_EDGE // Edge router. No routing protocol participation, access via other protocols. -} dx_router_mode_t; - -typedef enum { - DX_LINK_ENDPOINT, // A link to a connected endpoint - DX_LINK_ROUTER, // A link to a peer router in the same area - DX_LINK_AREA // A link to a peer router in a different area (area boundary) -} dx_link_type_t; - - -typedef struct dx_routed_event_t { - DEQ_LINKS(struct dx_routed_event_t); - dx_delivery_t *delivery; - dx_message_t *message; - bool settle; - uint64_t disposition; -} dx_routed_event_t; - -ALLOC_DECLARE(dx_routed_event_t); -DEQ_DECLARE(dx_routed_event_t, dx_routed_event_list_t); - - -struct dx_router_link_t { - DEQ_LINKS(dx_router_link_t); - int mask_bit; // Unique mask bit if this is an inter-router link - dx_link_type_t link_type; - dx_direction_t link_direction; - dx_address_t *owning_addr; // [ref] Address record that owns this link - dx_link_t *link; // [own] Link pointer - dx_router_link_t *connected_link; // [ref] If this is a link-route, reference the connected link - dx_router_link_t *peer_link; // [ref] If this is a bidirectional link-route, reference the peer link - dx_router_link_ref_t *ref; // Pointer to a containing reference object - dx_routed_event_list_t event_fifo; // FIFO of outgoing delivery/link events (no messages) - dx_routed_event_list_t msg_fifo; // FIFO of outgoing message deliveries -}; - -ALLOC_DECLARE(dx_router_link_t); -DEQ_DECLARE(dx_router_link_t, dx_router_link_list_t); - -struct dx_router_node_t { - DEQ_LINKS(dx_router_node_t); - dx_address_t *owning_addr; - int mask_bit; - dx_router_node_t *next_hop; // Next hop node _if_ this is not a neighbor node - dx_router_link_t *peer_link; // Outgoing link _if_ this is a neighbor node - uint32_t ref_count; - dx_bitmask_t *valid_origins; -}; - -ALLOC_DECLARE(dx_router_node_t); -DEQ_DECLARE(dx_router_node_t, dx_router_node_list_t); - -struct dx_router_ref_t { - DEQ_LINKS(dx_router_ref_t); - dx_router_node_t *router; -}; - -ALLOC_DECLARE(dx_router_ref_t); -DEQ_DECLARE(dx_router_ref_t, dx_router_ref_list_t); - - -struct dx_router_link_ref_t { - DEQ_LINKS(dx_router_link_ref_t); - dx_router_link_t *link; -}; - -ALLOC_DECLARE(dx_router_link_ref_t); -DEQ_DECLARE(dx_router_link_ref_t, dx_router_link_ref_list_t); - - -struct dx_router_conn_t { - int mask_bit; -}; - -ALLOC_DECLARE(dx_router_conn_t); - - -struct dx_address_t { - DEQ_LINKS(dx_address_t); - dx_router_message_cb handler; // In-Process Consumer - void *handler_context; // In-Process Consumer context - dx_router_link_ref_list_t rlinks; // Locally-Connected Consumers - dx_router_ref_list_t rnodes; // Remotely-Connected Consumers - dx_hash_handle_t *hash_handle; // Linkage back to the hash table entry - - uint64_t deliveries_ingress; - uint64_t deliveries_egress; - uint64_t deliveries_transit; - uint64_t deliveries_to_container; - uint64_t deliveries_from_container; -}; - -ALLOC_DECLARE(dx_address_t); -DEQ_DECLARE(dx_address_t, dx_address_list_t); - - -struct dx_router_t { - dx_dispatch_t *dx; - dx_router_mode_t router_mode; - const char *router_area; - const char *router_id; - dx_node_t *node; - - dx_address_list_t addrs; - dx_hash_t *addr_hash; - dx_address_t *router_addr; - dx_address_t *hello_addr; - - dx_router_link_list_t links; - dx_router_node_list_t routers; - dx_router_link_t **out_links_by_mask_bit; - dx_router_node_t **routers_by_mask_bit; - - dx_bitmask_t *neighbor_free_mask; - sys_mutex_t *lock; - dx_timer_t *timer; - uint64_t dtag; - - PyObject *pyRouter; - PyObject *pyTick; - PyObject *pyAdded; - PyObject *pyRemoved; - - dx_agent_class_t *class_router; - dx_agent_class_t *class_link; - dx_agent_class_t *class_node; - dx_agent_class_t *class_address; -}; - - - -void dx_router_check_addr(dx_router_t *router, dx_address_t *addr, int was_local); -void dx_router_add_link_ref_LH(dx_router_link_ref_list_t *ref_list, dx_router_link_t *link); -void dx_router_del_link_ref_LH(dx_router_link_ref_list_t *ref_list, dx_router_link_t *link); - -void dx_router_add_node_ref_LH(dx_router_ref_list_t *ref_list, dx_router_node_t *rnode); -void dx_router_del_node_ref_LH(dx_router_ref_list_t *ref_list, dx_router_node_t *rnode); - -void dx_router_mobile_added(dx_router_t *router, dx_field_iterator_t *iter); -void dx_router_mobile_removed(dx_router_t *router, const char *addr); - - -#endif diff --git a/extras/dispatch/src/router_pynode.c b/extras/dispatch/src/router_pynode.c deleted file mode 100644 index 82b08c0785..0000000000 --- a/extras/dispatch/src/router_pynode.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/python_embedded.h> -#include <stdio.h> -#include <string.h> -#include <stdbool.h> -#include <stdlib.h> -#include <qpid/dispatch.h> -#include "dispatch_private.h" -#include "router_private.h" - -static char *module = "router.pynode"; - -typedef struct { - PyObject_HEAD - dx_router_t *router; -} RouterAdapter; - - -static char *dx_add_router(dx_router_t *router, const char *address, int router_maskbit, int link_maskbit) -{ - if (router_maskbit >= dx_bitmask_width() || router_maskbit < 0) - return "Router bit mask out of range"; - - if (link_maskbit >= dx_bitmask_width() || link_maskbit < -1) - return "Link bit mask out of range"; - - sys_mutex_lock(router->lock); - if (router->routers_by_mask_bit[router_maskbit] != 0) { - sys_mutex_unlock(router->lock); - return "Adding router over already existing router"; - } - - if (link_maskbit >= 0 && router->out_links_by_mask_bit[link_maskbit] == 0) { - sys_mutex_unlock(router->lock); - return "Adding neighbor router with invalid link reference"; - } - - // - // Hash lookup the address to ensure there isn't an existing router address. - // - dx_field_iterator_t *iter = dx_field_iterator_string(address, ITER_VIEW_ADDRESS_HASH); - dx_address_t *addr; - - dx_hash_retrieve(router->addr_hash, iter, (void**) &addr); - assert(addr == 0); - - // - // Create an address record for this router and insert it in the hash table. - // This record will be found whenever a "foreign" topological address to this - // remote router is looked up. - // - addr = new_dx_address_t(); - memset(addr, 0, sizeof(dx_address_t)); - DEQ_ITEM_INIT(addr); - DEQ_INIT(addr->rlinks); - DEQ_INIT(addr->rnodes); - dx_hash_insert(router->addr_hash, iter, addr, &addr->hash_handle); - DEQ_INSERT_TAIL(router->addrs, addr); - dx_field_iterator_free(iter); - - // - // Create a router-node record to represent the remote router. - // - dx_router_node_t *rnode = new_dx_router_node_t(); - DEQ_ITEM_INIT(rnode); - rnode->owning_addr = addr; - rnode->mask_bit = router_maskbit; - rnode->next_hop = 0; - rnode->peer_link = 0; - rnode->ref_count = 0; - rnode->valid_origins = dx_bitmask(0); - - DEQ_INSERT_TAIL(router->routers, rnode); - - // - // Link the router record to the address record. - // - dx_router_add_node_ref_LH(&addr->rnodes, rnode); - - // - // Link the router record to the router address record. - // - dx_router_add_node_ref_LH(&router->router_addr->rnodes, rnode); - - // - // Add the router record to the mask-bit index. - // - router->routers_by_mask_bit[router_maskbit] = rnode; - - // - // If this is a neighbor router, add the peer_link reference to the - // router record. - // - if (link_maskbit >= 0) - rnode->peer_link = router->out_links_by_mask_bit[link_maskbit]; - - sys_mutex_unlock(router->lock); - return 0; -} - - -static char *dx_del_router(dx_router_t *router, int router_maskbit) -{ - if (router_maskbit >= dx_bitmask_width() || router_maskbit < 0) - return "Router bit mask out of range"; - - sys_mutex_lock(router->lock); - if (router->routers_by_mask_bit[router_maskbit] == 0) { - sys_mutex_unlock(router->lock); - return "Deleting nonexistent router"; - } - - dx_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; - dx_address_t *oaddr = rnode->owning_addr; - assert(oaddr); - - // - // Unlink the router node from the address record - // - dx_router_del_node_ref_LH(&oaddr->rnodes, rnode); - - // - // While the router node has a non-zero reference count, look for addresses - // to unlink the node from. - // - dx_address_t *addr = DEQ_HEAD(router->addrs); - while (addr && rnode->ref_count > 0) { - dx_router_del_node_ref_LH(&addr->rnodes, rnode); - addr = DEQ_NEXT(addr); - } - assert(rnode->ref_count == 0); - - // - // Free the router node and the owning address records. - // - dx_bitmask_free(rnode->valid_origins); - DEQ_REMOVE(router->routers, rnode); - free_dx_router_node_t(rnode); - - dx_hash_remove_by_handle(router->addr_hash, oaddr->hash_handle); - DEQ_REMOVE(router->addrs, oaddr); - dx_hash_handle_free(oaddr->hash_handle); - router->routers_by_mask_bit[router_maskbit] = 0; - free_dx_address_t(oaddr); - - sys_mutex_unlock(router->lock); - return 0; -} - - -static PyObject* dx_add_remote_router(PyObject *self, PyObject *args) -{ - RouterAdapter *adapter = (RouterAdapter*) self; - dx_router_t *router = adapter->router; - const char *address; - int router_maskbit; - - if (!PyArg_ParseTuple(args, "si", &address, &router_maskbit)) - return 0; - - char *error = dx_add_router(router, address, router_maskbit, -1); - if (error) { - PyErr_SetString(PyExc_Exception, error); - return 0; - } - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject* dx_del_remote_router(PyObject *self, PyObject *args) -{ - RouterAdapter *adapter = (RouterAdapter*) self; - dx_router_t *router = adapter->router; - int router_maskbit; - - if (!PyArg_ParseTuple(args, "i", &router_maskbit)) - return 0; - - char *error = dx_del_router(router, router_maskbit); - if (error) { - PyErr_SetString(PyExc_Exception, error); - return 0; - } - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject* dx_set_next_hop(PyObject *self, PyObject *args) -{ - RouterAdapter *adapter = (RouterAdapter*) self; - dx_router_t *router = adapter->router; - int router_maskbit; - int next_hop_maskbit; - - if (!PyArg_ParseTuple(args, "ii", &router_maskbit, &next_hop_maskbit)) - return 0; - - if (router_maskbit >= dx_bitmask_width() || router_maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Router bit mask out of range"); - return 0; - } - - if (next_hop_maskbit >= dx_bitmask_width() || next_hop_maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Next Hop bit mask out of range"); - return 0; - } - - if (router->routers_by_mask_bit[router_maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Router Not Found"); - return 0; - } - - if (router->routers_by_mask_bit[next_hop_maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Next Hop Not Found"); - return 0; - } - - if (router_maskbit != next_hop_maskbit) { - dx_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; - rnode->next_hop = router->routers_by_mask_bit[next_hop_maskbit]; - } - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject* dx_set_valid_origins(PyObject *self, PyObject *args) -{ - RouterAdapter *adapter = (RouterAdapter*) self; - dx_router_t *router = adapter->router; - int router_maskbit; - PyObject *origin_list; - Py_ssize_t idx; - - if (!PyArg_ParseTuple(args, "iO", &router_maskbit, &origin_list)) - return 0; - - if (router_maskbit >= dx_bitmask_width() || router_maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Router bit mask out of range"); - return 0; - } - - if (router->routers_by_mask_bit[router_maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Router Not Found"); - return 0; - } - - if (!PyList_Check(origin_list)) { - PyErr_SetString(PyExc_Exception, "Expected List as argument 2"); - return 0; - } - - Py_ssize_t origin_count = PyList_Size(origin_list); - dx_router_node_t *rnode = router->routers_by_mask_bit[router_maskbit]; - int maskbit; - - for (idx = 0; idx < origin_count; idx++) { - maskbit = PyInt_AS_LONG(PyList_GetItem(origin_list, idx)); - - if (maskbit >= dx_bitmask_width() || maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Origin bit mask out of range"); - return 0; - } - - if (router->routers_by_mask_bit[maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Origin router Not Found"); - return 0; - } - } - - dx_bitmask_clear_all(rnode->valid_origins); - dx_bitmask_set_bit(rnode->valid_origins, 0); // This router is a valid origin for all destinations - for (idx = 0; idx < origin_count; idx++) { - maskbit = PyInt_AS_LONG(PyList_GetItem(origin_list, idx)); - dx_bitmask_set_bit(rnode->valid_origins, maskbit); - } - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject* dx_add_neighbor_router(PyObject *self, PyObject *args) -{ - RouterAdapter *adapter = (RouterAdapter*) self; - dx_router_t *router = adapter->router; - const char *address; - int router_maskbit; - int link_maskbit; - - if (!PyArg_ParseTuple(args, "sii", &address, &router_maskbit, &link_maskbit)) - return 0; - - char *error = dx_add_router(router, address, router_maskbit, link_maskbit); - if (error) { - PyErr_SetString(PyExc_Exception, error); - return 0; - } - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject* dx_del_neighbor_router(PyObject *self, PyObject *args) -{ - RouterAdapter *adapter = (RouterAdapter*) self; - dx_router_t *router = adapter->router; - int router_maskbit; - - if (!PyArg_ParseTuple(args, "i", &router_maskbit)) - return 0; - - char *error = dx_del_router(router, router_maskbit); - if (error) { - PyErr_SetString(PyExc_Exception, error); - return 0; - } - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject* dx_map_destination(PyObject *self, PyObject *args) -{ - RouterAdapter *adapter = (RouterAdapter*) self; - dx_router_t *router = adapter->router; - const char *addr_string; - int maskbit; - dx_address_t *addr; - dx_field_iterator_t *iter; - - if (!PyArg_ParseTuple(args, "si", &addr_string, &maskbit)) - return 0; - - if (maskbit >= dx_bitmask_width() || maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Router bit mask out of range"); - return 0; - } - - if (router->routers_by_mask_bit[maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Router Not Found"); - return 0; - } - - iter = dx_field_iterator_string(addr_string, ITER_VIEW_ADDRESS_HASH); - - sys_mutex_lock(router->lock); - dx_hash_retrieve(router->addr_hash, iter, (void**) &addr); - if (!addr) { - addr = new_dx_address_t(); - memset(addr, 0, sizeof(dx_address_t)); - DEQ_ITEM_INIT(addr); - DEQ_INIT(addr->rlinks); - DEQ_INIT(addr->rnodes); - dx_hash_insert(router->addr_hash, iter, addr, &addr->hash_handle); - DEQ_ITEM_INIT(addr); - DEQ_INSERT_TAIL(router->addrs, addr); - } - dx_field_iterator_free(iter); - - dx_router_node_t *rnode = router->routers_by_mask_bit[maskbit]; - dx_router_add_node_ref_LH(&addr->rnodes, rnode); - - sys_mutex_unlock(router->lock); - - dx_log(module, LOG_DEBUG, "Remote Destination '%s' Mapped to router %d", addr_string, maskbit); - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject* dx_unmap_destination(PyObject *self, PyObject *args) -{ - RouterAdapter *adapter = (RouterAdapter*) self; - dx_router_t *router = adapter->router; - const char *addr_string; - int maskbit; - dx_address_t *addr; - - if (!PyArg_ParseTuple(args, "si", &addr_string, &maskbit)) - return 0; - - if (maskbit >= dx_bitmask_width() || maskbit < 0) { - PyErr_SetString(PyExc_Exception, "Router bit mask out of range"); - return 0; - } - - if (router->routers_by_mask_bit[maskbit] == 0) { - PyErr_SetString(PyExc_Exception, "Router Not Found"); - return 0; - } - - dx_router_node_t *rnode = router->routers_by_mask_bit[maskbit]; - dx_field_iterator_t *iter = dx_field_iterator_string(addr_string, ITER_VIEW_ADDRESS_HASH); - - sys_mutex_lock(router->lock); - dx_hash_retrieve(router->addr_hash, iter, (void**) &addr); - dx_field_iterator_free(iter); - - if (!addr) { - PyErr_SetString(PyExc_Exception, "Address Not Found"); - sys_mutex_unlock(router->lock); - return 0; - } - - dx_router_del_node_ref_LH(&addr->rnodes, rnode); - sys_mutex_unlock(router->lock); - - dx_router_check_addr(router, addr, 0); - - dx_log(module, LOG_DEBUG, "Remote Destination '%s' Unmapped from router %d", addr_string, maskbit); - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyMethodDef RouterAdapter_methods[] = { - {"add_remote_router", dx_add_remote_router, METH_VARARGS, "A new remote/reachable router has been discovered"}, - {"del_remote_router", dx_del_remote_router, METH_VARARGS, "We've lost reachability to a remote router"}, - {"set_next_hop", dx_set_next_hop, METH_VARARGS, "Set the next hop for a remote router"}, - {"set_valid_origins", dx_set_valid_origins, METH_VARARGS, "Set the valid origins for a remote router"}, - {"add_neighbor_router", dx_add_neighbor_router, METH_VARARGS, "A new neighbor router has been discovered"}, - {"del_neighbor_router", dx_del_neighbor_router, METH_VARARGS, "We've lost reachability to a neighbor router"}, - {"map_destination", dx_map_destination, METH_VARARGS, "Add a newly discovered destination mapping"}, - {"unmap_destination", dx_unmap_destination, METH_VARARGS, "Delete a destination mapping"}, - {0, 0, 0, 0} -}; - -static PyTypeObject RouterAdapterType = { - PyObject_HEAD_INIT(0) - 0, /* ob_size*/ - "dispatch.RouterAdapter", /* tp_name*/ - sizeof(RouterAdapter), /* tp_basicsize*/ - 0, /* tp_itemsize*/ - 0, /* tp_dealloc*/ - 0, /* tp_print*/ - 0, /* tp_getattr*/ - 0, /* tp_setattr*/ - 0, /* tp_compare*/ - 0, /* tp_repr*/ - 0, /* tp_as_number*/ - 0, /* tp_as_sequence*/ - 0, /* tp_as_mapping*/ - 0, /* tp_hash */ - 0, /* tp_call*/ - 0, /* tp_str*/ - 0, /* tp_getattro*/ - 0, /* tp_setattro*/ - 0, /* tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /* tp_flags*/ - "Dispatch Router Adapter", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - RouterAdapter_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0 /* tp_version_tag */ -}; - - -void dx_router_python_setup(dx_router_t *router) -{ - // - // If we are not operating as an interior router, don't start the - // router module. - // - if (router->router_mode != DX_ROUTER_MODE_INTERIOR) - return; - - PyObject *pDispatchModule = dx_python_module(); - - RouterAdapterType.tp_new = PyType_GenericNew; - if (PyType_Ready(&RouterAdapterType) < 0) { - PyErr_Print(); - dx_log(module, LOG_CRITICAL, "Unable to initialize the Python Router Adapter"); - return; - } - - PyTypeObject *raType = &RouterAdapterType; - Py_INCREF(raType); - PyModule_AddObject(pDispatchModule, "RouterAdapter", (PyObject*) &RouterAdapterType); - - // - // Attempt to import the Python Router module - // - PyObject* pName; - PyObject* pId; - PyObject* pArea; - PyObject* pMaxRouters; - PyObject* pModule; - PyObject* pClass; - PyObject* pArgs; - - pName = PyString_FromString("qpid.dispatch.router"); - pModule = PyImport_Import(pName); - Py_DECREF(pName); - if (!pModule) { - dx_log(module, LOG_CRITICAL, "Can't Locate 'router' Python module"); - return; - } - - pClass = PyObject_GetAttrString(pModule, "RouterEngine"); - if (!pClass || !PyClass_Check(pClass)) { - dx_log(module, LOG_CRITICAL, "Can't Locate 'RouterEngine' class in the 'router' module"); - return; - } - - PyObject *adapterType = PyObject_GetAttrString(pDispatchModule, "RouterAdapter"); - PyObject *adapterInstance = PyObject_CallObject(adapterType, 0); - assert(adapterInstance); - - ((RouterAdapter*) adapterInstance)->router = router; - - // - // Constructor Arguments for RouterEngine - // - pArgs = PyTuple_New(4); - - // arg 0: adapter instance - PyTuple_SetItem(pArgs, 0, adapterInstance); - - // arg 1: router_id - pId = PyString_FromString(router->router_id); - PyTuple_SetItem(pArgs, 1, pId); - - // arg 2: area_id - pArea = PyString_FromString(router->router_area); - PyTuple_SetItem(pArgs, 2, pArea); - - // arg 3: max_routers - pMaxRouters = PyInt_FromLong((long) dx_bitmask_width()); - PyTuple_SetItem(pArgs, 3, pMaxRouters); - - // - // Instantiate the router - // - router->pyRouter = PyInstance_New(pClass, pArgs, 0); - Py_DECREF(pArgs); - Py_DECREF(adapterType); - - if (!router->pyRouter) { - PyErr_Print(); - dx_log(module, LOG_CRITICAL, "'RouterEngine' class cannot be instantiated"); - return; - } - - router->pyTick = PyObject_GetAttrString(router->pyRouter, "handleTimerTick"); - if (!router->pyTick || !PyCallable_Check(router->pyTick)) { - dx_log(module, LOG_CRITICAL, "'RouterEngine' class has no handleTimerTick method"); - return; - } - - router->pyAdded = PyObject_GetAttrString(router->pyRouter, "addressAdded"); - if (!router->pyAdded || !PyCallable_Check(router->pyAdded)) { - dx_log(module, LOG_CRITICAL, "'RouterEngine' class has no addressAdded method"); - return; - } - - router->pyRemoved = PyObject_GetAttrString(router->pyRouter, "addressRemoved"); - if (!router->pyRemoved || !PyCallable_Check(router->pyRemoved)) { - dx_log(module, LOG_CRITICAL, "'RouterEngine' class has no addressRemoved method"); - return; - } -} - - -void dx_pyrouter_tick(dx_router_t *router) -{ - PyObject *pArgs; - PyObject *pValue; - - if (router->pyTick && router->router_mode == DX_ROUTER_MODE_INTERIOR) { - dx_python_lock(); - pArgs = PyTuple_New(0); - pValue = PyObject_CallObject(router->pyTick, pArgs); - if (PyErr_Occurred()) { - PyErr_Print(); - } - Py_DECREF(pArgs); - if (pValue) { - Py_DECREF(pValue); - } - dx_python_unlock(); - } -} - - -void dx_router_mobile_added(dx_router_t *router, dx_field_iterator_t *iter) -{ - PyObject *pArgs; - PyObject *pValue; - - if (router->pyAdded && router->router_mode == DX_ROUTER_MODE_INTERIOR) { - dx_field_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); - char *address = (char*) dx_field_iterator_copy(iter); - - dx_python_lock(); - pArgs = PyTuple_New(1); - PyTuple_SetItem(pArgs, 0, PyString_FromString(address)); - pValue = PyObject_CallObject(router->pyAdded, pArgs); - if (PyErr_Occurred()) { - PyErr_Print(); - } - Py_DECREF(pArgs); - if (pValue) { - Py_DECREF(pValue); - } - dx_python_unlock(); - - free(address); - } -} - - -void dx_router_mobile_removed(dx_router_t *router, const char *address) -{ - PyObject *pArgs; - PyObject *pValue; - - if (router->pyRemoved && router->router_mode == DX_ROUTER_MODE_INTERIOR) { - dx_python_lock(); - pArgs = PyTuple_New(1); - PyTuple_SetItem(pArgs, 0, PyString_FromString(address)); - pValue = PyObject_CallObject(router->pyRemoved, pArgs); - if (PyErr_Occurred()) { - PyErr_Print(); - } - Py_DECREF(pArgs); - if (pValue) { - Py_DECREF(pValue); - } - dx_python_unlock(); - } -} - diff --git a/extras/dispatch/src/server.c b/extras/dispatch/src/server.c deleted file mode 100644 index 65e181bd2c..0000000000 --- a/extras/dispatch/src/server.c +++ /dev/null @@ -1,1039 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/threading.h> -#include <qpid/dispatch/log.h> -#include "server_private.h" -#include "timer_private.h" -#include "alloc_private.h" -#include "dispatch_private.h" -#include "work_queue.h" -#include <stdio.h> -#include <time.h> - -static char *module="SERVER"; -static __thread dx_server_t *thread_server = 0; - -typedef struct dx_thread_t { - dx_server_t *dx_server; - int thread_id; - volatile int running; - volatile int canceled; - int using_thread; - sys_thread_t *thread; -} dx_thread_t; - - -struct dx_server_t { - int thread_count; - const char *container_name; - pn_driver_t *driver; - dx_thread_start_cb_t start_handler; - dx_conn_handler_cb_t conn_handler; - dx_user_fd_handler_cb_t ufd_handler; - void *start_context; - void *conn_handler_context; - sys_cond_t *cond; - sys_mutex_t *lock; - dx_thread_t **threads; - work_queue_t *work_queue; - dx_timer_list_t pending_timers; - bool a_thread_is_waiting; - int threads_active; - int pause_requests; - int threads_paused; - int pause_next_sequence; - int pause_now_serving; - dx_signal_handler_cb_t signal_handler; - void *signal_context; - int pending_signal; -}; - - - - -ALLOC_DEFINE(dx_listener_t); -ALLOC_DEFINE(dx_connector_t); -ALLOC_DEFINE(dx_connection_t); -ALLOC_DEFINE(dx_user_fd_t); - - -static dx_thread_t *thread(dx_server_t *dx_server, int id) -{ - dx_thread_t *thread = NEW(dx_thread_t); - if (!thread) - return 0; - - thread->dx_server = dx_server; - thread->thread_id = id; - thread->running = 0; - thread->canceled = 0; - thread->using_thread = 0; - - return thread; -} - - -static void thread_process_listeners(dx_server_t *dx_server) -{ - pn_driver_t *driver = dx_server->driver; - pn_listener_t *listener = pn_driver_listener(driver); - pn_connector_t *cxtr; - dx_connection_t *ctx; - - while (listener) { - cxtr = pn_listener_accept(listener); - dx_log(module, LOG_TRACE, "Accepting Connection from %s", pn_connector_name(cxtr)); - ctx = new_dx_connection_t(); - ctx->state = CONN_STATE_OPENING; - ctx->owner_thread = CONTEXT_NO_OWNER; - ctx->enqueued = 0; - ctx->pn_cxtr = cxtr; - ctx->listener = (dx_listener_t*) pn_listener_context(listener); - ctx->connector = 0; - ctx->context = ctx->listener->context; - ctx->user_context = 0; - ctx->link_context = 0; - ctx->ufd = 0; - - pn_connection_t *conn = pn_connection(); - pn_connection_set_container(conn, dx_server->container_name); - pn_connector_set_connection(cxtr, conn); - pn_connection_set_context(conn, ctx); - ctx->pn_conn = conn; - - // - // Get a pointer to the transport so we can insert security components into it - // - pn_transport_t *tport = pn_connector_transport(cxtr); - const dx_server_config_t *config = ctx->listener->config; - - // - // Set up SSL if appropriate - // - if (config->ssl_enabled) { - pn_ssl_domain_t *domain = pn_ssl_domain(PN_SSL_MODE_SERVER); - pn_ssl_domain_set_credentials(domain, - config->ssl_certificate_file, - config->ssl_private_key_file, - config->ssl_password); - if (config->ssl_allow_unsecured_client) - pn_ssl_domain_allow_unsecured_client(domain); - - if (config->ssl_require_peer_authentication) - pn_ssl_domain_set_peer_authentication(domain, PN_SSL_VERIFY_PEER_NAME, config->ssl_trusted_certificate_db); - - pn_ssl_t *ssl = pn_ssl(tport); - pn_ssl_init(ssl, domain, 0); - pn_ssl_domain_free(domain); - } - - // - // Set up SASL - // - pn_sasl_t *sasl = pn_sasl(tport); - pn_sasl_mechanisms(sasl, config->sasl_mechanisms); - pn_sasl_server(sasl); - pn_sasl_done(sasl, PN_SASL_OK); // TODO - This needs to go away - - pn_connector_set_context(cxtr, ctx); - listener = pn_driver_listener(driver); - } -} - - -static void handle_signals_LH(dx_server_t *dx_server) -{ - int signum = dx_server->pending_signal; - - if (signum) { - dx_server->pending_signal = 0; - if (dx_server->signal_handler) { - sys_mutex_unlock(dx_server->lock); - dx_server->signal_handler(dx_server->signal_context, signum); - sys_mutex_lock(dx_server->lock); - } - } -} - - -static void block_if_paused_LH(dx_server_t *dx_server) -{ - if (dx_server->pause_requests > 0) { - dx_server->threads_paused++; - sys_cond_signal_all(dx_server->cond); - while (dx_server->pause_requests > 0) - sys_cond_wait(dx_server->cond, dx_server->lock); - dx_server->threads_paused--; - } -} - - -static int process_connector(dx_server_t *dx_server, pn_connector_t *cxtr) -{ - dx_connection_t *ctx = pn_connector_context(cxtr); - int events = 0; - int passes = 0; - - if (ctx->state == CONN_STATE_USER) { - dx_server->ufd_handler(ctx->ufd->context, ctx->ufd); - return 1; - } - - do { - passes++; - - // - // Step the engine for pre-handler processing - // - pn_connector_process(cxtr); - - // - // Call the handler that is appropriate for the connector's state. - // - switch (ctx->state) { - case CONN_STATE_CONNECTING: { - if (pn_connector_closed(cxtr)) { - ctx->state = CONN_STATE_FAILED; - events = 0; - break; - } - - pn_connection_t *conn = pn_connection(); - pn_connection_set_container(conn, dx_server->container_name); - pn_connector_set_connection(cxtr, conn); - pn_connection_set_context(conn, ctx); - ctx->pn_conn = conn; - - pn_transport_t *tport = pn_connector_transport(cxtr); - const dx_server_config_t *config = ctx->connector->config; - - // - // Set up SSL if appropriate - // - if (config->ssl_enabled) { - pn_ssl_domain_t *domain = pn_ssl_domain(PN_SSL_MODE_CLIENT); - pn_ssl_domain_set_credentials(domain, - config->ssl_certificate_file, - config->ssl_private_key_file, - config->ssl_password); - - if (config->ssl_require_peer_authentication) - pn_ssl_domain_set_peer_authentication(domain, PN_SSL_VERIFY_PEER_NAME, config->ssl_trusted_certificate_db); - - pn_ssl_t *ssl = pn_ssl(tport); - pn_ssl_init(ssl, domain, 0); - pn_ssl_domain_free(domain); - } - - // - // Set up SASL - // - pn_sasl_t *sasl = pn_sasl(tport); - pn_sasl_mechanisms(sasl, config->sasl_mechanisms); - pn_sasl_client(sasl); - - ctx->state = CONN_STATE_OPENING; - assert(ctx->connector); - ctx->connector->state = CXTR_STATE_OPEN; - events = 1; - break; - } - - case CONN_STATE_OPENING: { - pn_transport_t *tport = pn_connector_transport(cxtr); - pn_sasl_t *sasl = pn_sasl(tport); - - if (pn_sasl_outcome(sasl) == PN_SASL_OK) { - ctx->state = CONN_STATE_OPERATIONAL; - - dx_conn_event_t ce = DX_CONN_EVENT_PROCESS; // Initialize to keep the compiler happy - - if (ctx->listener) { - ce = DX_CONN_EVENT_LISTENER_OPEN; - } else if (ctx->connector) { - ce = DX_CONN_EVENT_CONNECTOR_OPEN; - ctx->connector->delay = 0; - } else - assert(0); - - dx_server->conn_handler(dx_server->conn_handler_context, - ctx->context, ce, (dx_connection_t*) pn_connector_context(cxtr)); - events = 1; - break; - } - else if (pn_sasl_outcome(sasl) != PN_SASL_NONE) { - ctx->state = CONN_STATE_FAILED; - if (ctx->connector) { - const dx_server_config_t *config = ctx->connector->config; - dx_log(module, LOG_TRACE, "Connection to %s:%s failed", config->host, config->port); - } - } - } - - case CONN_STATE_OPERATIONAL: - if (pn_connector_closed(cxtr)) { - dx_server->conn_handler(dx_server->conn_handler_context, ctx->context, - DX_CONN_EVENT_CLOSE, - (dx_connection_t*) pn_connector_context(cxtr)); - events = 0; - } - else - events = dx_server->conn_handler(dx_server->conn_handler_context, ctx->context, - DX_CONN_EVENT_PROCESS, - (dx_connection_t*) pn_connector_context(cxtr)); - break; - - default: - break; - } - } while (events > 0); - - return passes > 1; -} - - -// -// TEMPORARY FUNCTION PROTOTYPES -// -void pn_driver_wait_1(pn_driver_t *d); -int pn_driver_wait_2(pn_driver_t *d, int timeout); -void pn_driver_wait_3(pn_driver_t *d); -// -// END TEMPORARY -// - -static void *thread_run(void *arg) -{ - dx_thread_t *thread = (dx_thread_t*) arg; - dx_server_t *dx_server = thread->dx_server; - pn_connector_t *work; - pn_connection_t *conn; - dx_connection_t *ctx; - int error; - int poll_result; - - if (!thread) - return 0; - - thread_server = dx_server; - thread->running = 1; - - if (thread->canceled) - return 0; - - // - // Invoke the start handler if the application supplied one. - // This handler can be used to set NUMA or processor affinnity for the thread. - // - if (dx_server->start_handler) - dx_server->start_handler(dx_server->start_context, thread->thread_id); - - // - // Main Loop - // - while (thread->running) { - sys_mutex_lock(dx_server->lock); - - // - // Check for pending signals to process - // - handle_signals_LH(dx_server); - if (!thread->running) { - sys_mutex_unlock(dx_server->lock); - break; - } - - // - // Check to see if the server is pausing. If so, block here. - // - block_if_paused_LH(dx_server); - if (!thread->running) { - sys_mutex_unlock(dx_server->lock); - break; - } - - // - // Service pending timers. - // - dx_timer_t *timer = DEQ_HEAD(dx_server->pending_timers); - if (timer) { - DEQ_REMOVE_HEAD(dx_server->pending_timers); - - // - // Mark the timer as idle in case it reschedules itself. - // - dx_timer_idle_LH(timer); - - // - // Release the lock and invoke the connection handler. - // - sys_mutex_unlock(dx_server->lock); - timer->handler(timer->context); - pn_driver_wakeup(dx_server->driver); - continue; - } - - // - // Check the work queue for connectors scheduled for processing. - // - work = work_queue_get(dx_server->work_queue); - if (!work) { - // - // There is no pending work to do - // - if (dx_server->a_thread_is_waiting) { - // - // Another thread is waiting on the proton driver, this thread must - // wait on the condition variable until signaled. - // - sys_cond_wait(dx_server->cond, dx_server->lock); - } else { - // - // This thread elects itself to wait on the proton driver. Set the - // thread-is-waiting flag so other idle threads will not interfere. - // - dx_server->a_thread_is_waiting = true; - - // - // Ask the timer module when its next timer is scheduled to fire. We'll - // use this value in driver_wait as the timeout. If there are no scheduled - // timers, the returned value will be -1. - // - long duration = dx_timer_next_duration_LH(); - - // - // Invoke the proton driver's wait sequence. This is a bit of a hack for now - // and will be improved in the future. The wait process is divided into three parts, - // the first and third of which need to be non-reentrant, and the second of which - // must be reentrant (and blocks). - // - pn_driver_wait_1(dx_server->driver); - sys_mutex_unlock(dx_server->lock); - - do { - error = 0; - poll_result = pn_driver_wait_2(dx_server->driver, duration); - if (poll_result == -1) - error = pn_driver_errno(dx_server->driver); - } while (error == PN_INTR); - if (error) { - dx_log(module, LOG_ERROR, "Driver Error: %s", pn_error_text(pn_error(dx_server->driver))); - exit(-1); - } - - sys_mutex_lock(dx_server->lock); - pn_driver_wait_3(dx_server->driver); - - if (!thread->running) { - sys_mutex_unlock(dx_server->lock); - break; - } - - // - // Visit the timer module. - // - struct timespec tv; - clock_gettime(CLOCK_REALTIME, &tv); - long milliseconds = tv.tv_sec * 1000 + tv.tv_nsec / 1000000; - dx_timer_visit_LH(milliseconds); - - // - // Process listeners (incoming connections). - // - thread_process_listeners(dx_server); - - // - // Traverse the list of connectors-needing-service from the proton driver. - // If the connector is not already in the work queue and it is not currently - // being processed by another thread, put it in the work queue and signal the - // condition variable. - // - work = pn_driver_connector(dx_server->driver); - while (work) { - ctx = pn_connector_context(work); - if (!ctx->enqueued && ctx->owner_thread == CONTEXT_NO_OWNER) { - ctx->enqueued = 1; - work_queue_put(dx_server->work_queue, work); - sys_cond_signal(dx_server->cond); - } - work = pn_driver_connector(dx_server->driver); - } - - // - // Release our exclusive claim on pn_driver_wait. - // - dx_server->a_thread_is_waiting = false; - } - } - - // - // If we were given a connector to work on from the work queue, mark it as - // owned by this thread and as no longer enqueued. - // - if (work) { - ctx = pn_connector_context(work); - if (ctx->owner_thread == CONTEXT_NO_OWNER) { - ctx->owner_thread = thread->thread_id; - ctx->enqueued = 0; - dx_server->threads_active++; - } else { - // - // This connector is being processed by another thread, re-queue it. - // - work_queue_put(dx_server->work_queue, work); - work = 0; - } - } - sys_mutex_unlock(dx_server->lock); - - // - // Process the connector that we now have exclusive access to. - // - if (work) { - int work_done = process_connector(dx_server, work); - - // - // Check to see if the connector was closed during processing - // - if (pn_connector_closed(work)) { - // - // Connector is closed. Free the context and the connector. - // - conn = pn_connector_connection(work); - - // - // If this is a dispatch connector, schedule the re-connect timer - // - if (ctx->connector) { - ctx->connector->ctx = 0; - ctx->connector->state = CXTR_STATE_CONNECTING; - dx_timer_schedule(ctx->connector->timer, ctx->connector->delay); - } - - sys_mutex_lock(dx_server->lock); - free_dx_connection_t(ctx); - pn_connector_free(work); - if (conn) - pn_connection_free(conn); - dx_server->threads_active--; - sys_mutex_unlock(dx_server->lock); - } else { - // - // The connector lives on. Mark it as no longer owned by this thread. - // - sys_mutex_lock(dx_server->lock); - ctx->owner_thread = CONTEXT_NO_OWNER; - dx_server->threads_active--; - sys_mutex_unlock(dx_server->lock); - } - - // - // Wake up the proton driver to force it to reconsider its set of FDs - // in light of the processing that just occurred. - // - if (work_done) - pn_driver_wakeup(dx_server->driver); - } - } - - return 0; -} - - -static void thread_start(dx_thread_t *thread) -{ - if (!thread) - return; - - thread->using_thread = 1; - thread->thread = sys_thread(thread_run, (void*) thread); -} - - -static void thread_cancel(dx_thread_t *thread) -{ - if (!thread) - return; - - thread->running = 0; - thread->canceled = 1; -} - - -static void thread_join(dx_thread_t *thread) -{ - if (!thread) - return; - - if (thread->using_thread) - sys_thread_join(thread->thread); -} - - -static void thread_free(dx_thread_t *thread) -{ - if (!thread) - return; - - free(thread); -} - - -static void cxtr_try_open(void *context) -{ - dx_connector_t *ct = (dx_connector_t*) context; - if (ct->state != CXTR_STATE_CONNECTING) - return; - - dx_connection_t *ctx = new_dx_connection_t(); - ctx->server = ct->server; - ctx->state = CONN_STATE_CONNECTING; - ctx->owner_thread = CONTEXT_NO_OWNER; - ctx->enqueued = 0; - ctx->pn_conn = 0; - ctx->listener = 0; - ctx->connector = ct; - ctx->context = ct->context; - ctx->user_context = 0; - ctx->link_context = 0; - ctx->ufd = 0; - - // - // pn_connector is not thread safe - // - sys_mutex_lock(ct->server->lock); - ctx->pn_cxtr = pn_connector(ct->server->driver, ct->config->host, ct->config->port, (void*) ctx); - sys_mutex_unlock(ct->server->lock); - - ct->ctx = ctx; - ct->delay = 5000; - dx_log(module, LOG_TRACE, "Connecting to %s:%s", ct->config->host, ct->config->port); -} - - -dx_server_t *dx_server(int thread_count, const char *container_name) -{ - int i; - - dx_server_t *dx_server = NEW(dx_server_t); - if (dx_server == 0) - return 0; - - dx_server->thread_count = thread_count; - dx_server->container_name = container_name; - dx_server->driver = pn_driver(); - dx_server->start_handler = 0; - dx_server->conn_handler = 0; - dx_server->signal_handler = 0; - dx_server->ufd_handler = 0; - dx_server->start_context = 0; - dx_server->signal_context = 0; - dx_server->lock = sys_mutex(); - dx_server->cond = sys_cond(); - - dx_timer_initialize(dx_server->lock); - - dx_server->threads = NEW_PTR_ARRAY(dx_thread_t, thread_count); - for (i = 0; i < thread_count; i++) - dx_server->threads[i] = thread(dx_server, i); - - dx_server->work_queue = work_queue(); - DEQ_INIT(dx_server->pending_timers); - dx_server->a_thread_is_waiting = false; - dx_server->threads_active = 0; - dx_server->pause_requests = 0; - dx_server->threads_paused = 0; - dx_server->pause_next_sequence = 0; - dx_server->pause_now_serving = 0; - dx_server->pending_signal = 0; - - dx_log(module, LOG_INFO, "Container Name: %s", dx_server->container_name); - - return dx_server; -} - - -void dx_server_setup_agent(dx_dispatch_t *dx) -{ - // TODO -} - - -void dx_server_free(dx_server_t *dx_server) -{ - int i; - if (!dx_server) - return; - - for (i = 0; i < dx_server->thread_count; i++) - thread_free(dx_server->threads[i]); - - work_queue_free(dx_server->work_queue); - - pn_driver_free(dx_server->driver); - sys_mutex_free(dx_server->lock); - sys_cond_free(dx_server->cond); - free(dx_server); -} - - -void dx_server_set_conn_handler(dx_dispatch_t *dx, dx_conn_handler_cb_t handler, void *handler_context) -{ - dx->server->conn_handler = handler; - dx->server->conn_handler_context = handler_context; -} - - -void dx_server_set_signal_handler(dx_dispatch_t *dx, dx_signal_handler_cb_t handler, void *context) -{ - dx->server->signal_handler = handler; - dx->server->signal_context = context; -} - - -void dx_server_set_start_handler(dx_dispatch_t *dx, dx_thread_start_cb_t handler, void *context) -{ - dx->server->start_handler = handler; - dx->server->start_context = context; -} - - -void dx_server_set_user_fd_handler(dx_dispatch_t *dx, dx_user_fd_handler_cb_t ufd_handler) -{ - dx->server->ufd_handler = ufd_handler; -} - - -void dx_server_run(dx_dispatch_t *dx) -{ - dx_server_t *dx_server = dx->server; - - int i; - if (!dx_server) - return; - - assert(dx_server->conn_handler); // Server can't run without a connection handler. - - for (i = 1; i < dx_server->thread_count; i++) - thread_start(dx_server->threads[i]); - - dx_log(module, LOG_INFO, "Operational, %d Threads Running", dx_server->thread_count); - - thread_run((void*) dx_server->threads[0]); - - for (i = 1; i < dx_server->thread_count; i++) - thread_join(dx_server->threads[i]); - - dx_log(module, LOG_INFO, "Shut Down"); -} - - -void dx_server_start(dx_dispatch_t *dx) -{ - dx_server_t *dx_server = dx->server; - int i; - - if (!dx_server) - return; - - assert(dx_server->conn_handler); // Server can't run without a connection handler. - - for (i = 0; i < dx_server->thread_count; i++) - thread_start(dx_server->threads[i]); - - dx_log(module, LOG_INFO, "Operational, %d Threads Running", dx_server->thread_count); -} - - -void dx_server_stop(dx_dispatch_t *dx) -{ - dx_server_t *dx_server = dx->server; - int idx; - - sys_mutex_lock(dx_server->lock); - for (idx = 0; idx < dx_server->thread_count; idx++) - thread_cancel(dx_server->threads[idx]); - sys_cond_signal_all(dx_server->cond); - pn_driver_wakeup(dx_server->driver); - sys_mutex_unlock(dx_server->lock); - - if (thread_server != dx_server) { - for (idx = 0; idx < dx_server->thread_count; idx++) - thread_join(dx_server->threads[idx]); - dx_log(module, LOG_INFO, "Shut Down"); - } -} - - -void dx_server_signal(dx_dispatch_t *dx, int signum) -{ - dx_server_t *dx_server = dx->server; - - dx_server->pending_signal = signum; - sys_cond_signal_all(dx_server->cond); - pn_driver_wakeup(dx_server->driver); -} - - -void dx_server_pause(dx_dispatch_t *dx) -{ - dx_server_t *dx_server = dx->server; - - sys_mutex_lock(dx_server->lock); - - // - // Bump the request count to stop all the threads. - // - dx_server->pause_requests++; - int my_sequence = dx_server->pause_next_sequence++; - - // - // Awaken all threads that are currently blocking. - // - sys_cond_signal_all(dx_server->cond); - pn_driver_wakeup(dx_server->driver); - - // - // Wait for the paused thread count plus the number of threads requesting a pause to equal - // the total thread count. Also, don't exit the blocking loop until now_serving equals our - // sequence number. This ensures that concurrent pausers don't run at the same time. - // - while ((dx_server->threads_paused + dx_server->pause_requests < dx_server->thread_count) || - (my_sequence != dx_server->pause_now_serving)) - sys_cond_wait(dx_server->cond, dx_server->lock); - - sys_mutex_unlock(dx_server->lock); -} - - -void dx_server_resume(dx_dispatch_t *dx) -{ - dx_server_t *dx_server = dx->server; - - sys_mutex_lock(dx_server->lock); - dx_server->pause_requests--; - dx_server->pause_now_serving++; - sys_cond_signal_all(dx_server->cond); - sys_mutex_unlock(dx_server->lock); -} - - -void dx_server_activate(dx_connection_t *ctx) -{ - if (!ctx) - return; - - pn_connector_t *ctor = ctx->pn_cxtr; - if (!ctor) - return; - - if (!pn_connector_closed(ctor)) - pn_connector_activate(ctor, PN_CONNECTOR_WRITABLE); -} - - -void dx_connection_set_context(dx_connection_t *conn, void *context) -{ - conn->user_context = context; -} - - -void *dx_connection_get_context(dx_connection_t *conn) -{ - return conn->user_context; -} - - -void dx_connection_set_link_context(dx_connection_t *conn, void *context) -{ - conn->link_context = context; -} - - -void *dx_connection_get_link_context(dx_connection_t *conn) -{ - return conn->link_context; -} - - -pn_connection_t *dx_connection_pn(dx_connection_t *conn) -{ - return conn->pn_conn; -} - - -const dx_server_config_t *dx_connection_config(const dx_connection_t *conn) -{ - if (conn->listener) - return conn->listener->config; - return conn->connector->config; -} - - -dx_listener_t *dx_server_listen(dx_dispatch_t *dx, const dx_server_config_t *config, void *context) -{ - dx_server_t *dx_server = dx->server; - dx_listener_t *li = new_dx_listener_t(); - - if (!li) - return 0; - - li->server = dx_server; - li->config = config; - li->context = context; - li->pn_listener = pn_listener(dx_server->driver, config->host, config->port, (void*) li); - - if (!li->pn_listener) { - dx_log(module, LOG_ERROR, "Driver Error %d (%s)", - pn_driver_errno(dx_server->driver), pn_driver_error(dx_server->driver)); - free_dx_listener_t(li); - return 0; - } - dx_log(module, LOG_TRACE, "Listening on %s:%s", config->host, config->port); - - return li; -} - - -void dx_server_listener_free(dx_listener_t* li) -{ - pn_listener_free(li->pn_listener); - free_dx_listener_t(li); -} - - -void dx_server_listener_close(dx_listener_t* li) -{ - pn_listener_close(li->pn_listener); -} - - -dx_connector_t *dx_server_connect(dx_dispatch_t *dx, const dx_server_config_t *config, void *context) -{ - dx_server_t *dx_server = dx->server; - dx_connector_t *ct = new_dx_connector_t(); - - if (!ct) - return 0; - - ct->server = dx_server; - ct->state = CXTR_STATE_CONNECTING; - ct->config = config; - ct->context = context; - ct->ctx = 0; - ct->timer = dx_timer(dx, cxtr_try_open, (void*) ct); - ct->delay = 0; - - dx_timer_schedule(ct->timer, ct->delay); - return ct; -} - - -void dx_server_connector_free(dx_connector_t* ct) -{ - // Don't free the proton connector. This will be done by the connector - // processing/cleanup. - - if (ct->ctx) { - pn_connector_close(ct->ctx->pn_cxtr); - ct->ctx->connector = 0; - } - - dx_timer_free(ct->timer); - free_dx_connector_t(ct); -} - - -dx_user_fd_t *dx_user_fd(dx_dispatch_t *dx, int fd, void *context) -{ - dx_server_t *dx_server = dx->server; - dx_user_fd_t *ufd = new_dx_user_fd_t(); - - if (!ufd) - return 0; - - dx_connection_t *ctx = new_dx_connection_t(); - ctx->server = dx_server; - ctx->state = CONN_STATE_USER; - ctx->owner_thread = CONTEXT_NO_OWNER; - ctx->enqueued = 0; - ctx->pn_conn = 0; - ctx->listener = 0; - ctx->connector = 0; - ctx->context = 0; - ctx->user_context = 0; - ctx->link_context = 0; - ctx->ufd = ufd; - - ufd->context = context; - ufd->server = dx_server; - ufd->fd = fd; - ufd->pn_conn = pn_connector_fd(dx_server->driver, fd, (void*) ctx); - pn_driver_wakeup(dx_server->driver); - - return ufd; -} - - -void dx_user_fd_free(dx_user_fd_t *ufd) -{ - pn_connector_close(ufd->pn_conn); - free_dx_user_fd_t(ufd); -} - - -void dx_user_fd_activate_read(dx_user_fd_t *ufd) -{ - pn_connector_activate(ufd->pn_conn, PN_CONNECTOR_READABLE); - pn_driver_wakeup(ufd->server->driver); -} - - -void dx_user_fd_activate_write(dx_user_fd_t *ufd) -{ - pn_connector_activate(ufd->pn_conn, PN_CONNECTOR_WRITABLE); - pn_driver_wakeup(ufd->server->driver); -} - - -bool dx_user_fd_is_readable(dx_user_fd_t *ufd) -{ - return pn_connector_activated(ufd->pn_conn, PN_CONNECTOR_READABLE); -} - - -bool dx_user_fd_is_writeable(dx_user_fd_t *ufd) -{ - return pn_connector_activated(ufd->pn_conn, PN_CONNECTOR_WRITABLE); -} - - -void dx_server_timer_pending_LH(dx_timer_t *timer) -{ - DEQ_INSERT_TAIL(timer->server->pending_timers, timer); -} - - -void dx_server_timer_cancel_LH(dx_timer_t *timer) -{ - DEQ_REMOVE(timer->server->pending_timers, timer); -} - diff --git a/extras/dispatch/src/server_private.h b/extras/dispatch/src/server_private.h deleted file mode 100644 index 86a3ef98f1..0000000000 --- a/extras/dispatch/src/server_private.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef __server_private_h__ -#define __server_private_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/server.h> -#include <qpid/dispatch/user_fd.h> -#include <qpid/dispatch/timer.h> -#include <qpid/dispatch/alloc.h> -#include <proton/driver.h> -#include <proton/driver_extras.h> - -void dx_server_timer_pending_LH(dx_timer_t *timer); -void dx_server_timer_cancel_LH(dx_timer_t *timer); - - -typedef enum { - CONN_STATE_CONNECTING = 0, - CONN_STATE_OPENING, - CONN_STATE_OPERATIONAL, - CONN_STATE_FAILED, - CONN_STATE_USER -} conn_state_t; - -#define CONTEXT_NO_OWNER -1 - -typedef enum { - CXTR_STATE_CONNECTING = 0, - CXTR_STATE_OPEN, - CXTR_STATE_FAILED -} cxtr_state_t; - -typedef struct dx_server_t dx_server_t; - -struct dx_listener_t { - dx_server_t *server; - const dx_server_config_t *config; - void *context; - pn_listener_t *pn_listener; -}; - - -struct dx_connector_t { - dx_server_t *server; - cxtr_state_t state; - const dx_server_config_t *config; - void *context; - dx_connection_t *ctx; - dx_timer_t *timer; - long delay; -}; - - -struct dx_connection_t { - dx_server_t *server; - conn_state_t state; - int owner_thread; - int enqueued; - pn_connector_t *pn_cxtr; - pn_connection_t *pn_conn; - dx_listener_t *listener; - dx_connector_t *connector; - void *context; // Copy of context from listener or connector - void *user_context; - void *link_context; // Context shared by this connection's links - dx_user_fd_t *ufd; -}; - - -struct dx_user_fd_t { - dx_server_t *server; - void *context; - int fd; - pn_connector_t *pn_conn; -}; - - -ALLOC_DECLARE(dx_listener_t); -ALLOC_DECLARE(dx_connector_t); -ALLOC_DECLARE(dx_connection_t); -ALLOC_DECLARE(dx_user_fd_t); - - -#endif diff --git a/extras/dispatch/src/timer.c b/extras/dispatch/src/timer.c deleted file mode 100644 index a7f36e149b..0000000000 --- a/extras/dispatch/src/timer.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "timer_private.h" -#include "server_private.h" -#include "dispatch_private.h" -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/threading.h> -#include <qpid/dispatch/alloc.h> -#include <assert.h> -#include <stdio.h> - -static sys_mutex_t *lock; -static dx_timer_list_t idle_timers; -static dx_timer_list_t scheduled_timers; -static long time_base; - -ALLOC_DECLARE(dx_timer_t); -ALLOC_DEFINE(dx_timer_t); - -//========================================================================= -// Private static functions -//========================================================================= - -static void dx_timer_cancel_LH(dx_timer_t *timer) -{ - switch (timer->state) { - case TIMER_FREE: - assert(0); - break; - - case TIMER_IDLE: - break; - - case TIMER_SCHEDULED: - if (timer->next) - timer->next->delta_time += timer->delta_time; - DEQ_REMOVE(scheduled_timers, timer); - DEQ_INSERT_TAIL(idle_timers, timer); - break; - - case TIMER_PENDING: - dx_server_timer_cancel_LH(timer); - DEQ_INSERT_TAIL(idle_timers, timer); - break; - } - - timer->state = TIMER_IDLE; -} - - -//========================================================================= -// Public Functions from timer.h -//========================================================================= - -dx_timer_t *dx_timer(dx_dispatch_t *dx, dx_timer_cb_t cb, void* context) -{ - dx_timer_t *timer = new_dx_timer_t(); - if (!timer) - return 0; - - DEQ_ITEM_INIT(timer); - - timer->server = dx ? dx->server : 0; - timer->handler = cb; - timer->context = context; - timer->delta_time = 0; - timer->state = TIMER_IDLE; - - sys_mutex_lock(lock); - DEQ_INSERT_TAIL(idle_timers, timer); - sys_mutex_unlock(lock); - - return timer; -} - - -void dx_timer_free(dx_timer_t *timer) -{ - sys_mutex_lock(lock); - dx_timer_cancel_LH(timer); - DEQ_REMOVE(idle_timers, timer); - sys_mutex_unlock(lock); - - timer->state = TIMER_FREE; - free_dx_timer_t(timer); -} - - -void dx_timer_schedule(dx_timer_t *timer, long duration) -{ - dx_timer_t *ptr; - dx_timer_t *last; - long total_time; - - sys_mutex_lock(lock); - dx_timer_cancel_LH(timer); // Timer is now on the idle list - assert(timer->state == TIMER_IDLE); - DEQ_REMOVE(idle_timers, timer); - - // - // Handle the special case of a zero-time scheduling. In this case, - // the timer doesn't go on the scheduled list. It goes straight to the - // pending list in the server. - // - if (duration == 0) { - timer->state = TIMER_PENDING; - dx_server_timer_pending_LH(timer); - sys_mutex_unlock(lock); - return; - } - - // - // Find the insert point in the schedule. - // - total_time = 0; - ptr = DEQ_HEAD(scheduled_timers); - assert(!ptr || ptr->prev == 0); - while (ptr) { - total_time += ptr->delta_time; - if (total_time > duration) - break; - ptr = ptr->next; - } - - // - // Insert the timer into the schedule and adjust the delta time - // of the following timer if present. - // - if (total_time <= duration) { - assert(ptr == 0); - timer->delta_time = duration - total_time; - DEQ_INSERT_TAIL(scheduled_timers, timer); - } else { - total_time -= ptr->delta_time; - timer->delta_time = duration - total_time; - assert(ptr->delta_time > timer->delta_time); - ptr->delta_time -= timer->delta_time; - last = ptr->prev; - if (last) - DEQ_INSERT_AFTER(scheduled_timers, timer, last); - else - DEQ_INSERT_HEAD(scheduled_timers, timer); - } - - timer->state = TIMER_SCHEDULED; - - sys_mutex_unlock(lock); -} - - -void dx_timer_cancel(dx_timer_t *timer) -{ - sys_mutex_lock(lock); - dx_timer_cancel_LH(timer); - sys_mutex_unlock(lock); -} - - -//========================================================================= -// Private Functions from timer_private.h -//========================================================================= - -void dx_timer_initialize(sys_mutex_t *server_lock) -{ - lock = server_lock; - DEQ_INIT(idle_timers); - DEQ_INIT(scheduled_timers); - time_base = 0; -} - - -void dx_timer_finalize(void) -{ - lock = 0; -} - - -long dx_timer_next_duration_LH(void) -{ - dx_timer_t *timer = DEQ_HEAD(scheduled_timers); - if (timer) - return timer->delta_time; - return -1; -} - - -void dx_timer_visit_LH(long current_time) -{ - long delta; - dx_timer_t *timer = DEQ_HEAD(scheduled_timers); - - if (time_base == 0) { - time_base = current_time; - return; - } - - delta = current_time - time_base; - time_base = current_time; - - while (timer) { - assert(delta >= 0); - if (timer->delta_time > delta) { - timer->delta_time -= delta; - break; - } else { - DEQ_REMOVE_HEAD(scheduled_timers); - delta -= timer->delta_time; - timer->state = TIMER_PENDING; - dx_server_timer_pending_LH(timer); - - } - timer = DEQ_HEAD(scheduled_timers); - } -} - - -void dx_timer_idle_LH(dx_timer_t *timer) -{ - timer->state = TIMER_IDLE; - DEQ_INSERT_TAIL(idle_timers, timer); -} - diff --git a/extras/dispatch/src/timer_private.h b/extras/dispatch/src/timer_private.h deleted file mode 100644 index 4e173b7ad4..0000000000 --- a/extras/dispatch/src/timer_private.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __timer_private_h__ -#define __timer_private_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/timer.h> -#include <qpid/dispatch/threading.h> -#include "server_private.h" - -typedef enum { - TIMER_FREE, - TIMER_IDLE, - TIMER_SCHEDULED, - TIMER_PENDING -} dx_timer_state_t; - - -struct dx_timer_t { - DEQ_LINKS(dx_timer_t); - dx_server_t *server; - dx_timer_cb_t handler; - void *context; - long delta_time; - dx_timer_state_t state; -}; - -DEQ_DECLARE(dx_timer_t, dx_timer_list_t); - -void dx_timer_initialize(sys_mutex_t *server_lock); -void dx_timer_finalize(void); -long dx_timer_next_duration_LH(void); -void dx_timer_visit_LH(long current_time); -void dx_timer_idle_LH(dx_timer_t *timer); - - -#endif diff --git a/extras/dispatch/src/work_queue.c b/extras/dispatch/src/work_queue.c deleted file mode 100644 index 93c1cda1a9..0000000000 --- a/extras/dispatch/src/work_queue.c +++ /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/dispatch/ctools.h> -#include "work_queue.h" -#include <string.h> -#include <stdio.h> - -#define BATCH_SIZE 100 -typedef struct work_item_t work_item_t; - -struct work_item_t { - DEQ_LINKS(work_item_t); - pn_connector_t *conn; -}; - -DEQ_DECLARE(work_item_t, work_list_t); - -struct work_queue_t { - work_list_t items; - work_list_t free_list; -}; - -static void allocate_batch(work_queue_t *w) -{ - int i; - work_item_t *batch = NEW_ARRAY(work_item_t, BATCH_SIZE); - if (!batch) - return; - - memset(batch, 0, sizeof(work_item_t) * BATCH_SIZE); - - for (i = 0; i < BATCH_SIZE; i++) - DEQ_INSERT_TAIL(w->free_list, &batch[i]); -} - - -work_queue_t *work_queue(void) -{ - work_queue_t *w = NEW(work_queue_t); - if (!w) - return 0; - - DEQ_INIT(w->items); - DEQ_INIT(w->free_list); - - allocate_batch(w); - - return w; -} - - -void work_queue_free(work_queue_t *w) -{ - if (!w) - return; - - // KEEP TRACK OF BATCHES AND FREE - free(w); -} - - -void work_queue_put(work_queue_t *w, pn_connector_t *conn) -{ - work_item_t *item; - - if (!w) - return; - if (DEQ_SIZE(w->free_list) == 0) - allocate_batch(w); - if (DEQ_SIZE(w->free_list) == 0) - return; - - item = DEQ_HEAD(w->free_list); - DEQ_REMOVE_HEAD(w->free_list); - - item->conn = conn; - - DEQ_INSERT_TAIL(w->items, item); -} - - -pn_connector_t *work_queue_get(work_queue_t *w) -{ - work_item_t *item; - pn_connector_t *conn; - - if (!w) - return 0; - item = DEQ_HEAD(w->items); - if (!item) - return 0; - - DEQ_REMOVE_HEAD(w->items); - conn = item->conn; - item->conn = 0; - - DEQ_INSERT_TAIL(w->free_list, item); - - return conn; -} - - -int work_queue_empty(work_queue_t *w) -{ - return !w || DEQ_SIZE(w->items) == 0; -} - - -int work_queue_depth(work_queue_t *w) -{ - if (!w) - return 0; - return DEQ_SIZE(w->items); -} - diff --git a/extras/dispatch/src/work_queue.h b/extras/dispatch/src/work_queue.h deleted file mode 100644 index 3ad5c21c81..0000000000 --- a/extras/dispatch/src/work_queue.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __work_queue_h__ -#define __work_queue_h__ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include <proton/driver.h> - -typedef struct work_queue_t work_queue_t; - -work_queue_t *work_queue(void); -void work_queue_free(work_queue_t *w); -void work_queue_put(work_queue_t *w, pn_connector_t *conn); -pn_connector_t *work_queue_get(work_queue_t *w); -int work_queue_empty(work_queue_t *w); -int work_queue_depth(work_queue_t *w); - -#endif diff --git a/extras/dispatch/tests/CMakeLists.txt b/extras/dispatch/tests/CMakeLists.txt deleted file mode 100644 index fc85018991..0000000000 --- a/extras/dispatch/tests/CMakeLists.txt +++ /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. -## - -## -## Build test applications -## -set(unit_test_SOURCES - alloc_test.c - compose_test.c - parse_test.c - run_unit_tests.c - server_test.c - timer_test.c - tool_test.c - ) - -add_executable(unit_tests ${unit_test_SOURCES}) -target_link_libraries(unit_tests qpid-dispatch) - -set(unit_test_size_SOURCES - field_test.c - message_test.c - run_unit_tests_size.c - ) - -add_executable(unit_tests_size ${unit_test_size_SOURCES}) -target_link_libraries(unit_tests_size qpid-dispatch) - -add_test(unit_tests_size_10000 unit_tests_size 10000) -add_test(unit_tests_size_512 unit_tests_size 512) -add_test(unit_tests_size_10 unit_tests_size 10) -add_test(unit_tests_size_7 unit_tests_size 7) -add_test(unit_tests_size_5 unit_tests_size 5) -add_test(unit_tests_size_3 unit_tests_size 3) -add_test(unit_tests_size_2 unit_tests_size 2) -add_test(unit_tests_size_1 unit_tests_size 1) -add_test(unit_tests unit_tests ${CMAKE_CURRENT_SOURCE_DIR}/threads4.conf) -add_test(router_tests python ${CMAKE_CURRENT_SOURCE_DIR}/router_engine_test.py -v) -add_test(system_tests_single python ${CMAKE_CURRENT_SOURCE_DIR}/system_tests_one_router.py -v) - -set_property(TEST system_tests_single PROPERTY - ENVIRONMENT "CTEST_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}" - ) diff --git a/extras/dispatch/tests/alloc_test.c b/extras/dispatch/tests/alloc_test.c deleted file mode 100644 index 2406048209..0000000000 --- a/extras/dispatch/tests/alloc_test.c +++ /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 "test_case.h" -#include <stdio.h> -#include <string.h> -#include "alloc_private.h" - -typedef struct { - int A; - int B; -} object_t; - -dx_alloc_config_t config = {3, 7, 10}; - -ALLOC_DECLARE(object_t); -ALLOC_DEFINE_CONFIG(object_t, sizeof(object_t), 0, &config); - - -static char* check_stats(dx_alloc_stats_t *stats, uint64_t ah, uint64_t fh, uint64_t ht, uint64_t rt, uint64_t rg) -{ - if (stats->total_alloc_from_heap != ah) return "Incorrect alloc-from-heap"; - if (stats->total_free_to_heap != fh) return "Incorrect free-to-heap"; - if (stats->held_by_threads != ht) return "Incorrect held-by-threads"; - if (stats->batches_rebalanced_to_threads != rt) return "Incorrect rebalance-to-threads"; - if (stats->batches_rebalanced_to_global != rg) return "Incorrect rebalance-to-global"; - return 0; -} - - -static char* test_alloc_basic(void *context) -{ - object_t *obj[50]; - int idx; - dx_alloc_stats_t *stats; - char *error; - - for (idx = 0; idx < 20; idx++) - obj[idx] = new_object_t(); - - stats = alloc_stats_object_t(); - error = check_stats(stats, 21, 0, 21, 0, 0); - if (error) return error; - - for (idx = 0; idx < 20; idx++) - free_object_t(obj[idx]); - - error = check_stats(stats, 21, 5, 6, 0, 5); - if (error) return error; - - for (idx = 0; idx < 20; idx++) - obj[idx] = new_object_t(); - - error = check_stats(stats, 27, 5, 21, 3, 5); - if (error) return error; - - return 0; -} - - -int alloc_tests(void) -{ - int result = 0; - dx_alloc_initialize(); - - TEST_CASE(test_alloc_basic, 0); - - return result; -} - diff --git a/extras/dispatch/tests/compose_test.c b/extras/dispatch/tests/compose_test.c deleted file mode 100644 index 06292c221f..0000000000 --- a/extras/dispatch/tests/compose_test.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <assert.h> -#include <string.h> -#include <inttypes.h> -#include "test_case.h" -#include <qpid/dispatch.h> -#include "compose_private.h" - - -static char *vector0 = - "\x00\x53\x77" // amqp-value - "\xd0\x00\x00\x01\x26\x00\x00\x00\x0a" // list32 with ten items - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x0a" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x0b" // smalluint - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x14" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x15" // smalluint - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x14" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x15" // smalluint - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x14" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x15" // smalluint - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x14" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x15" // smalluint - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x14" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x15" // smalluint - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x14" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x15" // smalluint - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x14" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x15" // smalluint - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x14" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x15" // smalluint - "\xd1\x00\x00\x00\x18\x00\x00\x00\x04" // map32 with two pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x14" // smalluint - "\xa1\x06key002" // str8-utf8 - "\x52\x15" // smalluint - ; - -static int vector0_length = 302; - -static char *test_compose_list_of_maps(void *context) -{ - dx_composed_field_t *field = dx_compose(DX_PERFORMATIVE_BODY_AMQP_VALUE, 0); - - dx_compose_start_list(field); - - dx_compose_start_map(field); - dx_compose_insert_string(field, "key001"); - dx_compose_insert_uint(field, 10); - dx_compose_insert_string(field, "key002"); - dx_compose_insert_uint(field, 11); - dx_compose_end_map(field); - - for (int j = 0; j < 9; j++) { - dx_compose_start_map(field); - dx_compose_insert_string(field, "key001"); - dx_compose_insert_uint(field, 20); - dx_compose_insert_string(field, "key002"); - dx_compose_insert_uint(field, 21); - dx_compose_end_map(field); - } - - dx_compose_end_list(field); - - dx_buffer_t *buf = DEQ_HEAD(field->buffers); - - if (dx_buffer_size(buf) != vector0_length) return "Incorrect Length of Buffer"; - - char *left = vector0; - char *right = (char*) dx_buffer_base(buf); - int idx; - - for (idx = 0; idx < vector0_length; idx++) { - if (*left != *right) return "Pattern Mismatch"; - left++; - right++; - } - - dx_compose_free(field); - return 0; -} - -static char *vector1 = - "\x00\x53\x71" // delivery annotations - "\xd1\x00\x00\x00\x3d\x00\x00\x00\x04" // map32 with two item pairs - "\xa1\x06key001" // str8-utf8 - "\x52\x0a" // smalluint - "\xa1\x06key002" // str8-utf8 - "\xd0\x00\x00\x00\x22\x00\x00\x00\x04" // list32 with four items - "\xa1\x05item1" // str8-utf8 - "\xa1\x05item2" // str8-utf8 - "\xa1\x05item3" // str8-utf8 - "\xd0\x00\x00\x00\x04\x00\x00\x00\x00" // list32 empty - ; - -static int vector1_length = 69; - -static char *test_compose_nested_composites(void *context) -{ - dx_composed_field_t *field = dx_compose(DX_PERFORMATIVE_DELIVERY_ANNOTATIONS, 0); - - dx_compose_start_map(field); - - dx_compose_insert_string(field, "key001"); - dx_compose_insert_uint(field, 10); - - dx_compose_insert_string(field, "key002"); - dx_compose_start_list(field); - - dx_compose_insert_string(field, "item1"); - dx_compose_insert_string(field, "item2"); - dx_compose_insert_string(field, "item3"); - - dx_compose_start_list(field); - dx_compose_end_list(field); - - dx_compose_end_list(field); - dx_compose_end_map(field); - - dx_buffer_t *buf = DEQ_HEAD(field->buffers); - - if (dx_buffer_size(buf) != vector1_length) return "Incorrect Length of Buffer"; - - char *left = vector1; - char *right = (char*) dx_buffer_base(buf); - int idx; - - for (idx = 0; idx < vector1_length; idx++) { - if (*left != *right) return "Pattern Mismatch"; - left++; - right++; - } - - dx_compose_free(field); - return 0; -} - -static char *vector2 = - "\x00\x53\x73" // properties - "\xd0\x00\x00\x00\x83\x00\x00\x00\x1c" // list32 with 28 items - "\x40" // null - "\x42" // false - "\x41" // true - "\x43" // uint0 - "\x52\x01" // smalluint - "\x52\xff" // smalluint - "\x70\x00\x00\x01\x00" // uint - "\x70\x10\x00\x00\x00" // uint - "\x44" // ulong0 - "\x53\x01" // smallulong - "\x53\xff" // smallulong - "\x80\x00\x00\x00\x00\x00\x00\x01\x00" // ulong - "\x80\x00\x00\x00\x00\x20\x00\x00\x00" // ulong - "\x54\x00" // smallint - "\x54\x01" // smallint - "\x54\xff" // smallint - "\x71\x00\x00\x00\xff" // int - "\x71\x00\x00\x01\x00" // int - "\x55\x00" // smalllong - "\x55\x01" // smalllong - "\x55\xff" // smalllong - "\x81\x00\x00\x00\x00\x00\x00\x00\xff" // long - "\x81\x00\x00\x00\x00\x00\x00\x01\x00" // long - "\x83\x00\x11\x22\x33\x44\x55\x66\x77" // timestamp - "\x98\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" // uuid - "\xa0\x02\x00\x11" // vbin8 - "\xa1\x06string" // str8-utf8 - "\xa3\x06symbol" // sym8 - ; - -static int vector2_length = 139; - -static char *test_compose_scalars(void *context) -{ - dx_composed_field_t *field = dx_compose(DX_PERFORMATIVE_PROPERTIES, 0); - - dx_compose_start_list(field); - - dx_compose_insert_null(field); - - dx_compose_insert_bool(field, 0); - dx_compose_insert_bool(field, 1); - - dx_compose_insert_uint(field, 0); - dx_compose_insert_uint(field, 1); - dx_compose_insert_uint(field, 255); - dx_compose_insert_uint(field, 256); - dx_compose_insert_uint(field, 0x10000000); - - dx_compose_insert_ulong(field, 0); - dx_compose_insert_ulong(field, 1); - dx_compose_insert_ulong(field, 255); - dx_compose_insert_ulong(field, 256); - dx_compose_insert_ulong(field, 0x20000000); - - dx_compose_insert_int(field, 0); - dx_compose_insert_int(field, 1); - dx_compose_insert_int(field, -1); - dx_compose_insert_int(field, 255); - dx_compose_insert_int(field, 256); - - dx_compose_insert_long(field, 0); - dx_compose_insert_long(field, 1); - dx_compose_insert_long(field, -1); - dx_compose_insert_long(field, 255); - dx_compose_insert_long(field, 256); - - dx_compose_insert_timestamp(field, 0x0011223344556677); - dx_compose_insert_uuid(field, (uint8_t*) "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00"); - dx_compose_insert_binary(field, (uint8_t*) "\x00\x11", 2); - dx_compose_insert_string(field, "string"); - dx_compose_insert_symbol(field, "symbol"); - - dx_compose_end_list(field); - - dx_buffer_t *buf = DEQ_HEAD(field->buffers); - - if (dx_buffer_size(buf) != vector2_length) return "Incorrect Length of Buffer"; - - char *left = vector2; - char *right = (char*) dx_buffer_base(buf); - int idx; - - for (idx = 0; idx < vector2_length; idx++) { - if (*left != *right) return "Pattern Mismatch"; - left++; - right++; - } - - dx_compose_free(field); - return 0; -} - - -int compose_tests() -{ - int result = 0; - dx_log_set_mask(LOG_NONE); - - TEST_CASE(test_compose_list_of_maps, 0); - TEST_CASE(test_compose_nested_composites, 0); - TEST_CASE(test_compose_scalars, 0); - - return result; -} - diff --git a/extras/dispatch/tests/config-1/A.conf b/extras/dispatch/tests/config-1/A.conf deleted file mode 100644 index 308d86473c..0000000000 --- a/extras/dispatch/tests/config-1/A.conf +++ /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 -## - - -## -## Container section - Configures the general operation of the AMQP container. -## -container { - ## - ## worker-threads - The number of threads that will be created to - ## process message traffic and other application work (timers, non-amqp - ## file descriptors, etc.) - ## - ## The number of threads should be related to the number of available - ## processor cores. To fully utilize a quad-core system, set the - ## number of threads to 4. - ## - worker-threads: 4 - - ## - ## container-name - The name of the AMQP container. If not specified, - ## the container name will be set to a value of the container's - ## choosing. The automatically assigned container name is not - ## guaranteed to be persistent across restarts of the container. - ## - container-name: Qpid.Dispatch.Router.A -} - - -## -## Listeners and Connectors -## -listener { - addr: 0.0.0.0 - port: 20000 - sasl-mechanisms: ANONYMOUS -} - diff --git a/extras/dispatch/tests/config-2/A.conf b/extras/dispatch/tests/config-2/A.conf deleted file mode 100644 index a3fb411018..0000000000 --- a/extras/dispatch/tests/config-2/A.conf +++ /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 -## - - -## -## Container section - Configures the general operation of the AMQP container. -## -container { - ## - ## worker-threads - The number of threads that will be created to - ## process message traffic and other application work (timers, non-amqp - ## file descriptors, etc.) - ## - ## The number of threads should be related to the number of available - ## processor cores. To fully utilize a quad-core system, set the - ## number of threads to 4. - ## - worker-threads: 4 - - ## - ## container-name - The name of the AMQP container. If not specified, - ## the container name will be set to a value of the container's - ## choosing. The automatically assigned container name is not - ## guaranteed to be persistent across restarts of the container. - ## - container-name: Qpid.Dispatch.Router.A -} - - -## -## Listeners and Connectors -## -listener { - role: inter-router - addr: 0.0.0.0 - port: 20001 - sasl-mechanisms: ANONYMOUS -} - -router { - mode: interior - router-id: QDR.A -} diff --git a/extras/dispatch/tests/config-2/B.conf b/extras/dispatch/tests/config-2/B.conf deleted file mode 100644 index 0950584c88..0000000000 --- a/extras/dispatch/tests/config-2/B.conf +++ /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 -## - - -## -## Container section - Configures the general operation of the AMQP container. -## -container { - ## - ## worker-threads - The number of threads that will be created to - ## process message traffic and other application work (timers, non-amqp - ## file descriptors, etc.) - ## - ## The number of threads should be related to the number of available - ## processor cores. To fully utilize a quad-core system, set the - ## number of threads to 4. - ## - worker-threads: 4 - - ## - ## container-name - The name of the AMQP container. If not specified, - ## the container name will be set to a value of the container's - ## choosing. The automatically assigned container name is not - ## guaranteed to be persistent across restarts of the container. - ## - container-name: Qpid.Dispatch.Router.B -} - - -## -## Listeners and Connectors -## -listener { - role: inter-router - addr: 0.0.0.0 - port: 20002 - sasl-mechanisms: ANONYMOUS -} - -connector { - label: Router Uplink - role: inter-router - addr: 0.0.0.0 - port: 20001 - sasl-mechanisms: ANONYMOUS -} - -router { - mode: interior - router-id: QDR.B -} diff --git a/extras/dispatch/tests/config-3-linear/A.conf b/extras/dispatch/tests/config-3-linear/A.conf deleted file mode 100644 index 6f0f9abce8..0000000000 --- a/extras/dispatch/tests/config-3-linear/A.conf +++ /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 -## - - -## -## Container section - Configures the general operation of the AMQP container. -## -container { - ## - ## worker-threads - The number of threads that will be created to - ## process message traffic and other application work (timers, non-amqp - ## file descriptors, etc.) - ## - ## The number of threads should be related to the number of available - ## processor cores. To fully utilize a quad-core system, set the - ## number of threads to 4. - ## - worker-threads: 4 - - ## - ## container-name - The name of the AMQP container. If not specified, - ## the container name will be set to a value of the container's - ## choosing. The automatically assigned container name is not - ## guaranteed to be persistent across restarts of the container. - ## - container-name: QDR.A -} - - -## -## Listeners and Connectors -## -listener { - addr: 0.0.0.0 - port: 20001 - sasl-mechanisms: ANONYMOUS -} - -connector { - label: Router Uplink - role: inter-router - addr: 0.0.0.0 - port: 20002 - sasl-mechanisms: ANONYMOUS -} - -router { - mode: interior - router-id: QDR.A -} - - - diff --git a/extras/dispatch/tests/config-3-linear/B.conf b/extras/dispatch/tests/config-3-linear/B.conf deleted file mode 100644 index 85c146bd58..0000000000 --- a/extras/dispatch/tests/config-3-linear/B.conf +++ /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 -## - - -## -## Container section - Configures the general operation of the AMQP container. -## -container { - ## - ## worker-threads - The number of threads that will be created to - ## process message traffic and other application work (timers, non-amqp - ## file descriptors, etc.) - ## - ## The number of threads should be related to the number of available - ## processor cores. To fully utilize a quad-core system, set the - ## number of threads to 4. - ## - worker-threads: 4 - - ## - ## container-name - The name of the AMQP container. If not specified, - ## the container name will be set to a value of the container's - ## choosing. The automatically assigned container name is not - ## guaranteed to be persistent across restarts of the container. - ## - container-name: QDR.B -} - - -## -## Listeners and Connectors -## -listener { - role: inter-router - addr: 0.0.0.0 - port: 20002 - sasl-mechanisms: ANONYMOUS -} - -connector { - label: Router Uplink - role: inter-router - addr: 0.0.0.0 - port: 20003 - sasl-mechanisms: ANONYMOUS -} - - -router { - mode: interior - router-id: QDR.B -} diff --git a/extras/dispatch/tests/config-3-linear/C.conf b/extras/dispatch/tests/config-3-linear/C.conf deleted file mode 100644 index 17971462bc..0000000000 --- a/extras/dispatch/tests/config-3-linear/C.conf +++ /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 -## - - -## -## Container section - Configures the general operation of the AMQP container. -## -container { - ## - ## worker-threads - The number of threads that will be created to - ## process message traffic and other application work (timers, non-amqp - ## file descriptors, etc.) - ## - ## The number of threads should be related to the number of available - ## processor cores. To fully utilize a quad-core system, set the - ## number of threads to 4. - ## - worker-threads: 4 - - ## - ## container-name - The name of the AMQP container. If not specified, - ## the container name will be set to a value of the container's - ## choosing. The automatically assigned container name is not - ## guaranteed to be persistent across restarts of the container. - ## - container-name: QDR.C -} - - -## -## Listeners and Connectors -## -listener { - role: inter-router - addr: 0.0.0.0 - port: 20003 - sasl-mechanisms: ANONYMOUS -} - - -router { - mode: interior - router-id: QDR.C -} diff --git a/extras/dispatch/tests/config-3-linear/topology.txt b/extras/dispatch/tests/config-3-linear/topology.txt deleted file mode 100644 index 07d6d74008..0000000000 --- a/extras/dispatch/tests/config-3-linear/topology.txt +++ /dev/null @@ -1,12 +0,0 @@ - - - +----------+ +----------+ +----------+ - |QDR.A | |QDR.B | |QDR.C | - |port: | |port: | |port: | - | 20001 |--------->| 20002 |--------->| 20003 | - | | | | | | - | | | | | | - +----------+ +----------+ +----------+ - - * The direction of the arrow shows the direction of the connection setup - Connector --> Listener diff --git a/extras/dispatch/tests/field_test.c b/extras/dispatch/tests/field_test.c deleted file mode 100644 index 77cb6d969f..0000000000 --- a/extras/dispatch/tests/field_test.c +++ /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. - */ - -#include "test_case.h" -#include <stdio.h> -#include <string.h> -#include <qpid/dispatch/iterator.h> - -#define FAIL_TEXT_SIZE 10000 -static char fail_text[FAIL_TEXT_SIZE]; - -static char* test_view_global_dns(void *context) -{ - dx_field_iterator_t *iter = dx_field_iterator_string("amqp://host/global/sub", ITER_VIEW_ALL); - if (!dx_field_iterator_equal(iter, (unsigned char*) "amqp://host/global/sub")) - return "ITER_VIEW_ALL failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_NO_HOST); - if (!dx_field_iterator_equal(iter, (unsigned char*) "global/sub")) - return "ITER_VIEW_NO_HOST failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_NODE_ID); - if (!dx_field_iterator_equal(iter, (unsigned char*) "global")) - return "ITER_VIEW_NODE_ID failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_NODE_SPECIFIC); - if (!dx_field_iterator_equal(iter, (unsigned char*) "sub")) - return "ITER_VIEW_NODE_SPECIFIC failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); - if (!dx_field_iterator_equal(iter, (unsigned char*) "Mglobal/sub")) - return "ITER_VIEW_ADDRESS_HASH failed"; - - return 0; -} - - -static char* test_view_global_non_dns(void *context) -{ - dx_field_iterator_t *iter = dx_field_iterator_string("amqp:/global/sub", ITER_VIEW_ALL); - if (!dx_field_iterator_equal(iter, (unsigned char*) "amqp:/global/sub")) - return "ITER_VIEW_ALL failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_NO_HOST); - if (!dx_field_iterator_equal(iter, (unsigned char*) "global/sub")) - return "ITER_VIEW_NO_HOST failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_NODE_ID); - if (!dx_field_iterator_equal(iter, (unsigned char*) "global")) - return "ITER_VIEW_NODE_ID failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_NODE_SPECIFIC); - if (!dx_field_iterator_equal(iter, (unsigned char*) "sub")) - return "ITER_VIEW_NODE_SPECIFIC failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); - if (!dx_field_iterator_equal(iter, (unsigned char*) "Mglobal/sub")) - return "ITER_VIEW_ADDRESS_HASH failed"; - - return 0; -} - - -static char* test_view_global_no_host(void *context) -{ - dx_field_iterator_t *iter = dx_field_iterator_string("global/sub", ITER_VIEW_ALL); - if (!dx_field_iterator_equal(iter, (unsigned char*) "global/sub")) - return "ITER_VIEW_ALL failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_NO_HOST); - if (!dx_field_iterator_equal(iter, (unsigned char*) "global/sub")) - return "ITER_VIEW_NO_HOST failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_NODE_ID); - if (!dx_field_iterator_equal(iter, (unsigned char*) "global")) - return "ITER_VIEW_NODE_ID failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_NODE_SPECIFIC); - if (!dx_field_iterator_equal(iter, (unsigned char*) "sub")) - return "ITER_VIEW_NODE_SPECIFIC failed"; - - dx_field_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); - if (!dx_field_iterator_equal(iter, (unsigned char*) "Mglobal/sub")) - return "ITER_VIEW_ADDRESS_HASH failed"; - - return 0; -} - - -static char* test_view_address_hash(void *context) -{ - struct {const char *addr; const char *view;} cases[] = { - {"amqp:/_local/my-addr/sub", "Lmy-addr/sub"}, - {"amqp:/_local/my-addr", "Lmy-addr"}, - {"amqp:/_topo/area/router/local/sub", "Aarea"}, - {"amqp:/_topo/my-area/router/local/sub", "Rrouter"}, - {"amqp:/_topo/my-area/my-router/local/sub", "Llocal/sub"}, - {"amqp:/_topo/area/all/local/sub", "Aarea"}, - {"amqp:/_topo/my-area/all/local/sub", "Llocal/sub"}, - {"amqp:/_topo/all/all/local/sub", "Llocal/sub"}, - {"amqp://host:port/_local/my-addr", "Lmy-addr"}, - {"_topo/area/router/my-addr", "Aarea"}, - {"_topo/my-area/router/my-addr", "Rrouter"}, - {"_topo/my-area/my-router/my-addr", "Lmy-addr"}, - {"_topo/my-area/router", "Rrouter"}, - {0, 0} - }; - int idx; - - for (idx = 0; cases[idx].addr; idx++) { - dx_field_iterator_t *iter = dx_field_iterator_string(cases[idx].addr, ITER_VIEW_ADDRESS_HASH); - if (!dx_field_iterator_equal(iter, (unsigned char*) cases[idx].view)) { - char *got = (char*) dx_field_iterator_copy(iter); - snprintf(fail_text, FAIL_TEXT_SIZE, "Addr '%s' failed. Expected '%s', got '%s'", - cases[idx].addr, cases[idx].view, got); - return fail_text; - } - } - - return 0; -} - - -static char* test_view_node_hash(void *context) -{ - struct {const char *addr; const char *view;} cases[] = { - {"area/router", "Aarea"}, - {"my-area/router", "Rrouter"}, - {"my-area/my-router", "Rmy-router"}, - {0, 0} - }; - int idx; - - for (idx = 0; cases[idx].addr; idx++) { - dx_field_iterator_t *iter = dx_field_iterator_string(cases[idx].addr, ITER_VIEW_NODE_HASH); - if (!dx_field_iterator_equal(iter, (unsigned char*) cases[idx].view)) { - char *got = (char*) dx_field_iterator_copy(iter); - snprintf(fail_text, FAIL_TEXT_SIZE, "Addr '%s' failed. Expected '%s', got '%s'", - cases[idx].addr, cases[idx].view, got); - return fail_text; - } - } - - return 0; -} - - -int field_tests(void) -{ - int result = 0; - - dx_field_iterator_set_address("my-area", "my-router"); - - TEST_CASE(test_view_global_dns, 0); - TEST_CASE(test_view_global_non_dns, 0); - TEST_CASE(test_view_global_no_host, 0); - TEST_CASE(test_view_address_hash, 0); - TEST_CASE(test_view_node_hash, 0); - - return result; -} - diff --git a/extras/dispatch/tests/message_test.c b/extras/dispatch/tests/message_test.c deleted file mode 100644 index 59f4e444dc..0000000000 --- a/extras/dispatch/tests/message_test.c +++ /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 "test_case.h" -#include <stdio.h> -#include <string.h> -#include "message_private.h" -#include <qpid/dispatch/iterator.h> -#include <proton/message.h> - -static char buffer[10000]; - -static size_t flatten_bufs(dx_message_content_t *content) -{ - char *cursor = buffer; - dx_buffer_t *buf = DEQ_HEAD(content->buffers); - - while (buf) { - memcpy(cursor, dx_buffer_base(buf), dx_buffer_size(buf)); - cursor += dx_buffer_size(buf); - buf = buf->next; - } - - return (size_t) (cursor - buffer); -} - - -static void set_content(dx_message_content_t *content, size_t len) -{ - char *cursor = buffer; - dx_buffer_t *buf; - - while (len > (size_t) (cursor - buffer)) { - buf = dx_buffer(); - size_t segment = dx_buffer_capacity(buf); - size_t remaining = len - (size_t) (cursor - buffer); - if (segment > remaining) - segment = remaining; - memcpy(dx_buffer_base(buf), cursor, segment); - cursor += segment; - dx_buffer_insert(buf, segment); - DEQ_INSERT_TAIL(content->buffers, buf); - } -} - - -static char* test_send_to_messenger(void *context) -{ - dx_message_t *msg = dx_message(); - dx_message_content_t *content = MSG_CONTENT(msg); - - dx_message_compose_1(msg, "test_addr_0", 0); - dx_buffer_t *buf = DEQ_HEAD(content->buffers); - if (buf == 0) return "Expected a buffer in the test message"; - - pn_message_t *pn_msg = pn_message(); - size_t len = flatten_bufs(content); - int result = pn_message_decode(pn_msg, buffer, len); - if (result != 0) return "Error in pn_message_decode"; - - if (strcmp(pn_message_get_address(pn_msg), "test_addr_0") != 0) - return "Address mismatch in received message"; - - pn_message_free(pn_msg); - dx_message_free(msg); - - return 0; -} - - -static char* test_receive_from_messenger(void *context) -{ - pn_message_t *pn_msg = pn_message(); - pn_message_set_address(pn_msg, "test_addr_1"); - - size_t size = 10000; - int result = pn_message_encode(pn_msg, buffer, &size); - if (result != 0) return "Error in pn_message_encode"; - - dx_message_t *msg = dx_message(); - dx_message_content_t *content = MSG_CONTENT(msg); - - set_content(content, size); - - int valid = dx_message_check(msg, DX_DEPTH_ALL); - if (!valid) return "dx_message_check returns 'invalid'"; - - dx_field_iterator_t *iter = dx_message_field_iterator(msg, DX_FIELD_TO); - if (iter == 0) return "Expected an iterator for the 'to' field"; - - if (!dx_field_iterator_equal(iter, (unsigned char*) "test_addr_1")) - return "Mismatched 'to' field contents"; - - ssize_t test_len = dx_message_field_length(msg, DX_FIELD_TO); - if (test_len != 11) return "Incorrect field length"; - - char test_field[15]; - test_len = dx_message_field_copy(msg, DX_FIELD_TO, test_field); - if (test_len != 11) return "Incorrect length returned from field_copy"; - test_field[test_len] = '\0'; - if (strcmp(test_field, "test_addr_1") != 0) - return "Incorrect field content returned from field_copy"; - - pn_message_free(pn_msg); - dx_message_free(msg); - - return 0; -} - - -static char* test_insufficient_check_depth(void *context) -{ - pn_message_t *pn_msg = pn_message(); - pn_message_set_address(pn_msg, "test_addr_2"); - - size_t size = 10000; - int result = pn_message_encode(pn_msg, buffer, &size); - if (result != 0) return "Error in pn_message_encode"; - - dx_message_t *msg = dx_message(); - dx_message_content_t *content = MSG_CONTENT(msg); - - set_content(content, size); - - int valid = dx_message_check(msg, DX_DEPTH_DELIVERY_ANNOTATIONS); - if (!valid) return "dx_message_check returns 'invalid'"; - - dx_field_iterator_t *iter = dx_message_field_iterator(msg, DX_FIELD_TO); - if (iter) return "Expected no iterator for the 'to' field"; - - dx_message_free(msg); - - return 0; -} - - -static char* test_check_multiple(void *context) -{ - pn_message_t *pn_msg = pn_message(); - pn_message_set_address(pn_msg, "test_addr_2"); - - size_t size = 10000; - int result = pn_message_encode(pn_msg, buffer, &size); - if (result != 0) return "Error in pn_message_encode"; - - dx_message_t *msg = dx_message(); - dx_message_content_t *content = MSG_CONTENT(msg); - - set_content(content, size); - - int valid = dx_message_check(msg, DX_DEPTH_DELIVERY_ANNOTATIONS); - if (!valid) return "dx_message_check returns 'invalid' for DELIVERY_ANNOTATIONS"; - - valid = dx_message_check(msg, DX_DEPTH_BODY); - if (!valid) return "dx_message_check returns 'invalid' for BODY"; - - valid = dx_message_check(msg, DX_DEPTH_PROPERTIES); - if (!valid) return "dx_message_check returns 'invalid' for PROPERTIES"; - - dx_message_free(msg); - - return 0; -} - - -int message_tests(void) -{ - int result = 0; - - TEST_CASE(test_send_to_messenger, 0); - TEST_CASE(test_receive_from_messenger, 0); - TEST_CASE(test_insufficient_check_depth, 0); - TEST_CASE(test_check_multiple, 0); - - return result; -} - diff --git a/extras/dispatch/tests/parse_test.c b/extras/dispatch/tests/parse_test.c deleted file mode 100644 index 124ba1c0d4..0000000000 --- a/extras/dispatch/tests/parse_test.c +++ /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. - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <assert.h> -#include <string.h> -#include <inttypes.h> -#include "test_case.h" -#include <qpid/dispatch.h> - -struct fs_vector_t { - const char *data; - int length; - uint8_t expected_tag; - int check_uint; - int check_ulong; - int check_int; - int check_long; - uint64_t expected_ulong; - int64_t expected_long; -} fs_vectors[] = { -{"\x40", 1, DX_AMQP_NULL, 0, 0, 0, 0, 0, 0}, // 0 -{"\x41", 1, DX_AMQP_TRUE, 1, 0, 0, 0, 1, 0}, // 1 -{"\x42", 1, DX_AMQP_FALSE, 1, 0, 0, 0, 0, 0}, // 2 -{"\x56\x00", 2, DX_AMQP_BOOLEAN, 1, 0, 0, 0, 0, 0}, // 3 -{"\x56\x01", 2, DX_AMQP_BOOLEAN, 1, 0, 0, 0, 1, 0}, // 4 -{"\x50\x45", 2, DX_AMQP_UBYTE, 1, 0, 0, 0, 0x45, 0}, // 5 -{"\x60\x02\x04", 3, DX_AMQP_USHORT, 1, 0, 0, 0, 0x0204, 0}, // 6 -{"\x70\x01\x02\x03\x04", 5, DX_AMQP_UINT, 1, 0, 0, 0, 0x01020304, 0}, // 7 -{"\x52\x06", 2, DX_AMQP_SMALLUINT, 1, 0, 0, 0, 6, 0}, // 8 -{"\x43", 1, DX_AMQP_UINT0, 1, 0, 0, 0, 0, 0}, // 9 -{"\x80\x01\x02\x03\x04\x05\x06\x07\x08", - 9, DX_AMQP_ULONG, 0, 1, 0, 0, 0x0102030405060708, 0}, // 10 -{"\x53\x08", 2, DX_AMQP_SMALLULONG, 0, 1, 0, 0, 0x08, 0}, // 11 -{"\x44", 1, DX_AMQP_ULONG0, 0, 1, 0, 0, 0, 0}, // 12 -{"\x71\x01\x02\x03\x04", 5, DX_AMQP_INT, 0, 0, 1, 0, 0, 0x01020304}, // 13 -{"\x54\x02", 2, DX_AMQP_SMALLINT, 0, 0, 1, 0, 0, 2}, // 14 -{"\x81\x01\x02\x03\x04\x05\x06\x07\x08", - 9, DX_AMQP_LONG, 0, 0, 0, 1, 0, 0x0102030405060708}, // 15 -{"\x55\x08", 2, DX_AMQP_SMALLLONG, 0, 0, 0, 1, 0, 0x08}, // 16 -{0, 0, 0, 0, 0} -}; - - -static char *test_parser_fixed_scalars(void *context) -{ - int idx = 0; - static char error[1024]; - - while (fs_vectors[idx].data) { - dx_field_iterator_t *field = dx_field_iterator_binary(fs_vectors[idx].data, - fs_vectors[idx].length, - ITER_VIEW_ALL); - dx_parsed_field_t *parsed = dx_parse(field); - if (!dx_parse_ok(parsed)) return "Unexpected Parse Error"; - if (dx_parse_tag(parsed) != fs_vectors[idx].expected_tag) { - sprintf(error, "(%d) Tag: Expected %02x, Got %02x", idx, - fs_vectors[idx].expected_tag, dx_parse_tag(parsed)); - return error; - } - if (fs_vectors[idx].check_uint && - dx_parse_as_uint(parsed) != fs_vectors[idx].expected_ulong) { - sprintf(error, "(%d) UINT: Expected %"PRIx64", Got %"PRIx32, idx, - fs_vectors[idx].expected_ulong, dx_parse_as_uint(parsed)); - return error; - } - if (fs_vectors[idx].check_ulong && - dx_parse_as_ulong(parsed) != fs_vectors[idx].expected_ulong) { - sprintf(error, "(%d) ULONG: Expected %"PRIx64", Got %"PRIx64, idx, - fs_vectors[idx].expected_ulong, dx_parse_as_ulong(parsed)); - return error; - } - if (fs_vectors[idx].check_int && - dx_parse_as_int(parsed) != fs_vectors[idx].expected_long) { - sprintf(error, "(%d) INT: Expected %"PRIx64", Got %"PRIx32, idx, - fs_vectors[idx].expected_long, dx_parse_as_int(parsed)); - return error; - } - if (fs_vectors[idx].check_long && - dx_parse_as_long(parsed) != fs_vectors[idx].expected_long) { - sprintf(error, "(%d) LONG: Expected %"PRIx64", Got %"PRIx64, idx, - fs_vectors[idx].expected_long, dx_parse_as_long(parsed)); - return error; - } - idx++; - - dx_field_iterator_free(field); - dx_parse_free(parsed); - } - - return 0; -} - - -struct err_vector_t { - const char *data; - int length; - const char *expected_error; -} err_vectors[] = { -{"", 0, "Insufficient Data to Determine Tag"}, // 0 -{"\x21", 1, "Invalid Tag - No Length Information"}, // 1 -//{"\x56", 1, "w"}, // 2 -{"\xa0", 1, "Insufficient Data to Determine Length"}, // 3 -{"\xb0", 1, "Insufficient Data to Determine Length"}, // 4 -{"\xb0\x00", 2, "Insufficient Data to Determine Length"}, // 5 -{"\xb0\x00\x00", 3, "Insufficient Data to Determine Length"}, // 6 -{"\xb0\x00\x00\x00", 4, "Insufficient Data to Determine Length"}, // 7 -{"\xc0\x04", 2, "Insufficient Data to Determine Count"}, // 8 -{"\xd0\x00\x00\x00\x00\x00\x00\x00\x01", 9, "Insufficient Length to Determine Count"}, // 9 -{0, 0, 0} -}; - -static char *test_parser_errors(void *context) -{ - int idx = 0; - static char error[1024]; - - while (err_vectors[idx].data) { - dx_field_iterator_t *field = dx_field_iterator_binary(err_vectors[idx].data, - err_vectors[idx].length, - ITER_VIEW_ALL); - dx_parsed_field_t *parsed = dx_parse(field); - if (dx_parse_ok(parsed)) { - sprintf(error, "(%d) Unexpected Parse Success", idx); - return error; - } - if (strcmp(dx_parse_error(parsed), err_vectors[idx].expected_error) != 0) { - sprintf(error, "(%d) Error: Expected %s, Got %s", idx, - err_vectors[idx].expected_error, dx_parse_error(parsed)); - return error; - } - idx++; - } - - return 0; -} - - -int parse_tests() -{ - int result = 0; - dx_log_set_mask(LOG_NONE); - - TEST_CASE(test_parser_fixed_scalars, 0); - TEST_CASE(test_parser_errors, 0); - - return result; -} - diff --git a/extras/dispatch/tests/router_engine_test.py b/extras/dispatch/tests/router_engine_test.py deleted file mode 100644 index e25ce35d22..0000000000 --- a/extras/dispatch/tests/router_engine_test.py +++ /dev/null @@ -1,651 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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 unittest -from qpid.dispatch.router.router_engine import NeighborEngine, PathEngine, Configuration, NodeTracker -from qpid.dispatch.router.data import LinkState, MessageHELLO - -class Adapter(object): - def __init__(self, domain): - self._domain = domain - - def log(self, level, text): - print "Adapter.log(%d): domain=%s, text=%s" % (level, self._domain, text) - - def send(self, dest, opcode, body): - print "Adapter.send: domain=%s, dest=%s, opcode=%s, body=%s" % (self._domain, dest, opcode, body) - - def remote_bind(self, subject, peer): - print "Adapter.remote_bind: subject=%s, peer=%s" % (subject, peer) - - def remote_unbind(self, subject, peer): - print "Adapter.remote_unbind: subject=%s, peer=%s" % (subject, peer) - - def node_updated(self, address, reachable, neighbor, link_bit, router_bit): - print "Adapter.node_updated: address=%s, reachable=%r, neighbor=%r, link_bit=%d, router_bit=%d" % \ - (address, reachable, neighbor, link_bit, router_bit) - - -class DataTest(unittest.TestCase): - def test_link_state(self): - ls = LinkState(None, 'R1', 'area', 1, ['R2', 'R3']) - self.assertEqual(ls.id, 'R1') - self.assertEqual(ls.area, 'area') - self.assertEqual(ls.ls_seq, 1) - self.assertEqual(ls.peers, ['R2', 'R3']) - ls.bump_sequence() - self.assertEqual(ls.id, 'R1') - self.assertEqual(ls.area, 'area') - self.assertEqual(ls.ls_seq, 2) - self.assertEqual(ls.peers, ['R2', 'R3']) - - result = ls.add_peer('R4') - self.assertTrue(result) - self.assertEqual(ls.peers, ['R2', 'R3', 'R4']) - result = ls.add_peer('R2') - self.assertFalse(result) - self.assertEqual(ls.peers, ['R2', 'R3', 'R4']) - - result = ls.del_peer('R3') - self.assertTrue(result) - self.assertEqual(ls.peers, ['R2', 'R4']) - result = ls.del_peer('R5') - self.assertFalse(result) - self.assertEqual(ls.peers, ['R2', 'R4']) - - encoded = ls.to_dict() - new_ls = LinkState(encoded) - self.assertEqual(new_ls.id, 'R1') - self.assertEqual(new_ls.area, 'area') - self.assertEqual(new_ls.ls_seq, 2) - self.assertEqual(new_ls.peers, ['R2', 'R4']) - - - def test_hello_message(self): - msg1 = MessageHELLO(None, 'R1', 'area', ['R2', 'R3', 'R4']) - self.assertEqual(msg1.get_opcode(), "HELLO") - self.assertEqual(msg1.id, 'R1') - self.assertEqual(msg1.area, 'area') - self.assertEqual(msg1.seen_peers, ['R2', 'R3', 'R4']) - encoded = msg1.to_dict() - msg2 = MessageHELLO(encoded) - self.assertEqual(msg2.get_opcode(), "HELLO") - self.assertEqual(msg2.id, 'R1') - self.assertEqual(msg2.area, 'area') - self.assertEqual(msg2.seen_peers, ['R2', 'R3', 'R4']) - self.assertTrue(msg2.is_seen('R3')) - self.assertFalse(msg2.is_seen('R9')) - - -class NodeTrackerTest(unittest.TestCase): - def log(self, level, text): - pass - - def add_neighbor_router(self, address, router_bit, link_bit): - self.address = address - self.router_bit = router_bit - self.link_bit = link_bit - self.calls += 1 - - def del_neighbor_router(self, router_bit): - self.address = None - self.router_bit = router_bit - self.link_bit = None - self.calls += 1 - - def add_remote_router(self, address, router_bit): - self.address = address - self.router_bit = router_bit - self.link_bit = None - self.calls += 1 - - def del_remote_router(self, router_bit): - self.address = None - self.router_bit = router_bit - self.link_bit = None - self.calls += 1 - - def reset(self): - self.address = None - self.router_bit = None - self.link_bit = None - self.area = "area" - self.calls = 0 - - def test_node_tracker_limits(self): - tracker = NodeTracker(self, 5) - - self.reset() - tracker.new_neighbor('A', 1) - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertEqual(self.link_bit, 1) - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('B', 5) - self.assertEqual(self.address, 'amqp:/_topo/area/B') - self.assertEqual(self.link_bit, 5) - self.assertEqual(self.router_bit, 2) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('C', 6) - self.assertEqual(self.address, 'amqp:/_topo/area/C') - self.assertEqual(self.link_bit, 6) - self.assertEqual(self.router_bit, 3) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('D', 7) - self.assertEqual(self.address, 'amqp:/_topo/area/D') - self.assertEqual(self.link_bit, 7) - self.assertEqual(self.router_bit, 4) - self.assertEqual(self.calls, 1) - - self.reset() - try: - tracker.new_neighbor('E', 9) - AssertFalse("We shouldn't be here") - except: - pass - - self.reset() - tracker.lost_neighbor('C') - self.assertEqual(self.router_bit, 3) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('E', 9) - self.assertEqual(self.address, 'amqp:/_topo/area/E') - self.assertEqual(self.link_bit, 9) - self.assertEqual(self.router_bit, 3) - self.assertEqual(self.calls, 1) - - - def test_node_tracker_remote_neighbor(self): - tracker = NodeTracker(self, 5) - - self.reset() - tracker.new_node('A') - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertFalse(self.link_bit) - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_neighbor('A', 3) - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertEqual(self.link_bit, 3) - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 2) - - self.reset() - tracker.lost_node('A') - self.assertFalse(self.address) - self.assertFalse(self.link_bit) - self.assertFalse(self.router_bit) - self.assertEqual(self.calls, 0) - - self.reset() - tracker.lost_neighbor('A') - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - - - def test_node_tracker_neighbor_remote(self): - tracker = NodeTracker(self, 5) - - self.reset() - tracker.new_neighbor('A', 3) - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertEqual(self.link_bit, 3) - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - - self.reset() - tracker.new_node('A') - self.assertFalse(self.address) - self.assertFalse(self.link_bit) - self.assertFalse(self.router_bit) - self.assertEqual(self.calls, 0) - - self.reset() - tracker.lost_neighbor('A') - self.assertEqual(self.address, 'amqp:/_topo/area/A') - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 2) - - self.reset() - tracker.lost_node('A') - self.assertEqual(self.router_bit, 1) - self.assertEqual(self.calls, 1) - - -class NeighborTest(unittest.TestCase): - def log(self, level, text): - pass - - def send(self, dest, msg): - self.sent.append((dest, msg)) - - def local_link_state_changed(self, link_state): - self.local_link_state = link_state - - def new_neighbor(self, rid, lbit): - self.neighbors[rid] = None - - def lost_neighbor(self, rid): - self.neighbors.pop(rid) - - def setUp(self): - self.sent = [] - self.local_link_state = None - self.id = "R1" - self.area = "area" - self.config = Configuration() - self.neighbors = {} - - def test_hello_sent(self): - self.sent = [] - self.local_link_state = None - self.engine = NeighborEngine(self) - self.engine.tick(0.5) - self.assertEqual(self.sent, []) - self.engine.tick(1.5) - self.assertEqual(len(self.sent), 1) - dest, msg = self.sent.pop(0) - self.assertEqual(dest, "amqp:/_local/qdxhello") - self.assertEqual(msg.get_opcode(), "HELLO") - self.assertEqual(msg.id, self.id) - self.assertEqual(msg.area, self.area) - self.assertEqual(msg.seen_peers, []) - self.assertEqual(self.local_link_state, None) - - def test_sees_peer(self): - self.sent = [] - self.local_link_state = None - self.engine = NeighborEngine(self) - self.engine.handle_hello(MessageHELLO(None, 'R2', 'area', []), 2.0, 0) - self.engine.tick(5.0) - self.assertEqual(len(self.sent), 1) - dest, msg = self.sent.pop(0) - self.assertEqual(msg.seen_peers, ['R2']) - - def test_establish_peer(self): - self.sent = [] - self.local_link_state = None - self.engine = NeighborEngine(self) - self.engine.handle_hello(MessageHELLO(None, 'R2', 'area', ['R1']), 0.5, 0) - self.engine.tick(1.0) - self.engine.tick(2.0) - self.engine.tick(3.0) - self.assertEqual(self.local_link_state.id, 'R1') - self.assertEqual(self.local_link_state.area, 'area') - self.assertEqual(self.local_link_state.ls_seq, 1) - self.assertEqual(self.local_link_state.peers, ['R2']) - - def test_establish_multiple_peers(self): - self.sent = [] - self.local_link_state = None - self.engine = NeighborEngine(self) - self.engine.handle_hello(MessageHELLO(None, 'R2', 'area', ['R1']), 0.5, 0) - self.engine.tick(1.0) - self.engine.handle_hello(MessageHELLO(None, 'R3', 'area', ['R1', 'R2']), 1.5, 0) - self.engine.tick(2.0) - self.engine.handle_hello(MessageHELLO(None, 'R4', 'area', ['R1']), 2.5, 0) - self.engine.handle_hello(MessageHELLO(None, 'R5', 'area', ['R2']), 2.5, 0) - self.engine.handle_hello(MessageHELLO(None, 'R6', 'area', ['R1']), 2.5, 0) - self.engine.tick(3.0) - self.assertEqual(self.local_link_state.id, 'R1') - self.assertEqual(self.local_link_state.area, 'area') - self.assertEqual(self.local_link_state.ls_seq, 3) - self.local_link_state.peers.sort() - self.assertEqual(self.local_link_state.peers, ['R2', 'R3', 'R4', 'R6']) - - def test_timeout_peer(self): - self.sent = [] - self.local_link_state = None - self.engine = NeighborEngine(self) - self.engine.handle_hello(MessageHELLO(None, 'R2', 'area', ['R3', 'R1']), 2.0, 0) - self.engine.tick(5.0) - self.engine.tick(17.1) - self.assertEqual(self.local_link_state.id, 'R1') - self.assertEqual(self.local_link_state.area, 'area') - self.assertEqual(self.local_link_state.ls_seq, 2) - self.assertEqual(self.local_link_state.peers, []) - - -class PathTest(unittest.TestCase): - def setUp(self): - self.id = 'R1' - self.area = 'area' - self.next_hops = None - self.valid_origins = None - self.engine = PathEngine(self) - - def log(self, level, text): - pass - - def next_hops_changed(self, nh): - self.next_hops = nh - - def valid_origins_changed(self, vo): - self.valid_origins = vo - - def test_topology1(self): - """ - - +====+ +----+ +----+ - | R1 |------| R2 |------| R3 | - +====+ +----+ +----+ - - """ - collection = { 'R1': LinkState(None, 'R1', 'area', 1, ['R2']), - 'R2': LinkState(None, 'R2', 'area', 1, ['R1', 'R3']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R2']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 2) - self.assertEqual(self.next_hops['R2'], 'R2') - self.assertEqual(self.next_hops['R3'], 'R2') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.assertEqual(self.valid_origins['R2'], []) - self.assertEqual(self.valid_origins['R3'], []) - - def test_topology2(self): - """ - - +====+ +----+ +----+ - | R1 |------| R2 |------| R4 | - +====+ +----+ +----+ - | | - +----+ +----+ +----+ - | R3 |------| R5 |------| R6 | - +----+ +----+ +----+ - - """ - collection = { 'R1': LinkState(None, 'R1', 'area', 1, ['R2']), - 'R2': LinkState(None, 'R2', 'area', 1, ['R1', 'R3', 'R4']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R2', 'R5']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R2', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R3', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 5) - self.assertEqual(self.next_hops['R2'], 'R2') - self.assertEqual(self.next_hops['R3'], 'R2') - self.assertEqual(self.next_hops['R4'], 'R2') - self.assertEqual(self.next_hops['R5'], 'R2') - self.assertEqual(self.next_hops['R6'], 'R2') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.assertEqual(self.valid_origins['R2'], []) - self.assertEqual(self.valid_origins['R3'], []) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], []) - self.assertEqual(self.valid_origins['R6'], []) - - def test_topology3(self): - """ - - +----+ +----+ +----+ - | R2 |------| R3 |------| R4 | - +----+ +----+ +----+ - | | - +====+ +----+ +----+ - | R1 |------| R5 |------| R6 | - +====+ +----+ +----+ - - """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 5) - self.assertEqual(self.next_hops['R2'], 'R3') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) - - def test_topology4(self): - """ - - +----+ +----+ +----+ - | R2 |------| R3 |------| R4 | - +----+ +----+ +----+ - | | - +====+ +----+ +----+ - | R1 |------| R5 |------| R6 |------ R7 (no ls from R7) - +====+ +----+ +----+ - - """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 6) - self.assertEqual(self.next_hops['R2'], 'R3') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - self.assertEqual(self.next_hops['R7'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.valid_origins['R7'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R7'], ['R2', 'R3']) - - def test_topology5(self): - """ - - +----+ +----+ +----+ - | R2 |------| R3 |------| R4 | - +----+ +----+ +----+ - | | | - | +====+ +----+ +----+ - +--------| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) - +====+ +----+ +----+ - - """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3', 'R1']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5', 'R2']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 6) - self.assertEqual(self.next_hops['R2'], 'R2') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - self.assertEqual(self.next_hops['R7'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.valid_origins['R7'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R7'], ['R2', 'R3']) - - def test_topology5_with_asymmetry1(self): - """ - - +----+ +----+ +----+ - | R2 |------| R3 |------| R4 | - +----+ +----+ +----+ - ^ | | - ^ +====+ +----+ +----+ - +-<-<-<--| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) - +====+ +----+ +----+ - - """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5', 'R2']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 6) - self.assertEqual(self.next_hops['R2'], 'R2') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - self.assertEqual(self.next_hops['R7'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.valid_origins['R7'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R7'], ['R2', 'R3']) - - def test_topology5_with_asymmetry2(self): - """ - - +----+ +----+ +----+ - | R2 |------| R3 |------| R4 | - +----+ +----+ +----+ - v | | - v +====+ +----+ +----+ - +->->->->| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) - +====+ +----+ +----+ - - """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3', 'R1']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4', 'R6']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 6) - self.assertEqual(self.next_hops['R2'], 'R3') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - self.assertEqual(self.next_hops['R6'], 'R5') - self.assertEqual(self.next_hops['R7'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.valid_origins['R6'].sort() - self.valid_origins['R7'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R3'], ['R5', 'R6', 'R7']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R6'], ['R2', 'R3']) - self.assertEqual(self.valid_origins['R7'], ['R2', 'R3']) - - def test_topology5_with_asymmetry3(self): - """ - - +----+ +----+ +----+ - | R2 |------| R3 |------| R4 | - +----+ +----+ +----+ - v | | - v +====+ +----+ +----+ - +->->->->| R1 |------| R5 |<-<-<-| R6 |------ R7 (no ls from R7) - +====+ +----+ +----+ - - """ - collection = { 'R2': LinkState(None, 'R2', 'area', 1, ['R3', 'R1']), - 'R3': LinkState(None, 'R3', 'area', 1, ['R1', 'R2', 'R4']), - 'R4': LinkState(None, 'R4', 'area', 1, ['R3', 'R5']), - 'R1': LinkState(None, 'R1', 'area', 1, ['R3', 'R5']), - 'R5': LinkState(None, 'R5', 'area', 1, ['R1', 'R4']), - 'R6': LinkState(None, 'R6', 'area', 1, ['R5', 'R7']) } - self.engine.ls_collection_changed(collection) - self.engine.tick(1.0) - self.assertEqual(len(self.next_hops), 4) - self.assertEqual(self.next_hops['R2'], 'R3') - self.assertEqual(self.next_hops['R3'], 'R3') - self.assertEqual(self.next_hops['R4'], 'R3') - self.assertEqual(self.next_hops['R5'], 'R5') - - self.valid_origins['R2'].sort() - self.valid_origins['R3'].sort() - self.valid_origins['R4'].sort() - self.valid_origins['R5'].sort() - self.assertEqual(self.valid_origins['R2'], ['R5']) - self.assertEqual(self.valid_origins['R3'], ['R5']) - self.assertEqual(self.valid_origins['R4'], []) - self.assertEqual(self.valid_origins['R5'], ['R2', 'R3']) - - -if __name__ == '__main__': - unittest.main() diff --git a/extras/dispatch/tests/run_unit_tests.c b/extras/dispatch/tests/run_unit_tests.c deleted file mode 100644 index 2cb75169c1..0000000000 --- a/extras/dispatch/tests/run_unit_tests.c +++ /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/dispatch/buffer.h> -#include <stdio.h> - -int tool_tests(); -int timer_tests(); -int alloc_tests(); -int server_tests(); -int parse_tests(); -int compose_tests(); - -int main(int argc, char** argv) -{ - if (argc != 2) { - fprintf(stderr, "usage: %s <config-file>\n", argv[0]); - exit(1); - } - - int result = 0; - result += tool_tests(); - result += timer_tests(); - result += alloc_tests(); - result += server_tests(argv[1]); - result += parse_tests(0); - result += compose_tests(0); - return result; -} - diff --git a/extras/dispatch/tests/run_unit_tests_size.c b/extras/dispatch/tests/run_unit_tests_size.c deleted file mode 100644 index 1c6a78c38a..0000000000 --- a/extras/dispatch/tests/run_unit_tests_size.c +++ /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/dispatch/buffer.h> -#include "alloc_private.h" - -int message_tests(); -int field_tests(); - -int main(int argc, char** argv) -{ - ssize_t buffer_size = 512; - - if (argc > 1) { - buffer_size = atoi(argv[1]); - if (buffer_size < 1) - return 1; - } - - dx_alloc_initialize(); - dx_buffer_set_size(buffer_size); - - int result = 0; - result += message_tests(); - result += field_tests(); - return result; -} - diff --git a/extras/dispatch/tests/server_test.c b/extras/dispatch/tests/server_test.c deleted file mode 100644 index 525d8b6a9f..0000000000 --- a/extras/dispatch/tests/server_test.c +++ /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. - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <assert.h> -#include "test_case.h" -#include <qpid/dispatch.h> - -#define THREAD_COUNT 4 -#define OCTET_COUNT 100 - -static const char *config_file; -static dx_dispatch_t *dx; -static sys_mutex_t *test_lock; - -static void *expected_context; -static int call_count; -static int threads_seen[THREAD_COUNT]; -static char stored_error[512]; - -static int write_count; -static int read_count; -static int fd[2]; -static dx_user_fd_t *ufd_write; -static dx_user_fd_t *ufd_read; - - -static void thread_start_handler(void *context, int thread_id) -{ - sys_mutex_lock(test_lock); - if (context != expected_context && !stored_error[0]) - sprintf(stored_error, "Unexpected Context Value: %lx", (long) context); - if (thread_id >= THREAD_COUNT && !stored_error[0]) - sprintf(stored_error, "Thread_ID too large: %d", thread_id); - if (thread_id < 0 && !stored_error[0]) - sprintf(stored_error, "Thread_ID negative: %d", thread_id); - - call_count++; - if (thread_id >= 0 && thread_id < THREAD_COUNT) - threads_seen[thread_id]++; - - if (call_count == THREAD_COUNT) - dx_server_stop(dx); - sys_mutex_unlock(test_lock); -} - - -static void ufd_handler(void *context, dx_user_fd_t *ufd) -{ - long dir = (long) context; - char buffer; - ssize_t len; - static int in_read = 0; - static int in_write = 0; - - if (dir == 0) { // READ - in_read++; - assert(in_read == 1); - if (!dx_user_fd_is_readable(ufd_read)) { - sprintf(stored_error, "Expected Readable"); - dx_server_stop(dx); - } else { - len = read(fd[0], &buffer, 1); - if (len == 1) { - read_count++; - if (read_count == OCTET_COUNT) - dx_server_stop(dx); - } - dx_user_fd_activate_read(ufd_read); - } - in_read--; - } else { // WRITE - in_write++; - assert(in_write == 1); - if (!dx_user_fd_is_writeable(ufd_write)) { - sprintf(stored_error, "Expected Writable"); - dx_server_stop(dx); - } else { - write(fd[1], "X", 1); - - write_count++; - if (write_count < OCTET_COUNT) - dx_user_fd_activate_write(ufd_write); - } - in_write--; - } -} - - -static void fd_test_start(void *context) -{ - dx_user_fd_activate_read(ufd_read); -} - - -static char* test_start_handler(void *context) -{ - int i; - - dx = dx_dispatch(config_file); - - expected_context = (void*) 0x00112233; - stored_error[0] = 0x0; - call_count = 0; - for (i = 0; i < THREAD_COUNT; i++) - threads_seen[i] = 0; - - dx_server_set_start_handler(dx, thread_start_handler, expected_context); - dx_server_run(dx); - dx_dispatch_free(dx); - - if (stored_error[0]) return stored_error; - if (call_count != THREAD_COUNT) return "Incorrect number of thread-start callbacks"; - for (i = 0; i < THREAD_COUNT; i++) - if (threads_seen[i] != 1) return "Incorrect count on one thread ID"; - - return 0; -} - - -static char *test_server_start(void *context) -{ - dx = dx_dispatch(config_file); - dx_server_start(dx); - dx_server_stop(dx); - dx_dispatch_free(dx); - - return 0; -} - - -static char* test_user_fd(void *context) -{ - int res; - dx_timer_t *timer; - - dx = dx_dispatch(config_file); - dx_server_set_user_fd_handler(dx, ufd_handler); - timer = dx_timer(dx, fd_test_start, 0); - dx_timer_schedule(timer, 0); - - stored_error[0] = 0x0; - - res = pipe(fd); // Don't use pipe2 because it's not available on RHEL5 - if (res != 0) return "Error creating pipe2"; - - for (int i = 0; i < 2; i++) { - int flags = fcntl(fd[i], F_GETFL); - flags |= O_NONBLOCK; - if (fcntl(fd[i], F_SETFL, flags) < 0) { - perror("fcntl"); - return "Failed to set socket to non-blocking"; - } - } - - ufd_write = dx_user_fd(dx, fd[1], (void*) 1); - ufd_read = dx_user_fd(dx, fd[0], (void*) 0); - - dx_server_run(dx); - dx_timer_free(timer); - dx_dispatch_free(dx); - close(fd[0]); - close(fd[1]); - - if (stored_error[0]) return stored_error; - if (write_count - OCTET_COUNT > 2) sprintf(stored_error, "Excessively high Write Count: %d", write_count); - if (read_count != OCTET_COUNT) sprintf(stored_error, "Incorrect Read Count: %d", read_count);; - - if (stored_error[0]) return stored_error; - return 0; -} - - -int server_tests(const char *_config_file) -{ - int result = 0; - test_lock = sys_mutex(); - dx_log_set_mask(LOG_NONE); - - config_file = _config_file; - - TEST_CASE(test_server_start, 0); - TEST_CASE(test_start_handler, 0); - TEST_CASE(test_user_fd, 0); - - sys_mutex_free(test_lock); - return result; -} - diff --git a/extras/dispatch/tests/system_tests_one_router.py b/extras/dispatch/tests/system_tests_one_router.py deleted file mode 100644 index 59e2569eff..0000000000 --- a/extras/dispatch/tests/system_tests_one_router.py +++ /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. -# - -import os -import time -import unittest -import subprocess -from proton import Messenger, Message, PENDING, ACCEPTED, REJECTED - -class RouterTest(unittest.TestCase): - - def setUp(self): - if 'CTEST_SOURCE_DIR' not in os.environ: - raise Exception("Environment variable 'CTEST_SOURCE_DIR' not set") - srcdir = os.environ['CTEST_SOURCE_DIR'] - self.router = subprocess.Popen(['../router/dispatch-router', '-c', '%s/config-1/A.conf' % srcdir], - stderr=subprocess.PIPE, stdout=subprocess.PIPE) - time.sleep(1) - - def tearDown(self): - self.router.terminate() - self.router.wait() - - def flush(self, messenger): - while messenger.work(0.1): - pass - - def subscribe(self, messenger, address): - messenger.subscribe(address) - self.flush(messenger) - - - def test_0_discard(self): - addr = "amqp://0.0.0.0:20000/discard/1" - M1 = Messenger() - M1.timeout = 1.0 - M1.start() - tm = Message() - tm.address = addr - for i in range(100): - tm.body = {'number': i} - M1.put(tm) - M1.send() - M1.stop() - - - def test_1_pre_settled(self): - addr = "amqp://0.0.0.0:20000/pre_settled/1" - M1 = Messenger() - M2 = Messenger() - - M1.timeout = 1.0 - M2.timeout = 1.0 - - M1.start() - M2.start() - self.subscribe(M2, addr) - - tm = Message() - rm = Message() - - tm.address = addr - for i in range(100): - tm.body = {'number': i} - M1.put(tm) - M1.send() - - for i in range(100): - M2.recv(1) - M2.get(rm) - self.assertEqual(i, rm.body['number']) - - M1.stop() - M2.stop() - - - def test_2_multicast(self): - addr = "amqp://0.0.0.0:20000/pre_settled/multicast/1" - M1 = Messenger() - M2 = Messenger() - M3 = Messenger() - M4 = Messenger() - - M1.timeout = 1.0 - M2.timeout = 1.0 - M3.timeout = 1.0 - M4.timeout = 1.0 - - M1.start() - M2.start() - M3.start() - M4.start() - self.subscribe(M2, addr) - self.subscribe(M3, addr) - self.subscribe(M4, addr) - - tm = Message() - rm = Message() - - tm.address = addr - for i in range(100): - tm.body = {'number': i} - M1.put(tm) - M1.send() - - for i in range(100): - M2.recv(1) - M2.get(rm) - self.assertEqual(i, rm.body['number']) - - M3.recv(1) - M3.get(rm) - self.assertEqual(i, rm.body['number']) - - M4.recv(1) - M4.get(rm) - self.assertEqual(i, rm.body['number']) - - M1.stop() - M2.stop() - M3.stop() - M4.stop() - - - def test_2a_multicast_unsettled(self): - addr = "amqp://0.0.0.0:20000/pre_settled/multicast/1" - M1 = Messenger() - M2 = Messenger() - M3 = Messenger() - M4 = Messenger() - - M1.timeout = 1.0 - M2.timeout = 1.0 - M3.timeout = 1.0 - M4.timeout = 1.0 - - M1.outgoing_window = 5 - M2.incoming_window = 5 - M3.incoming_window = 5 - M4.incoming_window = 5 - - M1.start() - M2.start() - M3.start() - M4.start() - self.subscribe(M2, addr) - self.subscribe(M3, addr) - self.subscribe(M4, addr) - - tm = Message() - rm = Message() - - tm.address = addr - for i in range(2): - tm.body = {'number': i} - M1.put(tm) - M1.send(0) - - for i in range(2): - M2.recv(1) - trk = M2.get(rm) - M2.accept(trk) - M2.settle(trk) - self.assertEqual(i, rm.body['number']) - - M3.recv(1) - trk = M3.get(rm) - M3.accept(trk) - M3.settle(trk) - self.assertEqual(i, rm.body['number']) - - M4.recv(1) - trk = M4.get(rm) - M4.accept(trk) - M4.settle(trk) - self.assertEqual(i, rm.body['number']) - - M1.stop() - M2.stop() - M3.stop() - M4.stop() - - - def test_3_propagated_disposition(self): - addr = "amqp://0.0.0.0:20000/unsettled/1" - M1 = Messenger() - M2 = Messenger() - - M1.timeout = 1.0 - M2.timeout = 1.0 - M1.outgoing_window = 5 - M2.incoming_window = 5 - - M1.start() - M2.start() - self.subscribe(M2, addr) - - tm = Message() - rm = Message() - - tm.address = addr - tm.body = {'number': 0} - - ## - ## Test ACCEPT - ## - tx_tracker = M1.put(tm) - M1.send(0) - M2.recv(1) - rx_tracker = M2.get(rm) - self.assertEqual(0, rm.body['number']) - self.assertEqual(PENDING, M1.status(tx_tracker)) - - M2.accept(rx_tracker) - M2.settle(rx_tracker) - - self.flush(M2) - self.flush(M1) - - self.assertEqual(ACCEPTED, M1.status(tx_tracker)) - - ## - ## Test REJECT - ## - tx_tracker = M1.put(tm) - M1.send(0) - M2.recv(1) - rx_tracker = M2.get(rm) - self.assertEqual(0, rm.body['number']) - self.assertEqual(PENDING, M1.status(tx_tracker)) - - M2.reject(rx_tracker) - M2.settle(rx_tracker) - - self.flush(M2) - self.flush(M1) - - self.assertEqual(REJECTED, M1.status(tx_tracker)) - - M1.stop() - M2.stop() - - - def test_4_unsettled_undeliverable(self): - addr = "amqp://0.0.0.0:20000/unsettled_undeliverable/1" - M1 = Messenger() - - M1.timeout = 1.0 - M1.outgoing_window = 5 - - M1.start() - tm = Message() - tm.address = addr - tm.body = {'number': 200} - - tx_tracker = M1.put(tm) - M1.send(0) - self.flush(M1) - self.assertEqual(PENDING, M1.status(tx_tracker)) ## Is this right??? - - M1.stop() - - - def test_5_three_ack(self): - addr = "amqp://0.0.0.0:20000/three_ack/1" - M1 = Messenger() - M2 = Messenger() - - M1.timeout = 1.0 - M2.timeout = 1.0 - M1.outgoing_window = 5 - M2.incoming_window = 5 - - M1.start() - M2.start() - self.subscribe(M2, addr) - - tm = Message() - rm = Message() - - tm.address = addr - tm.body = {'number': 200} - - tx_tracker = M1.put(tm) - M1.send(0) - M2.recv(1) - rx_tracker = M2.get(rm) - self.assertEqual(200, rm.body['number']) - self.assertEqual(PENDING, M1.status(tx_tracker)) - - M2.accept(rx_tracker) - - self.flush(M2) - self.flush(M1) - - self.assertEqual(ACCEPTED, M1.status(tx_tracker)) - - M1.settle(tx_tracker) - - self.flush(M1) - self.flush(M2) - - ## - ## We need a way to verify on M2 (receiver) that the tracker has been - ## settled on the M1 (sender). [ See PROTON-395 ] - ## - - M2.settle(rx_tracker) - - self.flush(M2) - self.flush(M1) - - M1.stop() - M2.stop() - - -# def test_6_link_route_sender(self): -# pass - -# def test_7_link_route_receiver(self): -# pass - - - def test_8_delivery_annotations(self): - addr = "amqp://0.0.0.0:20000/da/1" - M1 = Messenger() - M2 = Messenger() - - M1.timeout = 1.0 - M2.timeout = 1.0 - - M1.start() - M2.start() - self.subscribe(M2, addr) - - tm = Message() - rm = Message() - - tm.address = addr - - - ## - ## No inbound delivery annotations - ## - for i in range(10): - tm.body = {'number': i} - M1.put(tm) - M1.send() - - for i in range(10): - M2.recv(1) - M2.get(rm) - self.assertEqual(i, rm.body['number']) - da = rm.instructions - self.assertEqual(da.__class__, dict) - self.assertEqual(da['qdx.ingress'], '0/Qpid.Dispatch.Router.A') - self.assertEqual(da['qdx.trace'], ['0/Qpid.Dispatch.Router.A']) - - ## - ## Pre-existing ingress - ## - tm.instructions = {'qdx.ingress': 'ingress-router'} - for i in range(10): - tm.body = {'number': i} - M1.put(tm) - M1.send() - - for i in range(10): - M2.recv(1) - M2.get(rm) - self.assertEqual(i, rm.body['number']) - da = rm.instructions - self.assertEqual(da.__class__, dict) - self.assertEqual(da['qdx.ingress'], 'ingress-router') - self.assertEqual(da['qdx.trace'], ['0/Qpid.Dispatch.Router.A']) - - ## - ## Invalid trace type - ## - tm.instructions = {'qdx.trace' : 45} - for i in range(10): - tm.body = {'number': i} - M1.put(tm) - M1.send() - - for i in range(10): - M2.recv(1) - M2.get(rm) - self.assertEqual(i, rm.body['number']) - da = rm.instructions - self.assertEqual(da.__class__, dict) - self.assertEqual(da['qdx.ingress'], '0/Qpid.Dispatch.Router.A') - self.assertEqual(da['qdx.trace'], ['0/Qpid.Dispatch.Router.A']) - - ## - ## Empty trace - ## - tm.instructions = {'qdx.trace' : []} - for i in range(10): - tm.body = {'number': i} - M1.put(tm) - M1.send() - - for i in range(10): - M2.recv(1) - M2.get(rm) - self.assertEqual(i, rm.body['number']) - da = rm.instructions - self.assertEqual(da.__class__, dict) - self.assertEqual(da['qdx.ingress'], '0/Qpid.Dispatch.Router.A') - self.assertEqual(da['qdx.trace'], ['0/Qpid.Dispatch.Router.A']) - - ## - ## Non-empty trace - ## - tm.instructions = {'qdx.trace' : ['0/first.hop']} - for i in range(10): - tm.body = {'number': i} - M1.put(tm) - M1.send() - - for i in range(10): - M2.recv(1) - M2.get(rm) - self.assertEqual(i, rm.body['number']) - da = rm.instructions - self.assertEqual(da.__class__, dict) - self.assertEqual(da['qdx.ingress'], '0/Qpid.Dispatch.Router.A') - self.assertEqual(da['qdx.trace'], ['0/first.hop', '0/Qpid.Dispatch.Router.A']) - - M1.stop() - M2.stop() - - -if __name__ == '__main__': - unittest.main() diff --git a/extras/dispatch/tests/test_case.h b/extras/dispatch/tests/test_case.h deleted file mode 100644 index 6e36b440a5..0000000000 --- a/extras/dispatch/tests/test_case.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _nexus_test_case_h_ -#define _nexus_test_case_h_ 1 -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -typedef char* (*testcase_t)(void *context); - -#define TEST_CASE(T,C) do { \ - char *r = T(C); \ - printf("Test Case %s.%s: ", __FUNCTION__, #T); \ - if (r) { \ - printf("FAIL: %s\n", r); \ - result++; \ - } else \ - printf("PASS\n"); \ -} while(0); - - -#endif - diff --git a/extras/dispatch/tests/threads4.conf b/extras/dispatch/tests/threads4.conf deleted file mode 100644 index 1466e11cca..0000000000 --- a/extras/dispatch/tests/threads4.conf +++ /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 -## - - -## -## Container section - Configures the general operation of the AMQP container. -## -container { - worker-threads: 4 -} diff --git a/extras/dispatch/tests/timer_test.c b/extras/dispatch/tests/timer_test.c deleted file mode 100644 index 93725dde4b..0000000000 --- a/extras/dispatch/tests/timer_test.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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 <qpid/dispatch/timer.h> -#include "alloc_private.h" -#include "timer_private.h" -#include "test_case.h" -#include <qpid/dispatch/threading.h> - - -static unsigned long fire_mask; -static dx_timer_list_t pending_timers; -static sys_mutex_t *lock; -static long time; -static dx_timer_t *timers[16]; - - -void dx_server_timer_pending_LH(dx_timer_t *timer) -{ - DEQ_INSERT_TAIL(pending_timers, timer); -} - - -void dx_server_timer_cancel_LH(dx_timer_t *timer) -{ - if (timer->state == TIMER_PENDING) - DEQ_REMOVE(pending_timers, timer); -} - - -static int fire_head() -{ - sys_mutex_lock(lock); - int result = DEQ_SIZE(pending_timers); - dx_timer_t *timer = DEQ_HEAD(pending_timers); - if (timer) { - DEQ_REMOVE_HEAD(pending_timers); - dx_timer_idle_LH(timer); - fire_mask |= (unsigned long) timer->context; - } - sys_mutex_unlock(lock); - return result; -} - - -static char* test_quiet(void *context) -{ - fire_mask = 0; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - - while(fire_head()); - - if (fire_mask != 0) - return "Expected zero timers fired"; - return 0; -} - -static char* test_immediate(void *context) -{ - while(fire_head()); - fire_mask = 0; - - dx_timer_schedule(timers[0], 0); - - if (fire_mask != 0) return "Premature firing"; - if (fire_head() > 1) return "Too many firings"; - if (fire_mask != 1) return "Incorrect fire mask"; - - return 0; -} - - -static char* test_immediate_reschedule(void *context) -{ - while(fire_head()); - fire_mask = 0; - - dx_timer_schedule(timers[0], 0); - dx_timer_schedule(timers[0], 0); - - if (fire_mask != 0) return "pass 1 - Premature firing"; - if (fire_head() > 1) return "pass 1 - Too many firings"; - if (fire_mask != 1) return "pass 1 - Incorrect fire mask"; - - fire_mask = 0; - dx_timer_schedule(timers[0], 0); - dx_timer_schedule(timers[0], 0); - - if (fire_mask != 0) return "pass 2 - Premature firing"; - if (fire_head() > 1) return "pass 2 - Too many firings"; - if (fire_mask != 1) return "pass 2 - Incorrect fire mask"; - - return 0; -} - - -static char* test_immediate_plus_delayed(void *context) -{ - while(fire_head()); - fire_mask = 0; - - dx_timer_schedule(timers[0], 0); - dx_timer_schedule(timers[1], 5); - - if (fire_mask != 0) return "Premature firing"; - if (fire_head() > 1) return "Too many firings"; - if (fire_mask != 1) return "Incorrect fire mask 1"; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - time += 8; - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - - if (fire_head() < 1) return "Delayed Failed to fire"; - if (fire_mask != 3) return "Incorrect fire mask 3"; - - return 0; -} - - -static char* test_single(void *context) -{ - while(fire_head()); - fire_mask = 0; - - dx_timer_schedule(timers[0], 2); - if (fire_head() > 0) return "Premature firing 1"; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - if (fire_head() > 0) return "Premature firing 2"; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - if (fire_head() < 1) return "Failed to fire"; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - if (fire_head() != 0) return "Spurious fires"; - - if (fire_mask != 1) return "Incorrect fire mask"; - if (timers[0]->state != TIMER_IDLE) return "Expected idle timer state"; - - return 0; -} - - -static char* test_two_inorder(void *context) -{ - while(fire_head()); - fire_mask = 0; - - dx_timer_schedule(timers[0], 2); - dx_timer_schedule(timers[1], 4); - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - int count = fire_head(); - if (count < 1) return "First failed to fire"; - if (count > 1) return "Second fired prematurely"; - if (fire_mask != 1) return "Incorrect fire mask 1"; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - if (fire_head() < 1) return "Second failed to fire"; - if (fire_mask != 3) return "Incorrect fire mask 3"; - - return 0; -} - - -static char* test_two_reverse(void *context) -{ - while(fire_head()); - fire_mask = 0; - - dx_timer_schedule(timers[0], 4); - dx_timer_schedule(timers[1], 2); - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - int count = fire_head(); - if (count < 1) return "First failed to fire"; - if (count > 1) return "Second fired prematurely"; - if (fire_mask != 2) return "Incorrect fire mask 2"; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - if (fire_head() < 1) return "Second failed to fire"; - if (fire_mask != 3) return "Incorrect fire mask 3"; - - return 0; -} - - -static char* test_two_duplicate(void *context) -{ - while(fire_head()); - fire_mask = 0; - - dx_timer_schedule(timers[0], 2); - dx_timer_schedule(timers[1], 2); - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - int count = fire_head(); - if (count != 2) return "Expected two firings"; - fire_head(); - if (fire_mask != 3) return "Incorrect fire mask 3"; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - if (fire_head() > 0) return "Spurious timer fires"; - - return 0; -} - - -static char* test_separated(void *context) -{ - int count; - - while(fire_head()); - fire_mask = 0; - - dx_timer_schedule(timers[0], 2); - dx_timer_schedule(timers[1], 4); - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - count = fire_head(); - if (count < 1) return "First failed to fire"; - if (count > 1) return "Second fired prematurely"; - if (fire_mask != 1) return "Incorrect fire mask 1"; - - dx_timer_schedule(timers[2], 2); - dx_timer_schedule(timers[3], 4); - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - count = fire_head(); - fire_head(); - if (count < 1) return "Second failed to fire"; - if (count < 2) return "Third failed to fire"; - if (fire_mask != 7) return "Incorrect fire mask 7"; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - count = fire_head(); - if (count < 1) return "Fourth failed to fire"; - if (fire_mask != 15) return "Incorrect fire mask 15"; - - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - count = fire_head(); - if (count > 0) return "Spurious fire"; - - return 0; -} - - -static char* test_big(void *context) -{ - while(fire_head()); - fire_mask = 0; - - long durations[16] = - { 5, 8, 7, 6, - 14, 10, 16, 15, - 11, 12, 9, 12, - 1, 2, 3, 4}; - unsigned long masks[18] = { - 0x1000, - 0x3000, - 0x7000, - 0xf000, - 0xf001, - 0xf009, - 0xf00d, - 0xf00f, - 0xf40f, - 0xf42f, - 0xf52f, - 0xff2f, - 0xff2f, - 0xff3f, - 0xffbf, - 0xffff, - 0xffff, - 0xffff - }; - - int i; - for (i = 0; i < 16; i++) - dx_timer_schedule(timers[i], durations[i]); - for (i = 0; i < 18; i++) { - sys_mutex_lock(lock); - dx_timer_visit_LH(time++); - sys_mutex_unlock(lock); - while(fire_head()); - if (fire_mask != masks[i]) { - static char error[100]; - sprintf(error, "Iteration %d: expected mask %04lx, got %04lx", i, masks[i], fire_mask); - return error; - } - } - - return 0; -} - - -int timer_tests(void) -{ - int result = 0; - dx_alloc_initialize(); - - fire_mask = 0; - DEQ_INIT(pending_timers); - lock = sys_mutex(); - dx_timer_initialize(lock); - time = 1; - - timers[0] = dx_timer(0, 0, (void*) 0x00000001); - timers[1] = dx_timer(0, 0, (void*) 0x00000002); - timers[2] = dx_timer(0, 0, (void*) 0x00000004); - timers[3] = dx_timer(0, 0, (void*) 0x00000008); - timers[4] = dx_timer(0, 0, (void*) 0x00000010); - timers[5] = dx_timer(0, 0, (void*) 0x00000020); - timers[6] = dx_timer(0, 0, (void*) 0x00000040); - timers[7] = dx_timer(0, 0, (void*) 0x00000080); - timers[8] = dx_timer(0, 0, (void*) 0x00000100); - timers[9] = dx_timer(0, 0, (void*) 0x00000200); - timers[10] = dx_timer(0, 0, (void*) 0x00000400); - timers[11] = dx_timer(0, 0, (void*) 0x00000800); - timers[12] = dx_timer(0, 0, (void*) 0x00001000); - timers[13] = dx_timer(0, 0, (void*) 0x00002000); - timers[14] = dx_timer(0, 0, (void*) 0x00004000); - timers[15] = dx_timer(0, 0, (void*) 0x00008000); - - TEST_CASE(test_quiet, 0); - TEST_CASE(test_immediate, 0); - TEST_CASE(test_immediate_reschedule, 0); - TEST_CASE(test_immediate_plus_delayed, 0); - TEST_CASE(test_single, 0); - TEST_CASE(test_two_inorder, 0); - TEST_CASE(test_two_reverse, 0); - TEST_CASE(test_two_duplicate, 0); - TEST_CASE(test_separated, 0); - TEST_CASE(test_big, 0); - - int i; - for (i = 0; i < 16; i++) - dx_timer_free(timers[i]); - - dx_timer_finalize(); - - return result; -} - diff --git a/extras/dispatch/tests/tool_test.c b/extras/dispatch/tests/tool_test.c deleted file mode 100644 index 2c90714b3d..0000000000 --- a/extras/dispatch/tests/tool_test.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES 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_case.h" -#include <stdio.h> -#include <string.h> -#include <qpid/dispatch/ctools.h> -#include <qpid/dispatch/bitmask.h> -#include "alloc_private.h" - -typedef struct item_t { - DEQ_LINKS(struct item_t); - char letter; -} item_t; - -DEQ_DECLARE(item_t, item_list_t); - - -static char* list_well_formed(item_list_t list, char *key) -{ - item_t *ptr; - item_t *last = 0; - int size = DEQ_SIZE(list); - int count = 0; - char str[32]; - - ptr = DEQ_HEAD(list); - while (ptr) { - str[count] = ptr->letter; - count++; - if (DEQ_PREV(ptr) != last) return "Corrupt previous link"; - last = ptr; - ptr = DEQ_NEXT(ptr); - } - str[count] = '\0'; - if (strcmp(str, key) != 0) return "Invalid key"; - - if (count != size) return "Size different from number of items (forward)"; - - count = 0; - last = 0; - ptr = DEQ_TAIL(list); - while (ptr) { - count++; - if (DEQ_NEXT(ptr) != last) return "Corrupt next link"; - last = ptr; - ptr = DEQ_PREV(ptr); - } - - if (count != size) return "Size different from number of items (backward)"; - - return 0; -} - - -static char* test_deq_basic(void *context) -{ - item_list_t list; - item_t item[10]; - item_t *ptr; - int idx; - char *subtest; - - DEQ_INIT(list); - if (DEQ_SIZE(list) != 0) return "Expected zero initial size"; - - for (idx = 0; idx < 10; idx++) { - DEQ_ITEM_INIT(&item[idx]); - item[idx].letter = 'A' + idx; - DEQ_INSERT_TAIL(list, &item[idx]); - } - if (DEQ_SIZE(list) != 10) return "Expected 10 items in list"; - - ptr = DEQ_HEAD(list); - if (!ptr) return "Expected valid head item"; - if (DEQ_PREV(ptr)) return "Head item has non-null previous link"; - if (ptr->letter != 'A') return "Expected item A at the head"; - if (DEQ_NEXT(ptr) == 0) return "Head item has null next link"; - subtest = list_well_formed(list, "ABCDEFGHIJ"); - if (subtest) return subtest; - - DEQ_REMOVE_HEAD(list); - if (DEQ_SIZE(list) != 9) return "Expected 9 items in list"; - ptr = DEQ_HEAD(list); - if (ptr->letter != 'B') return "Expected item B at the head"; - subtest = list_well_formed(list, "BCDEFGHIJ"); - if (subtest) return subtest; - - DEQ_REMOVE_TAIL(list); - if (DEQ_SIZE(list) != 8) return "Expected 8 items in list"; - ptr = DEQ_TAIL(list); - if (ptr->letter != 'I') return "Expected item I at the tail"; - subtest = list_well_formed(list, "BCDEFGHI"); - if (subtest) return subtest; - - DEQ_REMOVE(list, &item[4]); - if (DEQ_SIZE(list) != 7) return "Expected 7 items in list"; - subtest = list_well_formed(list, "BCDFGHI"); - if (subtest) return subtest; - - DEQ_REMOVE(list, &item[1]); - if (DEQ_SIZE(list) != 6) return "Expected 6 items in list"; - subtest = list_well_formed(list, "CDFGHI"); - if (subtest) return subtest; - - DEQ_REMOVE(list, &item[8]); - if (DEQ_SIZE(list) != 5) return "Expected 5 items in list"; - subtest = list_well_formed(list, "CDFGH"); - if (subtest) return subtest; - - DEQ_INSERT_HEAD(list, &item[8]); - if (DEQ_SIZE(list) != 6) return "Expected 6 items in list"; - ptr = DEQ_HEAD(list); - if (ptr->letter != 'I') return "Expected item I at the head"; - subtest = list_well_formed(list, "ICDFGH"); - if (subtest) return subtest; - - DEQ_INSERT_AFTER(list, &item[4], &item[7]); - if (DEQ_SIZE(list) != 7) return "Expected 7 items in list"; - ptr = DEQ_TAIL(list); - if (ptr->letter != 'E') return "Expected item E at the head"; - subtest = list_well_formed(list, "ICDFGHE"); - if (subtest) return subtest; - - DEQ_INSERT_AFTER(list, &item[1], &item[5]); - if (DEQ_SIZE(list) != 8) return "Expected 8 items in list"; - subtest = list_well_formed(list, "ICDFBGHE"); - if (subtest) return subtest; - - if (item[0].prev || item[0].next) return "Unlisted item A has non-null pointers"; - if (item[9].prev || item[9].next) return "Unlisted item J has non-null pointers"; - - return 0; -} - - -static char* test_deq_basic2(void *context) -{ - item_list_t list; - item_t item[10]; - item_t *ptr; - int idx; - char *subtest; - - DEQ_INIT(list); - if (DEQ_SIZE(list) != 0) return "Expected zero initial size"; - - for (idx = 0; idx < 10; idx++) { - DEQ_ITEM_INIT(&item[idx]); - item[idx].letter = '0' + idx; - } - - DEQ_INSERT_TAIL(list, &item[0]); - if (DEQ_SIZE(list) != 1) return "Expected 1 items in list"; - subtest = list_well_formed(list, "0"); - if (subtest) return subtest; - - ptr = DEQ_HEAD(list); - DEQ_REMOVE_HEAD(list); - if (ptr->letter != '0') return "Expected item '0'"; - if (DEQ_SIZE(list) != 0) return "Expected 0 items in list"; - - DEQ_INSERT_TAIL(list, &item[0]); - if (DEQ_SIZE(list) != 1) return "Expected 1 items in list"; - subtest = list_well_formed(list, "0"); - if (subtest) return subtest; - - ptr = DEQ_HEAD(list); - DEQ_REMOVE_HEAD(list); - if (ptr->letter != '0') return "Expected item '0'"; - if (DEQ_SIZE(list) != 0) return "Expected 0 items in list"; - - return 0; -} - - -static char* test_bitmask(void *context) -{ - dx_bitmask_t *bm; - int num; - - bm = dx_bitmask(0); - if (!bm) return "Can't allocate a bit mask"; - if (dx_bitmask_first_set(bm, &num)) return "Expected no first set bit"; - - dx_bitmask_set_bit(bm, 3); - dx_bitmask_set_bit(bm, 500); - - if (!dx_bitmask_first_set(bm, &num)) return "Expected first set bit"; - if (num != 3) return "Expected first set bit to be 3"; - - dx_bitmask_clear_bit(bm, num); - - if (!dx_bitmask_first_set(bm, &num)) return "Expected first set bit (2)"; - if (num != 500) return "Expected first set bit to be 500"; - - dx_bitmask_clear_bit(bm, num); - if (dx_bitmask_first_set(bm, &num)) return "Expected no first set bit (2)"; - - dx_bitmask_free(bm); - - return 0; -} - - -int tool_tests(void) -{ - int result = 0; - dx_alloc_initialize(); - - TEST_CASE(test_deq_basic, 0); - TEST_CASE(test_deq_basic2, 0); - TEST_CASE(test_bitmask, 0); - - return result; -} - diff --git a/extras/dispatch/tools/src/py/qdstat b/extras/dispatch/tools/src/py/qdstat deleted file mode 100755 index 32594b4d4e..0000000000 --- a/extras/dispatch/tools/src/py/qdstat +++ /dev/null @@ -1,328 +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 -from optparse import OptionParser, OptionGroup -import sys -import locale -import socket -import re -from proton import Messenger, Message - -home = os.environ.get("QD_TOOLS_HOME", os.path.normpath("/usr/share/qd-tools")) -sys.path.append(os.path.join(home, "python")) - -from qdtoollibs import Display, Header, Sorter, YN, Commas, TimeLong - - -class Config: - def __init__(self): - self._host = "0.0.0.0" - self._connTimeout = 10 - self._types = "" - self._limit = 50 - self._increasing = False - self._sortcol = None - -config = Config() -conn_options = {} - -def OptionsAndArguments(argv): - """ Set global variables for options, return arguments """ - - global config - global conn_options - - usage = \ -"""%prog -g [options] - %prog -c [options] - %prog -l [options] - %prog -n [options] - %prog -a [options] - %prog -m [options]""" - - parser = OptionParser(usage=usage) - - group1 = OptionGroup(parser, "General Options") - group1.add_option("-b", "--bus", action="store", type="string", default="0.0.0.0", metavar="<url>", - help="URL of the messaging bus to connect to") - group1.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="<secs>", - help="Maximum time to wait for connection (in seconds)") - group1.add_option("--sasl-mechanism", action="store", type="string", metavar="<mech>", - help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD5, DIGEST-MD5, GSSAPI). SASL automatically picks the most secure available mechanism - use this option to override.") - group1.add_option("--ssl-certificate", action="store", type="string", metavar="<cert>", help="Client SSL certificate (PEM Format)") - group1.add_option("--ssl-key", action="store", type="string", metavar="<key>", help="Client SSL private key (PEM Format)") - parser.add_option_group(group1) - - group2 = OptionGroup(parser, "Command Options") - group2.add_option("-g", "--general", help="Show General Broker Stats", action="store_const", const="g", dest="show") - group2.add_option("-c", "--connections", help="Show Connections", action="store_const", const="c", dest="show") - group2.add_option("-l", "--links", help="Show Router Links", action="store_const", const="l", dest="show") - group2.add_option("-n", "--nodes", help="Show Router Nodes", action="store_const", const="n", dest="show") - group2.add_option("-a", "--address", help="Show Router Addresses", action="store_const", const="a", dest="show") - group2.add_option("-m", "--memory", help="Show Broker Memory Stats", action="store_const", const="m", dest="show") - parser.add_option_group(group2) - - opts, args = parser.parse_args(args=argv) - - if not opts.show: - parser.error("You must specify one of these options: -g, -c, -l, -n, -a, or -m. For details, try $ qdstat --help") - - config._types = opts.show - config._host = opts.bus - config._connTimeout = opts.timeout - - return args - - -class BusManager: - def __init__(self): - pass - - def SetHost(self, host): - self.M = Messenger() - self.M.start() - self.M.route("amqp:/*", "amqp://%s/$1" % host) - self.address = "amqp:/_local/$management" - self.reply = "amqp:/temp.reply-address/0001" # FIX THIS! - self.M.subscribe(self.reply) - - def Disconnect(self): - self.M.stop() - - def displayConn(self): - pass - - def _addr_class(self, addr): - if not addr: - return "-" - if addr[0] == 'M' : return "mobile" - if addr[0] == 'R' : return "router" - if addr[0] == 'A' : return "area" - if addr[0] == 'L' : return "local" - return "unknown: %s" % addr[0] - - def _addr_text(self, addr): - if not addr: - return "-" - return addr[1:] - - def displayRouterLinks(self): - disp = Display(prefix=" ") - heads = [] - heads.append(Header("type")) - heads.append(Header("dir")) - heads.append(Header("rindex")) - heads.append(Header("class")) - heads.append(Header("addr")) - rows = [] - - request = Message() - response = Message() - - request.address = self.address - request.reply_to = self.reply - request.correlation_id = 1 - request.properties = {u'operation':u'GET', u'type':u'org.apache.qpid.dispatch.router.link'} - - self.M.put(request) - self.M.send() - - self.M.recv() - self.M.get(response) - - for link in response.body: - row = [] - row.append(link['link-type']) - row.append(link['link-dir']) - if link['link-type'] == "router": - row.append(link['index']) - else: - row.append('-') - row.append(self._addr_class(link['owning-addr'])) - row.append(self._addr_text(link['owning-addr'])) - rows.append(row) - title = "Router Links" - dispRows = rows - disp.formattedTable(title, heads, dispRows) - - def displayRouterNodes(self): - disp = Display(prefix=" ") - heads = [] - heads.append(Header("class")) - heads.append(Header("address")) - heads.append(Header("rindex")) - heads.append(Header("next-hop")) - heads.append(Header("link")) - rows = [] - - request = Message() - response = Message() - - request.address = self.address - request.reply_to = self.reply - request.correlation_id = 1 - request.properties = {u'operation':u'GET', u'type':u'org.apache.qpid.dispatch.router.node'} - - self.M.put(request) - self.M.send() - - self.M.recv() - self.M.get(response) - - for node in response.body: - row = [] - row.append(self._addr_class(node['addr'])) - row.append(self._addr_text(node['addr'])) - row.append(node['index']) - if node['next-hop'] != None: - row.append(node['next-hop']) - else: - row.append('-') - if node['router-link'] != None: - row.append(node['router-link']) - else: - row.append('-') - rows.append(row) - title = "Router Nodes" - dispRows = rows - disp.formattedTable(title, heads, dispRows) - - def displayAddresses(self): - disp = Display(prefix=" ") - heads = [] - heads.append(Header("class")) - heads.append(Header("address")) - heads.append(Header("in-proc", Header.Y)) - heads.append(Header("local", Header.COMMAS)) - heads.append(Header("remote", Header.COMMAS)) - heads.append(Header("in", Header.COMMAS)) - heads.append(Header("out", Header.COMMAS)) - heads.append(Header("thru", Header.COMMAS)) - heads.append(Header("to-proc", Header.COMMAS)) - heads.append(Header("from-proc", Header.COMMAS)) - rows = [] - - request = Message() - response = Message() - - request.address = self.address - request.reply_to = self.reply - request.correlation_id = 1 - request.properties = {u'operation':u'GET', u'type':u'org.apache.qpid.dispatch.router.address'} - - self.M.put(request) - self.M.send() - - self.M.recv() - self.M.get(response) - - for addr in response.body: - row = [] - row.append(self._addr_class(addr['addr'])) - row.append(self._addr_text(addr['addr'])) - row.append(addr['in-process']) - row.append(addr['subscriber-count']) - row.append(addr['remote-count']) - row.append(addr['deliveries-ingress']) - row.append(addr['deliveries-egress']) - row.append(addr['deliveries-transit']) - row.append(addr['deliveries-to-container']) - row.append(addr['deliveries-from-container']) - rows.append(row) - title = "Router Addresses" - sorter = Sorter(heads, rows, 'address', 0, True) - dispRows = sorter.getSorted() - disp.formattedTable(title, heads, dispRows) - - def displayMemory(self): - disp = Display(prefix=" ") - heads = [] - heads.append(Header("type")) - heads.append(Header("size", Header.COMMAS)) - heads.append(Header("batch")) - heads.append(Header("thread-max", Header.COMMAS)) - heads.append(Header("total", Header.COMMAS)) - heads.append(Header("in-threads", Header.COMMAS)) - heads.append(Header("rebal-in", Header.COMMAS)) - heads.append(Header("rebal-out", Header.COMMAS)) - rows = [] - - request = Message() - response = Message() - - request.address = self.address - request.reply_to = self.reply - request.correlation_id = 1 - request.properties = {u'operation':u'GET', u'type':u'org.apache.qpid.dispatch.allocator'} - - self.M.put(request) - self.M.send() - - self.M.recv() - self.M.get(response) - - for t in response.body: - row = [] - row.append(t['name']) - row.append(t['type_size']) - row.append(t['transfer_batch_size']) - row.append(t['local_free_list_max']) - row.append(t['total_alloc_from_heap']) - row.append(t['held_by_threads']) - row.append(t['batches_rebalanced_to_threads']) - row.append(t['batches_rebalanced_to_global']) - rows.append(row) - title = "Types" - sorter = Sorter(heads, rows, 'type', 0, True) - dispRows = sorter.getSorted() - disp.formattedTable(title, heads, dispRows) - - def displayMain(self, names, main): - if main == 'l': self.displayRouterLinks() - elif main == 'n': self.displayRouterNodes() - elif main == 'a': self.displayAddresses() - elif main == 'm': self.displayMemory() - - def display(self, names): - self.displayMain(names, config._types) - - -def main(argv=None): - - args = OptionsAndArguments(argv) - bm = BusManager() - - try: - bm.SetHost(config._host) - bm.display(args) - bm.Disconnect() - return 0 - except KeyboardInterrupt: - print - except Exception,e: - print "Failed: %s - %s" % (e.__class__.__name__, e) - - bm.Disconnect() # try to deallocate brokers - return 1 - -if __name__ == "__main__": - sys.exit(main()) diff --git a/extras/dispatch/tools/src/py/qdtoollibs/__init__.py b/extras/dispatch/tools/src/py/qdtoollibs/__init__.py deleted file mode 100644 index 378bf24ef1..0000000000 --- a/extras/dispatch/tools/src/py/qdtoollibs/__init__.py +++ /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. -# - -from qdtoollibs.disp import * - diff --git a/extras/dispatch/tools/src/py/qdtoollibs/disp.py b/extras/dispatch/tools/src/py/qdtoollibs/disp.py deleted file mode 100644 index 529a727449..0000000000 --- a/extras/dispatch/tools/src/py/qdtoollibs/disp.py +++ /dev/null @@ -1,270 +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. -# - -from time import strftime, gmtime - -def YN(val): - if val: - return 'Y' - return 'N' - -def Commas(value): - sval = str(value) - result = "" - while True: - if len(sval) == 0: - return result - left = sval[:-3] - right = sval[-3:] - result = right + result - if len(left) > 0: - result = ',' + result - sval = left - -def TimeLong(value): - return strftime("%c", gmtime(value / 1000000000)) - -def TimeShort(value): - return strftime("%X", gmtime(value / 1000000000)) - - -class Header: - """ """ - NONE = 1 - KMG = 2 - YN = 3 - Y = 4 - TIME_LONG = 5 - TIME_SHORT = 6 - DURATION = 7 - COMMAS = 8 - - def __init__(self, text, format=NONE): - self.text = text - self.format = format - - def __repr__(self): - return self.text - - def __str__(self): - return self.text - - def formatted(self, value): - try: - if value == None: - return '' - if self.format == Header.NONE: - return value - if self.format == Header.KMG: - return self.num(value) - if self.format == Header.YN: - if value: - return 'Y' - return 'N' - if self.format == Header.Y: - if value: - return 'Y' - return '' - if self.format == Header.TIME_LONG: - return TimeLong(value) - if self.format == Header.TIME_SHORT: - return TimeShort(value) - if self.format == Header.DURATION: - if value < 0: value = 0 - sec = value / 1000000000 - min = sec / 60 - hour = min / 60 - day = hour / 24 - result = "" - if day > 0: - result = "%dd " % day - if hour > 0 or result != "": - result += "%dh " % (hour % 24) - if min > 0 or result != "": - result += "%dm " % (min % 60) - result += "%ds" % (sec % 60) - return result - if self.format == Header.COMMAS: - return Commas(value) - except: - return "?" - - def numCell(self, value, tag): - fp = float(value) / 1000. - if fp < 10.0: - return "%1.2f%c" % (fp, tag) - if fp < 100.0: - return "%2.1f%c" % (fp, tag) - return "%4d%c" % (value / 1000, tag) - - def num(self, value): - if value < 1000: - return "%4d" % value - if value < 1000000: - return self.numCell(value, 'k') - value /= 1000 - if value < 1000000: - return self.numCell(value, 'm') - value /= 1000 - return self.numCell(value, 'g') - - -class Display: - """ Display formatting """ - - def __init__(self, spacing=2, prefix=" "): - self.tableSpacing = spacing - self.tablePrefix = prefix - self.timestampFormat = "%X" - - def formattedTable(self, title, heads, rows): - fRows = [] - for row in rows: - fRow = [] - col = 0 - for cell in row: - fRow.append(heads[col].formatted(cell)) - col += 1 - fRows.append(fRow) - headtext = [] - for head in heads: - headtext.append(head.text) - self.table(title, headtext, fRows) - - def table(self, title, heads, rows): - """ Print a table with autosized columns """ - - # Pad the rows to the number of heads - for row in rows: - diff = len(heads) - len(row) - for idx in range(diff): - row.append("") - - print title - if len (rows) == 0: - return - colWidth = [] - col = 0 - line = self.tablePrefix - for head in heads: - width = len (head) - for row in rows: - text = row[col] - if text.__class__ == str: - text = text.decode('utf-8') - cellWidth = len(unicode(text)) - if cellWidth > width: - width = cellWidth - colWidth.append (width + self.tableSpacing) - line = line + head - if col < len (heads) - 1: - for i in range (colWidth[col] - len (head)): - line = line + " " - col = col + 1 - print line - line = self.tablePrefix - for width in colWidth: - for i in range (width): - line = line + "=" - print line - - for row in rows: - line = self.tablePrefix - col = 0 - for width in colWidth: - text = row[col] - if text.__class__ == str: - text = text.decode('utf-8') - line = line + unicode(text) - if col < len (heads) - 1: - for i in range (width - len(unicode(text))): - line = line + " " - col = col + 1 - print line - - def do_setTimeFormat (self, fmt): - """ Select timestamp format """ - if fmt == "long": - self.timestampFormat = "%c" - elif fmt == "short": - self.timestampFormat = "%X" - - def timestamp (self, nsec): - """ Format a nanosecond-since-the-epoch timestamp for printing """ - return strftime (self.timestampFormat, gmtime (nsec / 1000000000)) - - def duration(self, nsec): - if nsec < 0: nsec = 0 - sec = nsec / 1000000000 - min = sec / 60 - hour = min / 60 - day = hour / 24 - result = "" - if day > 0: - result = "%dd " % day - if hour > 0 or result != "": - result += "%dh " % (hour % 24) - if min > 0 or result != "": - result += "%dm " % (min % 60) - result += "%ds" % (sec % 60) - return result - -class Sortable: - """ """ - def __init__(self, row, sortIndex): - self.row = row - self.sortIndex = sortIndex - if sortIndex >= len(row): - raise Exception("sort index exceeds row boundary") - - def __cmp__(self, other): - return cmp(self.row[self.sortIndex], other.row[self.sortIndex]) - - def getRow(self): - return self.row - -class Sorter: - """ """ - def __init__(self, heads, rows, sortCol, limit=0, inc=True): - col = 0 - for head in heads: - if head.text == sortCol: - break - col += 1 - if col == len(heads): - raise Exception("sortCol '%s', not found in headers" % sortCol) - - list = [] - for row in rows: - list.append(Sortable(row, col)) - list.sort() - if not inc: - list.reverse() - count = 0 - self.sorted = [] - for row in list: - self.sorted.append(row.getRow()) - count += 1 - if count == limit: - break - - def getSorted(self): - return self.sorted |