You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2014/07/08 22:31:14 UTC
svn commit: r1608947 [1/2] - in /qpid/dispatch/trunk: ./ include/qpid/
include/qpid/dispatch/ python/qpid_dispatch_internal/management/
router/src/ src/ tests/ tests/management/ tools/
Author: aconway
Date: Tue Jul 8 20:31:13 2014
New Revision: 1608947
URL: http://svn.apache.org/r1608947
Log:
DISPATCH-56: Push configuration from python to C for dispatch router.
Python code parses config files asentity list and pushes each configuration
entity into the C code.
- libqpid_dispatch.py: ctypes python wrapper around libqpid-dispatch
- Various error handling and memory management fixes.
- Introduce EnumValue, C code can take enum as string or int.
- Generate C source code for schema enum values.
Added:
qpid/dispatch/trunk/python/qpid_dispatch_internal/management/libqpid_dispatch.py
qpid/dispatch/trunk/src/CMakeLists.txt
qpid/dispatch/trunk/src/entity.c
qpid/dispatch/trunk/src/entity_private.h
qpid/dispatch/trunk/src/schema_c.py
Removed:
qpid/dispatch/trunk/include/qpid/dispatch/config.h
qpid/dispatch/trunk/src/config.c
qpid/dispatch/trunk/src/config_private.h
Modified:
qpid/dispatch/trunk/CMakeLists.txt
qpid/dispatch/trunk/include/qpid/dispatch.h
qpid/dispatch/trunk/include/qpid/dispatch/connection_manager.h
qpid/dispatch/trunk/include/qpid/dispatch/dispatch.h
qpid/dispatch/trunk/include/qpid/dispatch/error.h
qpid/dispatch/trunk/include/qpid/dispatch/log.h
qpid/dispatch/trunk/include/qpid/dispatch/python_embedded.h
qpid/dispatch/trunk/python/qpid_dispatch_internal/management/__init__.py
qpid/dispatch/trunk/python/qpid_dispatch_internal/management/entity.py
qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.json
qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py
qpid/dispatch/trunk/python/qpid_dispatch_internal/management/schema.py
qpid/dispatch/trunk/router/src/config.h.in
qpid/dispatch/trunk/router/src/main.c
qpid/dispatch/trunk/src/connection_manager.c
qpid/dispatch/trunk/src/dispatch.c
qpid/dispatch/trunk/src/dispatch_private.h
qpid/dispatch/trunk/src/error.c
qpid/dispatch/trunk/src/log.c
qpid/dispatch/trunk/src/log_private.h
qpid/dispatch/trunk/src/python_embedded.c
qpid/dispatch/trunk/src/router_agent.c
qpid/dispatch/trunk/src/router_config.c
qpid/dispatch/trunk/src/router_node.c
qpid/dispatch/trunk/src/router_private.h
qpid/dispatch/trunk/src/router_pynode.c
qpid/dispatch/trunk/src/static_assert.h
qpid/dispatch/trunk/tests/management/schema.py
qpid/dispatch/trunk/tests/run.py.in
qpid/dispatch/trunk/tests/run_unit_tests.c
qpid/dispatch/trunk/tests/system_test.py
qpid/dispatch/trunk/tests/threads4.conf
qpid/dispatch/trunk/tools/qdstat
Modified: qpid/dispatch/trunk/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/CMakeLists.txt?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/CMakeLists.txt (original)
+++ qpid/dispatch/trunk/CMakeLists.txt Tue Jul 8 20:31:13 2014
@@ -78,6 +78,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/src
${proton_include}
${PYTHON_INCLUDE_PATH}
)
@@ -98,50 +99,8 @@ configure_file(${CMAKE_CURRENT_SOURCE_DI
${CMAKE_CURRENT_BINARY_DIR}/conditionals.h)
##
-## Build the Multi-Threaded Server Library
+## Header file installation
##
-set(server_SOURCES
- src/agent.c
- src/alloc.c
- src/amqp.c
- src/bitmask.c
- src/buffer.c
- src/error.c
- src/compose.c
- src/config.c
- src/connection_manager.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_config.c
- src/router_node.c
- src/router_pynode.c
- src/server.c
- src/timer.c
- src/waypoint.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)
@@ -169,9 +128,9 @@ install(PROGRAMS ${TOOLS_EXECUTABLES}
install(FILES ${DOC_FILES}
DESTINATION ${DOC_INSTALL_DIR}/qpid-dispatch)
-##
## Build Tests first as other subdirs use tests/run.py
##
add_subdirectory(tests)
+add_subdirectory(src)
add_subdirectory(doc)
add_subdirectory(router)
Modified: qpid/dispatch/trunk/include/qpid/dispatch.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/include/qpid/dispatch.h?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/include/qpid/dispatch.h (original)
+++ qpid/dispatch/trunk/include/qpid/dispatch.h Tue Jul 8 20:31:13 2014
@@ -8,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -31,7 +31,6 @@
#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>
Modified: qpid/dispatch/trunk/include/qpid/dispatch/connection_manager.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/include/qpid/dispatch/connection_manager.h?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/include/qpid/dispatch/connection_manager.h (original)
+++ qpid/dispatch/trunk/include/qpid/dispatch/connection_manager.h Tue Jul 8 20:31:13 2014
@@ -8,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -42,14 +42,6 @@ void qd_connection_manager_free(qd_conne
/**
- * Load the Listeners and Connections from the configuration file.
- *
- * @param qd The dispatch handle returned by qd_dispatch.
- */
-void qd_connection_manager_configure(qd_dispatch_t *qd);
-
-
-/**
* Start the configured Listeners and Connectors
*
* Note that on-demand connectors are not started by this function.
Modified: qpid/dispatch/trunk/include/qpid/dispatch/dispatch.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/include/qpid/dispatch/dispatch.h?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/include/qpid/dispatch/dispatch.h (original)
+++ qpid/dispatch/trunk/include/qpid/dispatch/dispatch.h Tue Jul 8 20:31:13 2014
@@ -20,6 +20,9 @@
*/
#include <qpid/dispatch/error.h>
+
+typedef struct qd_entity_t qd_entity_t;
+
/**
* @defgroup dispatch
*
@@ -35,7 +38,7 @@ typedef struct qd_dispatch_t qd_dispatch
* @param python_pkgdir The path to the Python files.
* @return A handle to be used in API calls for this instance.
*/
-qd_dispatch_t *qd_dispatch(const char *python_pkgdir);
+qd_dispatch_t *qd_dispatch(const char *python_pkgdir, const char *qpid_dispatch_lib);
/**
@@ -46,15 +49,6 @@ qd_dispatch_t *qd_dispatch(const char *p
void qd_dispatch_free(qd_dispatch_t *dispatch);
/**
- * Extend the schema for the configuration file prior to loading and
- * parsing the file.
- *
- * @param dispatch The dispatch handle returned by qd_dispatch
- * @param text Python text used to extend the schema structure in the config reader
- */
-void qd_dispatch_extend_config_schema(qd_dispatch_t *dispatch, const char* text);
-
-/**
* Load the configuration file.
*
* @param dispatch The dispatch handle returned by qd_dispatch
@@ -63,20 +57,21 @@ void qd_dispatch_extend_config_schema(qd
qd_error_t qd_dispatch_load_config(qd_dispatch_t *dispatch, const char *config_path);
/**
- * Configure the AMQP container from the parsed configuration file.
- * If this is not called, the container will take on default settings.
+ * Configure the AMQP container from a configuration entity.
*
* @param dispatch The dispatch handle returned by qd_dispatch
+ * @param entity The configuration entity.
*/
-void qd_dispatch_configure_container(qd_dispatch_t *dispatch);
+qd_error_t qd_dispatch_configure_container(qd_dispatch_t *dispatch, qd_entity_t *entity);
/**
- * Configure the router node from the parsed configuration file.
+ * Configure the router node from a configuration entity.
* If this is not called, the router will run in ENDPOINT mode.
*
- * @param dispatch The dispatch handle returned by qd_dispatch
+ * @param dispatch The dispatch handle returned by qd_dispatch.
+ * @param entity The configuration entity.
*/
-void qd_dispatch_configure_router(qd_dispatch_t *dispatch);
+qd_error_t qd_dispatch_configure_router(qd_dispatch_t *dispatch, qd_entity_t *entity);
/**
* Prepare Dispatch for operation. This must be called prior to
@@ -84,16 +79,17 @@ void qd_dispatch_configure_router(qd_dis
*
* @param dispatch The dispatch handle returned by qd_dispatch
*/
-void qd_dispatch_prepare(qd_dispatch_t *dispatch);
+qd_error_t qd_dispatch_prepare(qd_dispatch_t *dispatch);
/**
- * Configure the server connectors and listeners from the
- * parsed configuration file. This must be called after the
- * call to qd_dispatch_prepare completes.
- *
- * @param dispatch The dispatch handle returned by qd_dispatch
+ * Configure an address, must be called after qd_dispatch_prepare
+ */
+qd_error_t qd_dispatch_configure_address(qd_dispatch_t *dispatch, qd_entity_t *entity);
+
+/**
+ * Configure a waypoint, must be called after qd_dispatch_prepare
*/
-void qd_dispatch_post_configure_connections(qd_dispatch_t *dispatch);
+qd_error_t qd_dispatch_configure_waypoint(qd_dispatch_t *dispatch, qd_entity_t *entity);
/**
* \brief Configure the logging module from the
@@ -102,7 +98,7 @@ void qd_dispatch_post_configure_connecti
*
* @param dispatch The dispatch handle returned by qd_dispatch
*/
-void qd_dispatch_configure_logging(qd_dispatch_t *qd);
+qd_error_t qd_dispatch_configure_logging(qd_dispatch_t *qd);
/**
* @}
Modified: qpid/dispatch/trunk/include/qpid/dispatch/error.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/include/qpid/dispatch/error.h?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/include/qpid/dispatch/error.h (original)
+++ qpid/dispatch/trunk/include/qpid/dispatch/error.h Tue Jul 8 20:31:13 2014
@@ -35,7 +35,7 @@
*/
// NOTE: If you modify this enum, you must update error_names in error.c
typedef enum {
- QD_ERROR_NONE = 0,
+ QD_ERROR_NONE,
QD_ERROR_NOT_FOUND,
QD_ERROR_ALREADY_EXISTS,
QD_ERROR_ALLOC,
@@ -43,7 +43,7 @@ typedef enum {
QD_ERROR_PYTHON, ///< Error from python code.
QD_ERROR_CONFIG, ///< Error in configuration
- QD_ERROR_COUNT ///< Not an error, marks the end of the enum
+ QD_ERROR_ENUM_COUNT ///< Not an error, marks the end of the enum
} qd_error_t;
/**
@@ -85,4 +85,7 @@ extern const int QD_ERROR_MAX;
*/
qd_error_t qd_error_py();
+#define QD_ERROR_RET() do { if (qd_error_code()) return qd_error_code(); } while(0)
+#define QD_ERROR_PY_RET() do { if (qd_error_py()) return qd_error_code(); } while(0)
+
#endif
Modified: qpid/dispatch/trunk/include/qpid/dispatch/log.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/include/qpid/dispatch/log.h?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/include/qpid/dispatch/log.h (original)
+++ qpid/dispatch/trunk/include/qpid/dispatch/log.h Tue Jul 8 20:31:13 2014
@@ -8,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
Modified: qpid/dispatch/trunk/include/qpid/dispatch/python_embedded.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/include/qpid/dispatch/python_embedded.h?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/include/qpid/dispatch/python_embedded.h (original)
+++ qpid/dispatch/trunk/include/qpid/dispatch/python_embedded.h Tue Jul 8 20:31:13 2014
@@ -8,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -30,7 +30,8 @@
* any other call into this module is invoked.
*/
void qd_python_initialize(qd_dispatch_t *qd,
- const char *python_pkgdir);
+ const char *python_pkgdir,
+ const char *qpid_dispatch_lib);
/**
* Finalize the embedded-python subsystem. After this is called, there
Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/__init__.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/__init__.py?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/__init__.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/__init__.py Tue Jul 8 20:31:13 2014
@@ -18,7 +18,7 @@
#
"""Management package"""
-from .entity import Entity, EntityList
-from .node import Url, Node, ManagementError
-from .qdrouter import QdSchema, QdConfig
-from .schema import Type, BooleanType, EnumType, AttributeType, AttributeTypeHolder, IncludeType, EntityType, Schema, schema_file, ValidationError
+from .entity import *
+from .node import *
+from .qdrouter import *
+from .schema import *
Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/entity.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/entity.py?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/entity.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/entity.py Tue Jul 8 20:31:13 2014
@@ -63,5 +63,3 @@ class EntityList(list):
def __getattr__(self, name):
return self.get(type=name)
-
-__all__ = [ Entity, EntityList ]
Added: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/libqpid_dispatch.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/libqpid_dispatch.py?rev=1608947&view=auto
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/libqpid_dispatch.py (added)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/libqpid_dispatch.py Tue Jul 8 20:31:13 2014
@@ -0,0 +1,83 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License
+#
+
+"""Access to fucntions in libqpid-dispatch.so"""
+
+# TODO aconway 2014-06-19: this is all linux specific.
+
+import ctypes, os, glob
+from ctypes import c_char_p, c_void_p, c_long, py_object
+try:
+ from dispatch import QPID_DISPATCH_LIB
+except:
+ QPID_DISPATCH_LIB = None
+
+class CError(Exception):
+ """Exception raised if there is an error in a C call"""
+ pass
+
+class QdDll(ctypes.PyDLL):
+ """
+ Load the library, set up function prototypes.
+
+ NOTE: We use the python calling convention because the C library
+ internally makes python calls.
+ """
+ _instance = None
+ @classmethod
+ def instance(cls):
+ if not cls._instance:
+ cls._instance = QdDll()
+ return cls._instance
+
+ def __init__(self):
+ lib = QPID_DISPATCH_LIB or os.environ.get('QPID_DISPATCH_LIB')
+ assert lib
+ super(QdDll, self).__init__(lib)
+
+ # Types
+ self.qd_dispatch_p = ctypes.c_void_p # Use void* for qd_dispatch_t*
+
+ # No check on qd_error_* functions, it would be recursive
+ self._prototype(self.qd_error_code, c_long, [], check=False)
+ self._prototype(self.qd_error_message, c_char_p, [], check=False)
+
+ self._prototype(self.qd_log_entity, c_long, [py_object])
+ self._prototype(self.qd_dispatch_configure_container, None, [self.qd_dispatch_p, py_object])
+ self._prototype(self.qd_dispatch_configure_router, None, [self.qd_dispatch_p, py_object])
+ self._prototype(self.qd_dispatch_prepare, None, [self.qd_dispatch_p])
+ self._prototype(self.qd_dispatch_configure_listener, None, [self.qd_dispatch_p, py_object])
+ self._prototype(self.qd_dispatch_configure_connector, None, [self.qd_dispatch_p, py_object])
+ self._prototype(self.qd_dispatch_configure_address, None, [self.qd_dispatch_p, py_object])
+ self._prototype(self.qd_dispatch_configure_waypoint, None, [self.qd_dispatch_p, py_object])
+ self._prototype(self.qd_connection_manager_start, None, [self.qd_dispatch_p])
+ self._prototype(self.qd_waypoint_activate_all, None, [self.qd_dispatch_p])
+
+ def _errcheck(self, result, func, args):
+ if self.qd_error_code():
+ raise CError(self.qd_error_message())
+
+ def _prototype(self, f, restype, argtypes, check=True):
+ """Set up the return and argument types and the error checker for a ctypes function"""
+ f.restype = restype
+ f.argtypes = argtypes
+ if check: f.errcheck = self._errcheck
+
+def instance():
+ return QdDll.instance()
Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.json
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.json?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.json (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.json Tue Jul 8 20:31:13 2014
@@ -115,7 +115,8 @@
"type": [
"standalone",
"interior",
- "edge"
+ "edge",
+ "endpoint"
],
"default": "standalone",
"description": "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. In interior mode, the router operates in cooreration with other interior routers in an interconnected network. In edge mode, 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. "
@@ -221,6 +222,7 @@
"DEFAULT",
"ERROR"
],
+ "required": true,
"description": "Module to configure logging level. The special module 'DEFAULT' specifies logging for modules that don't have explicit log sections."
},
"level": {
Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/qdrouter.py Tue Jul 8 20:31:13 2014
@@ -25,7 +25,7 @@ import json, re, sys
import schema
from entity import EntityList, Entity, OrderedDict
from copy import copy
-
+import libqpid_dispatch
class QdSchema(schema.Schema):
"""
@@ -153,6 +153,9 @@ class QdConfig(EntityList):
def section_count(self, section):
return len(self.get(type=section))
+ def entity(self, section, index):
+ return self.get(type=section)[index]
+
def value(self, section, index, key, convert=lambda x: x):
"""
@return: Value at section, index, key or None if absent.
@@ -162,3 +165,26 @@ class QdConfig(EntityList):
if len(entities) <= index or key not in entities[index]:
return None
return convert(entities[index][key])
+
+
+def configure_dispatch(dispatch, filename):
+ """Called by C router code to load configuration file and do configuration"""
+ qd = libqpid_dispatch.instance()
+ dispatch = qd.qd_dispatch_p(dispatch)
+ config = QdConfig(filename)
+ # Configure any DEFAULT log entities first so we can report errors in non-
+ # default log configurations to the correct place.
+ for l in config.log:
+ if l.module.upper() == 'DEFAULT': qd.qd_log_entity(l)
+ for l in config.log:
+ if l.module.upper() != 'DEFAULT': qd.qd_log_entity(l)
+ qd.qd_dispatch_configure_container(dispatch, config.container[0])
+ qd.qd_dispatch_configure_router(dispatch, config.router[0])
+ qd.qd_dispatch_prepare(dispatch)
+ # Note must configure addresses, waypoints, listeners and connectors after qd_dispatch_prepare
+ for a in config.get(type='fixed-address'): qd.qd_dispatch_configure_address(dispatch, a)
+ for w in config.waypoint: qd.qd_dispatch_configure_waypoint(dispatch, w)
+ for l in config.listener: qd.qd_dispatch_configure_listener(dispatch, l)
+ for c in config.connector: qd.qd_dispatch_configure_connector(dispatch, c)
+ qd.qd_connection_manager_start(dispatch);
+ qd.qd_waypoint_activate_all(dispatch);
Modified: qpid/dispatch/trunk/python/qpid_dispatch_internal/management/schema.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/python/qpid_dispatch_internal/management/schema.py?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/python/qpid_dispatch_internal/management/schema.py (original)
+++ qpid/dispatch/trunk/python/qpid_dispatch_internal/management/schema.py Tue Jul 8 20:31:13 2014
@@ -93,6 +93,19 @@ class BooleanType(Type):
except:
raise ValidationError("Invalid Boolean value '%r'"%value)
+class EnumValue(str):
+ """A string that convets to an integer value via int()"""
+
+ def __new__(cls, name, value):
+ s = super(EnumValue, cls).__new__(cls, name)
+ setattr(s, 'value', value)
+ return s
+
+ def __int__(self): return self.value
+ def __eq__(self, x): return str(self) == x or int(self) == x
+ def __ne__(self, x): return not self == x
+ def __repr__(self): return "EnumValue('%s', %s)"%(str(self), int(self))
+
class EnumType(Type):
"""An enumerated type"""
@@ -104,27 +117,19 @@ class EnumType(Type):
super(EnumType, self).__init__("enum%s"%([str(t) for t in tags]), int)
self.tags = tags
- def validate(self, value, enum_as_int=False, **kwargs):
+ def validate(self, value, **kwargs):
"""
@param value: May be a string from the set of enum tag strings or anything
that can convert to an int - in which case it must be in the enum range.
- @keyword enum_as_int: If true the return value will be an int.
@param kwargs: See L{Schema.validate}
- @return: If enum_as_int is True the int value of the enum, othewise the enum tag string.
+ @return: An EnumValue.
"""
if value in self.tags:
- if enum_as_int:
- return self.tags.index(value)
- else:
- return value
+ return EnumValue(value, self.tags.index(value))
else:
try:
i = int(value)
- if 0 <= i and i < len(self.tags):
- if enum_as_int:
- return i
- else:
- return self.tags[i]
+ return EnumValue(self.tags[i], i)
except (ValueError, IndexError):
pass
raise ValidationError("Invalid value for %s: '%r'"%(self.name, value))
@@ -339,7 +344,11 @@ class EntityType(AttributeTypeHolder):
return d
def resolve(self, value, attributes):
- """Resolve a $ or $$ reference"""
+ """
+ Resolve a $ or $$ reference.
+ $attr refers to another attribute.
+ $$name refers to a value in EntityType.refs
+ """
values = [value]
while True:
if isinstance(value, basestring) and value.startswith('$$'):
@@ -376,18 +385,21 @@ class EntityType(AttributeTypeHolder):
drop_none()
- # Add missing values
- for attr in self.attributes.itervalues():
- if attr.name not in attributes:
- value = attr.missing_value(**kwargs)
- if value is not None: attributes[attr.name] = value
-
- # Validate attributes.
- for name, value in attributes.iteritems():
- if name not in self.attributes:
- raise ValidationError("%s has unknown attribute '%s'"%(self, name))
- attributes[name] = self.attributes[name].validate(
- value, lambda v: self.resolve(v, attributes), **kwargs)
+ try:
+ # Add missing values
+ for attr in self.attributes.itervalues():
+ if attr.name not in attributes:
+ value = attr.missing_value(**kwargs)
+ if value is not None: attributes[attr.name] = value
+
+ # Validate attributes.
+ for name, value in attributes.iteritems():
+ if name not in self.attributes:
+ raise ValidationError("%s has unknown attribute '%s'"%(self, name))
+ attributes[name] = self.attributes[name].validate(
+ value, lambda v: self.resolve(v, attributes), **kwargs)
+ except ValidationError, e:
+ raise ValidationError, "Entity '%s': %s"%(self.name, e), sys.exc_info()[2]
drop_none()
@@ -440,12 +452,11 @@ class Schema(object):
'includes': OrderedDict((k, v.dump()) for k, v in self.includes.iteritems()),
'entity_types': OrderedDict((k, v.dump()) for k, v in self.entity_types.iteritems())}
- def validate(self, entities, enum_as_int=False, check_required=True, add_default=True, check_unique=True, check_singleton=True):
+ def validate(self, entities, check_required=True, add_default=True, check_unique=True, check_singleton=True):
"""
Validate entities, verify singleton entities and unique attributes are unique.
@param entities: List of L{Entity}
- @keyword enum_as_int: Represent enums as int rather than string.
@keyword check_required: Raise exception if required attributes are missing.
@keyword add_default: Add defaults for missing attributes.
@keyword check_unique: Raise exception if unique attributes are duplicated.
@@ -458,7 +469,6 @@ class Schema(object):
for e in entities:
et = self.entity_types[e.type]
et.validate(e,
- enum_as_int=enum_as_int,
check_required=check_required,
add_default=add_default,
check_unique=check_unique,
Modified: qpid/dispatch/trunk/router/src/config.h.in
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/router/src/config.h.in?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/router/src/config.h.in (original)
+++ qpid/dispatch/trunk/router/src/config.h.in Tue Jul 8 20:31:13 2014
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -19,3 +19,6 @@
#cmakedefine DEFAULT_CONFIG_PATH "${DEFAULT_CONFIG_PATH}"
#cmakedefine QPID_DISPATCH_HOME_INSTALLED "${QPID_DISPATCH_HOME_INSTALLED}"
+
+// Use #define, not #cmakedefine because SO_VERSION_MAJOR may be 0 which #cmakedefine considers unset.
+#define QPID_DISPATCH_LIB "libqpid-dispatch.so.${SO_VERSION_MAJOR}"
Modified: qpid/dispatch/trunk/router/src/main.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/router/src/main.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/router/src/main.c (original)
+++ qpid/dispatch/trunk/router/src/main.c Tue Jul 8 20:31:13 2014
@@ -88,6 +88,7 @@ int main(int argc, char **argv)
#define DEFAULT_DISPATCH_PYTHON_DIR QPID_DISPATCH_HOME_INSTALLED "/python"
const char *config_path = DEFAULT_CONFIG_PATH;
const char *python_pkgdir = DEFAULT_DISPATCH_PYTHON_DIR;
+ const char *qpid_dispatch_lib = QPID_DISPATCH_LIB;
static struct option long_options[] = {
{"config", required_argument, 0, 'c'},
@@ -126,22 +127,13 @@ int main(int argc, char **argv)
qd_error_clear();
- dispatch = qd_dispatch(python_pkgdir);
- log_source = qd_log_source("MAIN"); /* Logging is initialized by qd_dispatch. */
+ dispatch = qd_dispatch(python_pkgdir, qpid_dispatch_lib);
check();
+ log_source = qd_log_source("MAIN"); /* Logging is initialized by qd_dispatch. */
qd_dispatch_load_config(dispatch, config_path);
check();
- qd_log_configure(dispatch);
- check();
- qd_dispatch_configure_container(dispatch);
- check();
- qd_dispatch_configure_router(dispatch);
- check();
- qd_dispatch_prepare(dispatch);
- check();
- qd_dispatch_post_configure_connections(dispatch);
- check();
+ (void)server_signal_handler; (void)thread_start_handler;(void)signal_handler;
qd_server_set_signal_handler(dispatch, server_signal_handler, 0);
qd_server_set_start_handler(dispatch, thread_start_handler, 0);
Added: qpid/dispatch/trunk/src/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/CMakeLists.txt?rev=1608947&view=auto
==============================================================================
--- qpid/dispatch/trunk/src/CMakeLists.txt (added)
+++ qpid/dispatch/trunk/src/CMakeLists.txt Tue Jul 8 20:31:13 2014
@@ -0,0 +1,82 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+##
+
+# Generate code from the management schema.
+set(GENERATED_SOURCES
+ schema_enum.h
+ schema_enum.c
+ )
+
+file (GLOB_RECURSE GENERATOR_DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/schema_c.py
+ ${CMAKE_SOURCE_DIR}/python/qpid_router_internal/management/*.py
+ ${CMAKE_SOURCE_DIR}/python/qpid_router_internal/management/qdrouterd.json)
+
+add_custom_command (
+ OUTPUT ${GENERATED_SOURCES}
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/tests/run.py -s ${CMAKE_CURRENT_SOURCE_DIR}/schema_c.py
+ DEPENDS ${GENERATOR_DEPENDS})
+
+add_custom_target(generate ALL DEPENDS ${GENERATED_SOURCES})
+
+# Build the qpid-dispatch library.
+set(qpid_dispatch_SOURCES
+ agent.c
+ alloc.c
+ amqp.c
+ bitmask.c
+ buffer.c
+ error.c
+ compose.c
+ connection_manager.c
+ container.c
+ dispatch.c
+ entity.c
+ hash.c
+ iovec.c
+ iterator.c
+ log.c
+ message.c
+ parse.c
+ posix/threading.c
+ python_embedded.c
+ router_agent.c
+ router_config.c
+ router_node.c
+ router_pynode.c
+ schema_enum.c
+ server.c
+ timer.c
+ waypoint.c
+ )
+
+set_property(
+ SOURCE python_embedded.c router_pynode.c
+ PROPERTY COMPILE_FLAGS -Wno-strict-aliasing
+ )
+
+add_library(qpid-dispatch SHARED ${qpid_dispatch_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})
Modified: qpid/dispatch/trunk/src/connection_manager.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/connection_manager.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/connection_manager.c (original)
+++ qpid/dispatch/trunk/src/connection_manager.c Tue Jul 8 20:31:13 2014
@@ -22,12 +22,10 @@
#include <qpid/dispatch/agent.h>
#include "dispatch_private.h"
#include "server_private.h"
+#include "entity_private.h"
+#include "schema_enum.h"
#include <string.h>
-static const char *CONF_LISTENER = "listener";
-static const char *CONF_CONNECTOR = "connector";
-
-
struct qd_config_listener_t {
DEQ_LINKS(qd_config_listener_t);
qd_listener_t *listener;
@@ -58,93 +56,95 @@ struct qd_connection_manager_t {
};
-static void load_server_config(qd_dispatch_t *qd, qd_server_config_t *config, const char *section, int i)
+// True if entity has any of attributes.
+static bool has_attrs(qd_entity_t *entity, const char **attributes, int n) {
+ for (int i = 0; i < n; ++i)
+ if (qd_entity_has(entity, attributes[i])) return true;
+ return false;
+}
+
+static const char *ssl_attributes[] = {
+ "allow-unsecured", "cert-file", "key-file", "password", "cert-db",
+ "trusted-certs", "require-peer-auth"
+};
+static const int ssl_attributes_count = sizeof(ssl_attributes)/sizeof(ssl_attributes[0]);
+
+static void qd_server_config_free(qd_server_config_t *cf)
+{
+ if (!cf) return;
+ free(cf->host);
+ free(cf->port);
+ free(cf->role);
+ free(cf->sasl_mechanisms);
+ if (cf->ssl_enabled) {
+ free(cf->ssl_certificate_file);
+ free(cf->ssl_private_key_file);
+ free(cf->ssl_password);
+ free(cf->ssl_trusted_certificate_db);
+ free(cf->ssl_trusted_certificates);
+ }
+ memset(cf, 0, sizeof(*cf));
+}
+
+#define CHECK() if (qd_error_code()) goto error
+static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *config, qd_entity_t* entity)
{
- config->host = qd_config_item_value_string(qd, section, i, "addr");
- config->port = qd_config_item_value_string(qd, section, i, "port");
- config->role = qd_config_item_value_string(qd, section, i, "role");
- config->max_frame_size = qd_config_item_value_int(qd, section, i, "max-frame-size");
- config->sasl_mechanisms =
- qd_config_item_value_string(qd, section, i, "sasl-mechanisms");
- config->ssl_enabled =
- qd_config_item_value_bool(qd, section, i, "ssl-profile");
+ qd_error_clear();
+ memset(config, 0, sizeof(*config));
+ config->host = qd_entity_string(entity, "addr"); CHECK();
+ config->port = qd_entity_string(entity, "port"); CHECK();
+ config->role = qd_entity_string(entity, "role"); CHECK();
+ config->max_frame_size = qd_entity_long(entity, "max-frame-size"); CHECK();
+ config->sasl_mechanisms = qd_entity_string(entity, "sasl-mechanisms"); CHECK();
+ config->ssl_enabled = has_attrs(entity, ssl_attributes, ssl_attributes_count);
if (config->ssl_enabled) {
config->ssl_server = 1;
- config->ssl_allow_unsecured_client =
- qd_config_item_value_bool(qd, section, i, "allow-unsecured");
- config->ssl_certificate_file =
- qd_config_item_value_string(qd, section, i, "cert-file");
- config->ssl_private_key_file =
- qd_config_item_value_string(qd, section, i, "key-file");
- config->ssl_password =
- qd_config_item_value_string(qd, section, i, "password");
- config->ssl_trusted_certificate_db =
- qd_config_item_value_string(qd, section, i, "cert-db");
- config->ssl_trusted_certificates =
- qd_config_item_value_string(qd, section, i, "trusted-certs");
- config->ssl_require_peer_authentication =
- qd_config_item_value_bool(qd, section, i, "require-peer-auth");
+ config->ssl_allow_unsecured_client = qd_entity_opt_bool(entity, "allow-unsecured", false); CHECK();
+ config->ssl_certificate_file = qd_entity_opt_string(entity, "cert-file", 0); CHECK();
+ config->ssl_private_key_file = qd_entity_opt_string(entity, "key-file", 0); CHECK();
+ config->ssl_trusted_certificate_db = qd_entity_opt_string(entity, "cert-db", 0); CHECK();
+ config->ssl_trusted_certificates = qd_entity_opt_string(entity, "trusted-certs", 0); CHECK();
}
-}
+ return QD_ERROR_NONE;
+ error:
+ qd_server_config_free(config);
+ return qd_error_code();
+}
-static void configure_listeners(qd_dispatch_t *qd)
+void qd_dispatch_configure_listener(qd_dispatch_t *qd, qd_entity_t *entity)
{
- int count;
qd_connection_manager_t *cm = qd->connection_manager;
-
- if (!qd->config || !cm) {
- qd_log(cm->log_source, QD_LOG_ERROR, "Cannot configure listeners%s%s",
- (qd->config ? "" : ", no configuration"),
- (cm ? "" : ", no connection manager"));
- assert(false);
- return;
- }
-
- count = qd_config_item_count(qd, CONF_LISTENER);
- for (int i = 0; i < count; i++) {
- qd_config_listener_t *cl = NEW(qd_config_listener_t);
- cl->listener = 0;
- load_server_config(qd, &cl->configuration, CONF_LISTENER, i);
- DEQ_ITEM_INIT(cl);
- DEQ_INSERT_TAIL(cm->config_listeners, cl);
- qd_log(cm->log_source, QD_LOG_INFO, "Configured Listener: %s:%s role=%s",
- cl->configuration.host, cl->configuration.port, cl->configuration.role);
- }
+ qd_config_listener_t *cl = NEW(qd_config_listener_t);
+ cl->listener = 0;
+ load_server_config(qd, &cl->configuration, entity);
+ DEQ_ITEM_INIT(cl);
+ DEQ_INSERT_TAIL(cm->config_listeners, cl);
+ qd_log(cm->log_source, QD_LOG_INFO, "Configured Listener: %s:%s role=%s",
+ cl->configuration.host, cl->configuration.port, cl->configuration.role);
}
-static void configure_connectors(qd_dispatch_t *qd)
+qd_error_t qd_dispatch_configure_connector(qd_dispatch_t *qd, qd_entity_t *entity)
{
- int count;
+ qd_error_clear();
qd_connection_manager_t *cm = qd->connection_manager;
-
- if (!qd->config || !cm) {
- assert(false);
- return;
- }
-
- count = qd_config_item_count(qd, CONF_CONNECTOR);
- for (int i = 0; i < count; i++) {
- qd_config_connector_t *cc = NEW(qd_config_connector_t);
- cc->context = 0;
- cc->connector = 0;
- cc->connector_name = 0;
- cc->started = false;
- load_server_config(qd, &cc->configuration, CONF_CONNECTOR, i);
- DEQ_ITEM_INIT(cc);
- if (strcmp(cc->configuration.role, "on-demand") == 0) {
- cc->connector_name =
- qd_config_item_value_string(qd, CONF_CONNECTOR, i, "name");
- DEQ_INSERT_TAIL(cm->on_demand_connectors, cc);
- qd_log(cm->log_source, QD_LOG_INFO, "Configured on-demand connector: %s:%s name=%s",
- cc->configuration.host, cc->configuration.port, cc->connector_name);
- } else {
- DEQ_INSERT_TAIL(cm->config_connectors, cc);
- qd_log(cm->log_source, QD_LOG_INFO, "Configured Connector: %s:%s role=%s",
- cc->configuration.host, cc->configuration.port, cc->configuration.role);
- }
+ qd_config_connector_t *cc = NEW(qd_config_connector_t);
+ memset(cc, 0, sizeof(*cc));
+ if (load_server_config(qd, &cc->configuration, entity))
+ return qd_error_code();
+ DEQ_ITEM_INIT(cc);
+ if (strcmp(cc->configuration.role, "on-demand") == 0) {
+ cc->connector_name = qd_entity_string(entity, "name"); QD_ERROR_RET();
+ DEQ_INSERT_TAIL(cm->on_demand_connectors, cc);
+ qd_log(cm->log_source, QD_LOG_INFO, "Configured on-demand connector: %s:%s name=%s",
+ cc->configuration.host, cc->configuration.port, cc->connector_name);
+ } else {
+ DEQ_INSERT_TAIL(cm->config_connectors, cc);
+ qd_log(cm->log_source, QD_LOG_INFO, "Configured Connector: %s:%s role=%s",
+ cc->configuration.host, cc->configuration.port, cc->configuration.role);
}
+ return QD_ERROR_NONE;
}
@@ -164,23 +164,6 @@ qd_connection_manager_t *qd_connection_m
}
-static void qd_connection_manager_config_free(qd_server_config_t *cf)
-{
- if (!cf) return;
- free(cf->host);
- free(cf->port);
- free(cf->role);
- free(cf->sasl_mechanisms);
- if (cf->ssl_enabled) {
- free(cf->ssl_certificate_file);
- free(cf->ssl_private_key_file);
- free(cf->ssl_password);
- free(cf->ssl_trusted_certificate_db);
- free(cf->ssl_trusted_certificates);
- }
-}
-
-
void qd_connection_manager_free(qd_connection_manager_t *cm)
{
if (!cm) return;
@@ -188,7 +171,7 @@ void qd_connection_manager_free(qd_conne
while (cl) {
DEQ_REMOVE_HEAD(cm->config_listeners);
qd_server_listener_free(cl->listener);
- qd_connection_manager_config_free(&cl->configuration);
+ qd_server_config_free(&cl->configuration);
free(cl);
cl = DEQ_HEAD(cm->config_listeners);
}
@@ -197,7 +180,7 @@ void qd_connection_manager_free(qd_conne
while(cc) {
DEQ_REMOVE_HEAD(cm->config_connectors);
qd_server_connector_free(cc->connector);
- qd_connection_manager_config_free(&cc->configuration);
+ qd_server_config_free(&cc->configuration);
free(cc);
cc = DEQ_HEAD(cm->config_connectors);
}
@@ -207,20 +190,13 @@ void qd_connection_manager_free(qd_conne
DEQ_REMOVE_HEAD(cm->on_demand_connectors);
if (odc->connector)
qd_server_connector_free(odc->connector);
- qd_connection_manager_config_free(&odc->configuration);
+ qd_server_config_free(&odc->configuration);
free(odc);
odc = DEQ_HEAD(cm->on_demand_connectors);
}
}
-void qd_connection_manager_configure(qd_dispatch_t *qd)
-{
- configure_listeners(qd);
- configure_connectors(qd);
-}
-
-
void qd_connection_manager_start(qd_dispatch_t *qd)
{
qd_config_listener_t *cl = DEQ_HEAD(qd->connection_manager->config_listeners);
Modified: qpid/dispatch/trunk/src/dispatch.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/dispatch.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/dispatch.c (original)
+++ qpid/dispatch/trunk/src/dispatch.c Tue Jul 8 20:31:13 2014
@@ -27,6 +27,8 @@
#include "router_private.h"
#include "waypoint_private.h"
#include "message_private.h"
+#include "entity_private.h"
+#include "static_assert.h"
/**
* Private Function Prototypes
@@ -44,90 +46,79 @@ qd_agent_t *qd_agent(qd_dispatch_t *
void qd_agent_free(qd_agent_t *agent);
void qd_error_initialize();
-static const char *CONF_CONTAINER = "container";
-static const char *CONF_ROUTER = "router";
-
-
-qd_dispatch_t *qd_dispatch(const char *python_pkgdir)
+qd_dispatch_t *qd_dispatch(const char *python_pkgdir, const char *qpid_dispatch_lib)
{
+ qd_error_clear();
qd_dispatch_t *qd = NEW(qd_dispatch_t);
-
memset(qd, 0, sizeof(qd_dispatch_t));
// alloc, log and error have to be initialized before any module.
qd_alloc_initialize();
qd_log_initialize();
qd_error_initialize();
+ if (qd_error_code()) return 0;
qd->router_area = strdup("0");
qd->router_id = strdup("0");
qd->router_mode = QD_ROUTER_MODE_ENDPOINT;
- qd_python_initialize(qd, python_pkgdir);
- qd_config_initialize();
+ qd_python_initialize(qd, python_pkgdir, qpid_dispatch_lib);
+ if (qd_error_code()) { qd_dispatch_free(qd); return 0; }
qd_message_initialize();
- qd->config = qd_config();
-
- assert(qd->config);
-
+ if (qd_error_code()) { qd_dispatch_free(qd); return 0; }
return qd;
}
+// We pass pointers as longs via the python interface, make sure this is safe.
+STATIC_ASSERT(sizeof(long) >= sizeof(void*), pointer_is_bigger_than_long);
+
qd_error_t qd_dispatch_load_config(qd_dispatch_t *qd, const char *config_path)
{
- return qd_config_read(qd->config, config_path);
+ PyObject *module = 0, *configure_dispatch = 0, *result = 0;
+ bool ok =
+ (module = PyImport_ImportModule("qpid_dispatch_internal.management")) &&
+ (configure_dispatch = PyObject_GetAttrString(module, "configure_dispatch")) &&
+ (result = PyObject_CallFunction(configure_dispatch, "(ls)", (long)qd, config_path));
+ Py_XDECREF(module);
+ Py_XDECREF(configure_dispatch);
+ Py_XDECREF(result);
+ return ok ? QD_ERROR_NONE : qd_error_py();
}
-void qd_dispatch_configure_container(qd_dispatch_t *qd)
+qd_error_t qd_dispatch_configure_container(qd_dispatch_t *qd, qd_entity_t *entity)
{
- if (qd->config) {
- int count = qd_config_item_count(qd, CONF_CONTAINER);
- if (count == 1) {
- qd->thread_count = qd_config_item_value_int(qd, CONF_CONTAINER, 0, "worker-threads");
- qd->container_name = qd_config_item_value_string(qd, CONF_CONTAINER, 0, "container-name");
- }
- }
-
- if (qd->thread_count == 0)
- qd->thread_count = 1;
-
- if (!qd->container_name)
- qd->container_name = "00000000-0000-0000-0000-000000000000"; // TODO - gen a real uuid
+ const char *default_name = "00000000-0000-0000-0000-000000000000";
+ qd->thread_count = qd_entity_opt_long(entity, "worker-threads", 1); QD_ERROR_RET();
+ qd->container_name = qd_entity_opt_string(entity, "container-name", default_name); QD_ERROR_RET();
+ return QD_ERROR_NONE;
}
-void qd_dispatch_configure_router(qd_dispatch_t *qd)
+qd_error_t qd_dispatch_configure_router(qd_dispatch_t *qd, qd_entity_t *entity)
{
- char *router_mode_str = 0;
-
- if (qd->config) {
- int count = qd_config_item_count(qd, CONF_ROUTER);
- if (count == 1) {
- router_mode_str = qd_config_item_value_string(qd, CONF_ROUTER, 0, "mode");
- free(qd->router_id);
- qd->router_id = qd_config_item_value_string(qd, CONF_ROUTER, 0, "router-id");
- }
- }
-
- if (router_mode_str && strcmp(router_mode_str, "standalone") == 0)
- qd->router_mode = QD_ROUTER_MODE_STANDALONE;
-
- if (router_mode_str && strcmp(router_mode_str, "interior") == 0)
- qd->router_mode = QD_ROUTER_MODE_INTERIOR;
-
- if (router_mode_str && strcmp(router_mode_str, "edge") == 0)
- qd->router_mode = QD_ROUTER_MODE_EDGE;
-
- if (!qd->router_id)
- qd->router_id = qd->container_name;
+ qd_error_clear();
+ free(qd->router_id);
+ qd->router_id = qd_entity_opt_string(entity, "router-id", qd->container_name);
+ QD_ERROR_RET();
+ qd->router_mode = qd_entity_long(entity, "mode");
+ return qd_error_code();
+}
- free(router_mode_str);
+qd_error_t qd_dispatch_configure_address(qd_dispatch_t *qd, qd_entity_t *entity) {
+ if (!qd->router) return qd_error(QD_ERROR_NOT_FOUND, "No router available");
+ qd_router_configure_address(qd->router, entity);
+ return qd_error_code();
}
+qd_error_t qd_dispatch_configure_waypoint(qd_dispatch_t *qd, qd_entity_t *entity) {
+ if (!qd->router) return qd_error(QD_ERROR_NOT_FOUND, "No router available");
+ qd_router_configure_waypoint(qd->router, entity);
+ return qd_error_code();
+}
-void qd_dispatch_prepare(qd_dispatch_t *qd)
+qd_error_t qd_dispatch_prepare(qd_dispatch_t *qd)
{
qd->server = qd_server(qd->thread_count, qd->container_name);
qd->container = qd_container(qd);
@@ -139,6 +130,7 @@ void qd_dispatch_prepare(qd_dispatch_t *
qd_connection_manager_setup_agent(qd);
qd_container_setup_agent(qd);
qd_router_setup_late(qd);
+ return qd_error_code();
}
@@ -146,9 +138,8 @@ void qd_dispatch_free(qd_dispatch_t *qd)
{
if (!qd) return;
free(qd->router_id);
+ free(qd->container_name);
free(qd->router_area);
- qd_config_free(qd->config);
- qd_config_finalize();
qd_connection_manager_free(qd->connection_manager);
qd_agent_free(qd->agent);
qd_router_free(qd->router);
@@ -158,11 +149,3 @@ void qd_dispatch_free(qd_dispatch_t *qd)
qd_alloc_finalize();
qd_python_finalize();
}
-
-
-void qd_dispatch_post_configure_connections(qd_dispatch_t *qd)
-{
- qd_connection_manager_configure(qd);
- qd_connection_manager_start(qd);
- qd_waypoint_activate_all(qd);
-}
Modified: qpid/dispatch/trunk/src/dispatch_private.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/dispatch_private.h?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/dispatch_private.h (original)
+++ qpid/dispatch/trunk/src/dispatch_private.h Tue Jul 8 20:31:13 2014
@@ -28,7 +28,6 @@ typedef struct qd_container_t qd_c
typedef struct qd_router_t qd_router_t;
typedef struct qd_agent_t qd_agent_t;
typedef struct qd_waypoint_t qd_waypoint_t;
-typedef struct qd_config_t qd_config_t;
typedef struct qd_router_link_t qd_router_link_t;
typedef struct qd_router_node_t qd_router_node_t;
typedef struct qd_router_ref_t qd_router_ref_t;
@@ -42,7 +41,6 @@ typedef struct qd_config_address_t qd_c
#include <qpid/dispatch/router.h>
#include <qpid/dispatch/connection_manager.h>
#include "server_private.h"
-#include "config_private.h"
#include "router_private.h"
@@ -51,7 +49,6 @@ struct qd_dispatch_t {
qd_container_t *container;
qd_router_t *router;
qd_agent_t *agent;
- qd_config_t *config;
qd_connection_manager_t *connection_manager;
int thread_count;
@@ -62,4 +59,3 @@ struct qd_dispatch_t {
};
#endif
-
Added: qpid/dispatch/trunk/src/entity.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/entity.c?rev=1608947&view=auto
==============================================================================
--- qpid/dispatch/trunk/src/entity.c (added)
+++ qpid/dispatch/trunk/src/entity.c Tue Jul 8 20:31:13 2014
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES 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/error.h>
+#include "dispatch_private.h"
+#include "entity_private.h"
+
+struct qd_entity_t {
+ PyObject py_object;
+};
+
+void qd_entity_free(qd_entity_t* entity) {
+ Py_XDECREF(entity);
+}
+
+bool qd_entity_has(qd_entity_t* entity, const char *attribute) {
+ return PyObject_HasAttrString((PyObject*)entity, attribute);
+}
+
+char *qd_entity_string(qd_entity_t *entity, const char* attribute) {
+ qd_error_clear();
+ PyObject *py_obj = PyObject_GetAttrString((PyObject*)entity, attribute);
+ PyObject *py_str = py_obj ? PyObject_Str(py_obj) : NULL;
+ char* str = py_str ? PyString_AsString(py_str) : NULL;
+ Py_XDECREF(py_obj);
+ Py_XDECREF(py_str);
+ if (str) return strdup(str);
+ qd_error_py();
+ return NULL;
+}
+
+long qd_entity_long(qd_entity_t *entity, const char* attribute) {
+ qd_error_clear();
+ PyObject *py_obj = PyObject_GetAttrString((PyObject*)entity, attribute);
+ long result = py_obj ? PyInt_AsLong(py_obj) : -1;
+ Py_XDECREF(py_obj);
+ qd_error_py();
+ return result;
+}
+
+bool qd_entity_bool(qd_entity_t *entity, const char* attribute) {
+ qd_error_clear();
+ PyObject *py_obj = PyObject_GetAttrString((PyObject*)entity, attribute);
+ bool result = py_obj ? PyObject_IsTrue(py_obj) : false;
+ Py_XDECREF(py_obj);
+ qd_error_py();
+ return result;
+}
+
+
+char *qd_entity_opt_string(qd_entity_t *entity, const char* attribute, const char* default_value)
+{
+ if (qd_entity_has(entity, attribute))
+ return qd_entity_string(entity, attribute);
+ else
+ return default_value ? strdup(default_value) : NULL;
+}
+
+long qd_entity_opt_long(qd_entity_t *entity, const char* attribute, long default_value) {
+ if (qd_entity_has(entity, attribute)) {
+ long result = qd_entity_long(entity, attribute);
+ if (!qd_error_code())
+ return result;
+ }
+ return default_value;
+}
+
+bool qd_entity_opt_bool(qd_entity_t *entity, const char* attribute, bool default_value) {
+ if (qd_entity_has(entity, attribute)) {
+ bool result = qd_entity_bool(entity, attribute);
+ if (!qd_error_code())
+ return result;
+ }
+ return default_value;
+}
Added: qpid/dispatch/trunk/src/entity_private.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/entity_private.h?rev=1608947&view=auto
==============================================================================
--- qpid/dispatch/trunk/src/entity_private.h (added)
+++ qpid/dispatch/trunk/src/entity_private.h Tue Jul 8 20:31:13 2014
@@ -0,0 +1,66 @@
+#ifndef ENTITY_PRIVATE_H
+#define ENTITY_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 <stdbool.h>
+
+typedef struct qd_entity_t qd_entity_t;
+
+typedef struct qd_dispatch_t qd_dispatch_t;
+
+void qd_entity_free(qd_entity_t* entity);
+
+/** True if the entity has this attribute. */
+bool qd_entity_has(qd_entity_t* entity, const char *attribute);
+
+/** Get a string valued attribute.
+ * @return New string value, caller must free.
+ * Return NULL and set qd_error if there is an error.
+ **/
+char *qd_entity_string(qd_entity_t *entity, const char* attribute);
+
+/** Get an integer valued attribute. Return -1 and set qd_error if there is an error. */
+long qd_entity_long(qd_entity_t *entity, const char* attribute);
+
+/** Get a boolean valued attribute. Return false and set qd_error if there is an error. */
+bool qd_entity_bool(qd_entity_t *entity, const char *attribute);
+
+
+/** Get a string valued attribute.
+ * @return New string value, caller must free.
+ * Return copy of default_value if attribute is missing or there is an error.
+ * Return NULL and set qd_error if there is an error (missing attribute is not an error.)
+ **/
+char *qd_entity_opt_string(qd_entity_t *entity, const char *attribute, const char *default_value);
+
+/** Get an integer valued attribute.
+ * @return Attribute value or default_value if attribute is missing.
+ * Set qd_error and return default_value if there is an error (missing attribute is not an error.)
+ */
+long qd_entity_opt_long(qd_entity_t *entity, const char *attribute, long default_value);
+
+/** Get a boolean valued attribute. Return false and set qd_error if there is an error.
+ * @return Attribute value or default_value if attribute is missing.
+ * Set qd_error and return default_value if there is an error (missing attribute is not an error.)
+ */
+bool qd_entity_opt_bool(qd_entity_t *entity, const char *attribute, bool default_value);
+
+
+#endif
Modified: qpid/dispatch/trunk/src/error.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/error.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/error.c (original)
+++ qpid/dispatch/trunk/src/error.c Tue Jul 8 20:31:13 2014
@@ -35,7 +35,8 @@ static const char *error_names[] = {
"Configuration"
};
-STATIC_ASSERT(sizeof(error_names)/sizeof(error_names[0]) == QD_ERROR_COUNT, error_names_wrong_size);
+STATIC_ASSERT(sizeof(error_names)/sizeof(error_names[0]) == QD_ERROR_ENUM_COUNT,
+ error_names_wrong_size);
#define ERROR_MAX QD_LOG_TEXT_MAX
const int QD_ERROR_MAX = ERROR_MAX;
@@ -56,7 +57,7 @@ qd_error_t qd_error(qd_error_t code, con
ts.error_code = code;
if (code) {
int i = 0;
- if (code < QD_ERROR_COUNT)
+ if (code < QD_ERROR_ENUM_COUNT)
i = snprintf(ts.error_message, ERROR_MAX,"%s: ", error_names[code]);
else
i = snprintf(ts.error_message, ERROR_MAX, "%d: ", code);
@@ -113,9 +114,21 @@ static void log_trace_py(PyObject *type,
Py_DECREF(locals);
if (result) {
- qd_log(log_source, level, "%s", PyString_AsString(result));
+ const char* trace = PyString_AsString(result);
+ if (strlen(trace) < QD_LOG_TEXT_MAX) {
+ qd_log(log_source, level, "%s", trace);
+ } else {
+ // Keep as much of the the tail of the trace as we can.
+ const char *tail = trace;
+ while (tail && strlen(tail) > QD_LOG_TEXT_MAX) {
+ tail = strchr(tail, '\n');
+ if (tail) ++tail;
+ }
+ qd_log(log_source, level, "Traceback truncated:\n%s", tail ? tail : "");
+ }
Py_DECREF(result);
}
+
}
qd_error_t qd_error_py() {
@@ -134,7 +147,7 @@ qd_error_t qd_error_py() {
Py_XDECREF(value_str);
Py_XDECREF(type_name);
- log_trace_py(type, value, trace, QD_LOG_DEBUG);
+ log_trace_py(type, value, trace, QD_LOG_ERROR);
Py_XDECREF(type);
Py_XDECREF(value);
Modified: qpid/dispatch/trunk/src/log.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/log.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/log.c (original)
+++ qpid/dispatch/trunk/src/log.c Tue Jul 8 20:31:13 2014
@@ -18,7 +18,7 @@
*/
#include "log_private.h"
-#include <qpid/dispatch/config.h>
+#include "entity_private.h"
#include <qpid/dispatch/ctools.h>
#include <qpid/dispatch/dispatch.h>
#include <qpid/dispatch/alloc.h>
@@ -312,7 +312,7 @@ void qd_log_initialize(void)
default_log_source = qd_log_source(SOURCE_DEFAULT);
// Only report errors until we have configured the logging system.
- default_log_source->mask = levels[ERROR].mask;
+ default_log_source->mask = levels[INFO].mask;
default_log_source->timestamp = 1;
default_log_source->sink = log_sink_lh(SINK_STDERR);
logging_log_source = qd_log_source(SOURCE_LOGGING);
@@ -328,37 +328,36 @@ void qd_log_finalize(void) {
log_sink_free_lh(DEQ_HEAD(sink_list));
}
-///@return 0,1 or -1 if not present
-static int get_optional_bool(const qd_dispatch_t *qd, const char* item, int i, const char* name) {
- if (!qd_config_item_exists(qd, item, i, name)) return -1;
- return qd_config_item_value_bool(qd, item, i, name);
-}
+qd_error_t qd_log_entity(qd_entity_t *entity) {
-#define ITEM_STRING(NAME) qd_config_item_value_string(qd, "log", i, NAME)
-#define ITEM_OPT_BOOL(NAME) get_optional_bool(qd, "log", i, NAME)
+ qd_error_clear();
+ char* module = qd_entity_string(entity, "module"); QD_ERROR_RET();
+ sys_mutex_lock(log_source_lock);
+ qd_log_source_t *src = qd_log_source_lh(module);
+ assert(src);
+ qd_log_source_t copy = *src;
+ sys_mutex_unlock(log_source_lock);
+ free(module);
-void qd_log_configure(const qd_dispatch_t *qd)
-{
- if (!qd) return;
- // Default to INFO now that we are configuring the logging system.
- default_log_source->mask = levels[INFO].mask;
- int count = qd_config_item_count(qd, "log");
- for (int i=0; i < count; i++) {
- sys_mutex_lock(log_source_lock);
- const char* module = ITEM_STRING("module");
- qd_log_source_t *src = qd_log_source_lh(module);
- src->mask = level_for_name(ITEM_STRING("level"))->mask;
- int timestamp = ITEM_OPT_BOOL("timestamp");
- if (timestamp != -1) src->timestamp = timestamp;
- const char* output = ITEM_STRING("output");
- if (output) {
- log_sink_t* old_sink = src->sink;
- src->sink = log_sink_lh(output);
- log_sink_free_lh(old_sink); /* DEFAULT source may already have a sink */
- if (src->sink->syslog) /* Timestamp off for syslog. */
- src->timestamp = 0;
- }
- sys_mutex_unlock(log_source_lock);
+ char *level = qd_entity_string(entity, "level"); QD_ERROR_RET();
+ copy.mask = level_for_name(level)->mask;
+ free(level);
+
+ if (qd_entity_has(entity, "timestamp"))
+ copy.timestamp = qd_entity_bool(entity, "timestamp");
+ QD_ERROR_RET();
+
+ if (qd_entity_has(entity, "output")) {
+ log_sink_free_lh(copy.sink); /* DEFAULT source may already have a sink */
+ char* output = qd_entity_string(entity, "output"); QD_ERROR_RET();
+ copy.sink = log_sink_lh(output);
+ free(output);
+ if (copy.sink->syslog) /* Timestamp off for syslog. */
+ copy.timestamp = 0;
}
- qd_log(logging_log_source, QD_LOG_INFO, "Logging system configured");
+
+ sys_mutex_lock(log_source_lock);
+ *src = copy;
+ sys_mutex_unlock(log_source_lock);
+ return qd_error_code();
}
Modified: qpid/dispatch/trunk/src/log_private.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/log_private.h?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/log_private.h (original)
+++ qpid/dispatch/trunk/src/log_private.h Tue Jul 8 20:31:13 2014
@@ -23,5 +23,6 @@
void qd_log_initialize(void);
void qd_log_finalize(void);
+
#define QD_LOG_TEXT_MAX 1024
#endif
Modified: qpid/dispatch/trunk/src/python_embedded.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/python_embedded.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/python_embedded.c (original)
+++ qpid/dispatch/trunk/src/python_embedded.c Tue Jul 8 20:31:13 2014
@@ -31,11 +31,11 @@
//===============================================================================
static qd_dispatch_t *dispatch = 0;
-static uint32_t ref_count = 0;
static sys_mutex_t *ilock = 0;
static qd_log_source_t *log_source = 0;
static PyObject *dispatch_module = 0;
static PyObject *dispatch_python_pkgdir = 0;
+static PyObject *qpid_dispatch_lib = 0;
static qd_address_semantics_t py_semantics = QD_FANOUT_MULTIPLE | QD_BIAS_NONE | QD_CONGESTION_DROP | QD_DROP_FOR_SLOW_CONSUMERS;
@@ -43,48 +43,28 @@ static void qd_python_setup(void);
void qd_python_initialize(qd_dispatch_t *qd,
- const char *python_pkgdir)
+ const char *python_pkgdir,
+ const char *qpid_dispatch_lib_)
{
log_source = qd_log_source("PYTHON");
dispatch = qd;
ilock = sys_mutex();
if (python_pkgdir)
dispatch_python_pkgdir = PyString_FromString(python_pkgdir);
+ if (qpid_dispatch_lib_)
+ qpid_dispatch_lib = PyString_FromString(qpid_dispatch_lib_);
+ Py_Initialize();
+ qd_python_setup();
}
void qd_python_finalize(void)
{
- assert(ref_count == 0);
sys_mutex_free(ilock);
-}
-
-
-void qd_python_start(void)
-{
- sys_mutex_lock(ilock);
- if (ref_count == 0) {
- Py_Initialize();
- qd_python_setup();
- qd_log(log_source, QD_LOG_TRACE, "Embedded Python Interpreter Initialized");
- }
- ref_count++;
- sys_mutex_unlock(ilock);
-}
-
-
-void qd_python_stop(void)
-{
- sys_mutex_lock(ilock);
- ref_count--;
- if (ref_count == 0) {
- Py_DECREF(dispatch_module);
- dispatch_module = 0;
- PyGC_Collect();
- Py_Finalize();
- qd_log(log_source, QD_LOG_TRACE, "Embedded Python Interpreter Shut Down");
- }
- sys_mutex_unlock(ilock);
+ Py_DECREF(dispatch_module);
+ dispatch_module = 0;
+ PyGC_Collect();
+ Py_Finalize();
}
@@ -660,6 +640,11 @@ static void qd_python_setup(void)
PyList_Append(sys_path, dispatch_python_pkgdir);
}
+ // Set the QPID_DISPATCH_LIB constant.
+ if (qpid_dispatch_lib) {
+ PyModule_AddObject(m, "QPID_DISPATCH_LIB", qpid_dispatch_lib);
+ }
+
//
// Add LogAdapter
//
Modified: qpid/dispatch/trunk/src/router_agent.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_agent.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_agent.c (original)
+++ qpid/dispatch/trunk/src/router_agent.c Tue Jul 8 20:31:13 2014
@@ -351,8 +351,9 @@ static void qd_router_query_address(void
}
-void qd_router_agent_setup(qd_router_t *router)
+qd_error_t qd_router_agent_setup(qd_router_t *router)
{
+ qd_error_clear();
router->class_router =
qd_agent_register_class(router->qd, ROUTER_TYPE, router, ROUTER_ATTRIBUTES, qd_router_query_router);
router->class_link =
@@ -361,6 +362,7 @@ void qd_router_agent_setup(qd_router_t *
qd_agent_register_class(router->qd, NODE_TYPE, router, NODE_ATTRIBUTES, qd_router_query_node);
router->class_address =
qd_agent_register_class(router->qd, ADDRESS_TYPE, router, ADDRESS_ATTRIBUTES, qd_router_query_address);
+ return qd_error_code();
}
Modified: qpid/dispatch/trunk/src/router_config.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_config.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_config.c (original)
+++ qpid/dispatch/trunk/src/router_config.c Tue Jul 8 20:31:13 2014
@@ -19,140 +19,120 @@
#include <qpid/dispatch/python_embedded.h>
#include <qpid/dispatch.h>
-#include <qpid/dispatch/config.h>
#include <qpid/dispatch/log.h>
#include "dispatch_private.h"
#include "router_private.h"
+#include "entity_private.h"
+#include "schema_enum.h"
-static const char *CONF_ADDRESS = "fixed-address";
-static const char *CONF_WAYPOINT = "waypoint";
-
-
-static void qd_router_configure_addresses(qd_router_t *router)
-{
- int count = qd_config_item_count(router->qd, CONF_ADDRESS);
-
- for (int idx = 0; idx < count; idx++) {
- char *prefix = qd_config_item_value_string(router->qd, CONF_ADDRESS, idx, "prefix");
- int phase = qd_config_item_value_int(router->qd, CONF_ADDRESS, idx, "phase");
- char *fanout = qd_config_item_value_string(router->qd, CONF_ADDRESS, idx, "fanout");
- char *bias = qd_config_item_value_string(router->qd, CONF_ADDRESS, idx, "bias");
-
- if (phase < 0 || phase > 9) {
- qd_log(router->log_source, QD_LOG_ERROR, "Invalid phase %d for prefix '%s' must be between 0 and 9. Ignoring", phase, prefix);
- free(prefix);
- free(fanout);
- free(bias);
- continue;
- }
-
- //
- // Search for a matching prefix in the list.
- //
- qd_config_address_t *addr = DEQ_HEAD(router->config_addrs);
- while (addr) {
- if (strcmp(addr->prefix, prefix) == 0)
- break;
- addr = DEQ_NEXT(addr);
- }
-
- if (addr == 0) {
- //
- // Create a new prefix
- //
- addr = NEW(qd_config_address_t);
- DEQ_ITEM_INIT(addr);
- addr->prefix = (char*) malloc(strlen(prefix) + 1);
- addr->last_phase = (char) phase + '0';
- DEQ_INIT(addr->phases);
- DEQ_INSERT_TAIL(router->config_addrs, addr);
- if (prefix[0] == '/')
- strcpy(addr->prefix, &prefix[1]);
- else
- strcpy(addr->prefix, prefix);
- }
-
- //
- // Add the phase to the prefix
- //
- qd_config_phase_t *addr_phase = NEW(qd_config_phase_t);
- DEQ_ITEM_INIT(addr_phase);
- addr_phase->phase = (char) phase + '0';
-
- qd_address_semantics_t semantics = 0;
- if (strcmp("multiple", fanout) == 0) semantics |= QD_FANOUT_MULTIPLE;
- else if (strcmp("single", fanout) == 0) semantics |= QD_FANOUT_SINGLE;
- else
- assert(0);
-
- if ((semantics & QD_FANOUTMASK) == QD_FANOUT_SINGLE) {
- if (strcmp("closest", bias) == 0) semantics |= QD_BIAS_CLOSEST;
- else if (strcmp("spread", bias) == 0) semantics |= QD_BIAS_SPREAD;
- else
- assert(0);
- qd_log(router->log_source, QD_LOG_INFO, "Configured Address: prefix=%s phase=%d fanout=%s bias=%s",
- prefix, phase, fanout, bias);
- } else {
- semantics |= QD_BIAS_NONE;
- qd_log(router->log_source, QD_LOG_INFO, "Configured Address: prefix=%s phase=%d fanout=%s",
- prefix, phase, fanout);
- }
-
- addr_phase->semantics = semantics;
- addr->last_phase = addr_phase->phase;
- DEQ_INSERT_TAIL(addr->phases, addr_phase);
+qd_error_t qd_router_configure_address(qd_router_t *router, qd_entity_t *entity) {
+ qd_error_clear();
+ /* FIXME aconway 2014-06-19: review phase default -1?? */
+ int phase = qd_entity_opt_long(entity, "phase", 0); QD_ERROR_RET();
+ qd_schema_fixed_address_fanout_t fanout = qd_entity_long(entity, "fanout"); QD_ERROR_RET();
+ qd_schema_fixed_address_bias_t bias = qd_entity_long(entity, "bias"); QD_ERROR_RET();
+ char *prefix = qd_entity_string(entity, "prefix"); QD_ERROR_RET();
+ if (phase < 0 || phase > 9) {
free(prefix);
- free(fanout);
- free(bias);
+ return qd_error(QD_ERROR_CONFIG, "Invalid phase %d for prefix '%s' must be between 0 and 9. Ignoring", phase, prefix);
}
-}
-
-static void qd_router_configure_waypoints(qd_router_t *router)
-{
- int count = qd_config_item_count(router->qd, CONF_WAYPOINT);
+ //
+ // Search for a matching prefix in the list.
+ //
+ qd_config_address_t *addr = DEQ_HEAD(router->config_addrs);
+ while (addr) {
+ if (strcmp(addr->prefix, prefix) == 0)
+ break;
+ addr = DEQ_NEXT(addr);
+ }
+
+ if (addr == 0) {
+ //
+ // Create a new prefix
+ //
+ addr = NEW(qd_config_address_t);
+ DEQ_ITEM_INIT(addr);
+ addr->prefix = (char*) malloc(strlen(prefix) + 1);
+ addr->last_phase = (char) phase + '0';
+ DEQ_INIT(addr->phases);
+ DEQ_INSERT_TAIL(router->config_addrs, addr);
+ if (prefix[0] == '/')
+ strcpy(addr->prefix, &prefix[1]);
+ else
+ strcpy(addr->prefix, prefix);
+ }
+
+ //
+ // Add the phase to the prefix
+ //
+ qd_config_phase_t *addr_phase = NEW(qd_config_phase_t);
+ DEQ_ITEM_INIT(addr_phase);
+ addr_phase->phase = (char) phase + '0';
+
+ qd_address_semantics_t semantics = 0;
+ switch(fanout) {
+ case QD_SCHEMA_FIXED_ADDRESS_FANOUT_MULTIPLE: semantics |= QD_FANOUT_MULTIPLE; break;
+ case QD_SCHEMA_FIXED_ADDRESS_FANOUT_SINGLE: semantics |= QD_FANOUT_SINGLE; break;
+ default:
+ free(prefix);
+ return qd_error(QD_ERROR_CONFIG, "Invalid fanout value %d", fanout);
+ }
- for (int idx = 0; idx < count; idx++) {
- char *address = qd_config_item_value_string(router->qd, CONF_WAYPOINT, idx, "address");
- char *connector = qd_config_item_value_string(router->qd, CONF_WAYPOINT, idx, "connector");
- int in_phase = qd_config_item_value_int(router->qd, CONF_WAYPOINT, idx, "in-phase");
- int out_phase = qd_config_item_value_int(router->qd, CONF_WAYPOINT, idx, "out-phase");
-
- if (in_phase > 9 || out_phase > 9) {
- qd_log(router->log_source, QD_LOG_ERROR, "Phases for waypoint '%s' must be between 0 and 9. Ignoring", address);
- free(address);
- free(connector);
- continue;
+ if ((semantics & QD_FANOUTMASK) == QD_FANOUT_SINGLE) {
+ switch(bias) {
+ case QD_SCHEMA_FIXED_ADDRESS_BIAS_CLOSEST: semantics |= QD_BIAS_CLOSEST; break;
+ case QD_SCHEMA_FIXED_ADDRESS_BIAS_SPREAD: semantics |= QD_BIAS_SPREAD; break;
+ default:
+ free(prefix);
+ return qd_error(QD_ERROR_CONFIG, "Invalid bias value %d", fanout);
}
-
- qd_waypoint_t *waypoint = NEW(qd_waypoint_t);
- memset(waypoint, 0, sizeof(qd_waypoint_t));
- DEQ_ITEM_INIT(waypoint);
- waypoint->address = address;
- waypoint->in_phase = in_phase >= 0 ? (char) in_phase + '0' : '\0';
- waypoint->out_phase = out_phase >= 0 ? (char) out_phase + '0' : '\0';
- waypoint->connector_name = connector;
-
- //
- // TODO - Look up connector
- //
-
- DEQ_INSERT_TAIL(router->waypoints, waypoint);
-
- qd_log(router->log_source, QD_LOG_INFO,
- "Configured Waypoint: address=%s in_phase=%d out_phase=%d connector=%s",
- address, in_phase, out_phase, connector);
- }
+ qd_log(router->log_source, QD_LOG_INFO,
+ "Configured Address: prefix=%s phase=%d fanout=%s bias=%s",
+ prefix, phase,
+ qd_schema_fixed_address_fanout_names[fanout],
+ qd_schema_fixed_address_bias_names[bias]);
+ } else {
+ semantics |= QD_BIAS_NONE;
+ qd_log(router->log_source, QD_LOG_INFO, "Configured Address: prefix=%s phase=%d fanout=%s",
+ prefix, phase, qd_schema_fixed_address_fanout_names[fanout]);
+ }
+
+ addr_phase->semantics = semantics;
+ addr->last_phase = addr_phase->phase;
+ DEQ_INSERT_TAIL(addr->phases, addr_phase);
+ free(prefix);
+ return qd_error_code();
}
-
-void qd_router_configure(qd_router_t *router)
+qd_error_t qd_router_configure_waypoint(qd_router_t *router, qd_entity_t *entity)
{
- if (!router->qd)
- return;
- qd_router_configure_addresses(router);
- qd_router_configure_waypoints(router);
+
+ char *address = qd_entity_string(entity, "address"); QD_ERROR_RET();
+ char *connector = qd_entity_string(entity, "connector"); QD_ERROR_RET();
+ int in_phase = qd_entity_opt_long(entity, "in-phase", 0); QD_ERROR_RET();
+ int out_phase = qd_entity_opt_long(entity, "out-phase", 0); QD_ERROR_RET();
+
+ if (in_phase > 9 || out_phase > 9) {
+ free(address);
+ free(connector);
+ return qd_error(QD_ERROR_CONFIG, "Phases for waypoint '%s' must be between 0 and 9.", address);
+ }
+ qd_waypoint_t *waypoint = NEW(qd_waypoint_t);
+ memset(waypoint, 0, sizeof(qd_waypoint_t));
+ DEQ_ITEM_INIT(waypoint);
+ waypoint->address = address;
+ waypoint->in_phase = in_phase >= 0 ? (char) in_phase + '0' : '\0';
+ waypoint->out_phase = out_phase >= 0 ? (char) out_phase + '0' : '\0';
+ waypoint->connector_name = connector;
+
+ DEQ_INSERT_TAIL(router->waypoints, waypoint);
+
+ qd_log(router->log_source, QD_LOG_INFO,
+ "Configured Waypoint: address=%s in_phase=%d out_phase=%d connector=%s",
+ address, in_phase, out_phase, connector);
+ return qd_error_code();
}
Modified: qpid/dispatch/trunk/src/router_node.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_node.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_node.c (original)
+++ qpid/dispatch/trunk/src/router_node.c Tue Jul 8 20:31:13 2014
@@ -1435,11 +1435,6 @@ qd_router_t *qd_router(qd_dispatch_t *qd
DEQ_INIT(router->waypoints);
//
- // Configure the router from the configuration file
- //
- qd_router_configure(router);
-
- //
// Create addresses for all of the routers in the topology. It will be registered
// locally later in the initialization sequence.
//
@@ -1455,11 +1450,6 @@ qd_router_t *qd_router(qd_dispatch_t *qd
qd_field_iterator_set_address(area, id);
//
- // Set up the usage of the embedded python router module.
- //
- qd_python_start();
-
- //
// Seed the random number generator
//
unsigned int seed = (unsigned int) time(0);
@@ -1515,7 +1505,6 @@ void qd_router_free(qd_router_t *router)
qd_hash_free(router->addr_hash);
qd_router_configure_free(router);
free(router);
- qd_python_stop();
free(node_id);
free(direct_prefix);
}
Modified: qpid/dispatch/trunk/src/router_private.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_private.h?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_private.h (original)
+++ qpid/dispatch/trunk/src/router_private.h Tue Jul 8 20:31:13 2014
@@ -31,11 +31,14 @@
#include <qpid/dispatch/agent.h>
#include <qpid/dispatch/log.h>
#include "dispatch_private.h"
+#include "entity_private.h"
+
+qd_error_t qd_router_python_setup(qd_router_t *router);
+qd_error_t qd_pyrouter_tick(qd_router_t *router);
+qd_error_t qd_router_agent_setup(qd_router_t *router);
+qd_error_t qd_router_configure_address(qd_router_t *router, qd_entity_t *entity);
+qd_error_t qd_router_configure_waypoint(qd_router_t *router, qd_entity_t *entity);
-void qd_router_python_setup(qd_router_t *router);
-void qd_pyrouter_tick(qd_router_t *router);
-void qd_router_agent_setup(qd_router_t *router);
-void qd_router_configure(qd_router_t *router);
void qd_router_configure_free(qd_router_t *router);
typedef enum {
Modified: qpid/dispatch/trunk/src/router_pynode.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_pynode.c?rev=1608947&r1=1608946&r2=1608947&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_pynode.c (original)
+++ qpid/dispatch/trunk/src/router_pynode.c Tue Jul 8 20:31:13 2014
@@ -527,9 +527,9 @@ static PyTypeObject RouterAdapterType =
};
-void qd_router_python_setup(qd_router_t *router)
+qd_error_t qd_router_python_setup(qd_router_t *router)
{
-
+ qd_error_clear();
log_source = qd_log_source("PYROUTER");
//
@@ -537,16 +537,12 @@ void qd_router_python_setup(qd_router_t
// router module.
//
if (router->router_mode != QD_ROUTER_MODE_INTERIOR)
- return;
+ return QD_ERROR_NONE;
PyObject *pDispatchModule = qd_python_module();
-
RouterAdapterType.tp_new = PyType_GenericNew;
- if (PyType_Ready(&RouterAdapterType) < 0) {
- qd_error_py();
- qd_log(log_source, QD_LOG_CRITICAL, "Unable to initialize the Python Router Adapter");
- return;
- }
+ PyType_Ready(&RouterAdapterType);
+ QD_ERROR_PY_RET();
PyTypeObject *raType = &RouterAdapterType;
Py_INCREF(raType);
@@ -555,7 +551,6 @@ void qd_router_python_setup(qd_router_t
//
// Attempt to import the Python Router module
//
- PyObject* pName;
PyObject* pId;
PyObject* pArea;
PyObject* pMaxRouters;
@@ -563,23 +558,13 @@ void qd_router_python_setup(qd_router_t
PyObject* pClass;
PyObject* pArgs;
- pName = PyString_FromString("qpid_dispatch_internal.router");
- pModule = PyImport_Import(pName);
- Py_DECREF(pName);
- if (!pModule) {
- qd_log(log_source, QD_LOG_CRITICAL, "Can't Locate 'router' Python module");
- return;
- }
-
+ pModule = PyImport_ImportModule("qpid_dispatch_internal.router"); QD_ERROR_PY_RET();
pClass = PyObject_GetAttrString(pModule, "RouterEngine");
- if (!pClass || !PyClass_Check(pClass)) {
- qd_log(log_source, QD_LOG_CRITICAL, "Can't Locate 'RouterEngine' class in the 'router' module");
- return;
- }
+ Py_DECREF(pModule);
+ QD_ERROR_PY_RET();
- PyObject *adapterType = PyObject_GetAttrString(pDispatchModule, "RouterAdapter");
- PyObject *adapterInstance = PyObject_CallObject(adapterType, 0);
- assert(adapterInstance);
+ PyObject *adapterType = PyObject_GetAttrString(pDispatchModule, "RouterAdapter"); QD_ERROR_PY_RET();
+ PyObject *adapterInstance = PyObject_CallObject(adapterType, 0); QD_ERROR_PY_RET();
((RouterAdapter*) adapterInstance)->router = router;
@@ -609,41 +594,20 @@ void qd_router_python_setup(qd_router_t
pyRouter = PyInstance_New(pClass, pArgs, 0);
Py_DECREF(pArgs);
Py_DECREF(adapterType);
+ QD_ERROR_PY_RET();
- if (!pyRouter) {
- qd_error_py();
- qd_log(log_source, QD_LOG_CRITICAL, "'RouterEngine' class cannot be instantiated");
- return;
- }
-
- pyTick = PyObject_GetAttrString(pyRouter, "handleTimerTick");
- if (!pyTick || !PyCallable_Check(pyTick)) {
- qd_log(log_source, QD_LOG_CRITICAL, "'RouterEngine' class has no handleTimerTick method");
- return;
- }
-
- pyAdded = PyObject_GetAttrString(pyRouter, "addressAdded");
- if (!pyAdded || !PyCallable_Check(pyAdded)) {
- qd_log(log_source, QD_LOG_CRITICAL, "'RouterEngine' class has no addressAdded method");
- return;
- }
-
- pyRemoved = PyObject_GetAttrString(pyRouter, "addressRemoved");
- if (!pyRemoved || !PyCallable_Check(pyRemoved)) {
- qd_log(log_source, QD_LOG_CRITICAL, "'RouterEngine' class has no addressRemoved method");
- return;
- }
-
- pyLinkLost = PyObject_GetAttrString(pyRouter, "linkLost");
- if (!pyLinkLost || !PyCallable_Check(pyLinkLost)) {
- qd_log(log_source, QD_LOG_CRITICAL, "'RouterEngine' class has no linkLost method");
- return;
- }
+ pyTick = PyObject_GetAttrString(pyRouter, "handleTimerTick"); QD_ERROR_PY_RET();
+ pyAdded = PyObject_GetAttrString(pyRouter, "addressAdded"); QD_ERROR_PY_RET();
+ pyRemoved = PyObject_GetAttrString(pyRouter, "addressRemoved"); QD_ERROR_PY_RET();
+ pyLinkLost = PyObject_GetAttrString(pyRouter, "linkLost"); QD_ERROR_PY_RET();
+ return qd_error_code();
}
-void qd_pyrouter_tick(qd_router_t *router)
+qd_error_t qd_pyrouter_tick(qd_router_t *router)
{
+ qd_error_clear();
+
PyObject *pArgs;
PyObject *pValue;
@@ -651,11 +615,11 @@ void qd_pyrouter_tick(qd_router_t *route
qd_python_lock();
pArgs = PyTuple_New(0);
pValue = PyObject_CallObject(pyTick, pArgs);
- qd_error_py();
Py_DECREF(pArgs);
Py_XDECREF(pValue);
qd_python_unlock();
}
+ return qd_error_py();
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org