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/10/18 01:35:37 UTC

svn commit: r1632696 [2/2] - in /qpid/dispatch/trunk: doc/api/ doc/man/ include/qpid/dispatch/ python/qpid_dispatch/ python/qpid_dispatch/management/ python/qpid_dispatch/qpid_dispatch/ python/qpid_dispatch_internal/ python/qpid_dispatch_internal/manag...

Modified: qpid/dispatch/trunk/src/entity_private.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/entity_private.h?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/entity_private.h (original)
+++ qpid/dispatch/trunk/src/entity_private.h Fri Oct 17 23:35:35 2014
@@ -22,6 +22,14 @@
 #include <stdbool.h>
 #include <qpid/dispatch/dispatch.h>
 
+/**
+ * @defgroup entity
+xo *
+ * Holds attributes of a managed entity.
+ * @{
+ */
+
+
 void qd_entity_free(qd_entity_t* entity);
 
 /** True if the entity has this attribute. */
@@ -60,4 +68,35 @@ long qd_entity_opt_long(qd_entity_t *ent
 bool qd_entity_opt_bool(qd_entity_t *entity, const char *attribute, bool default_value);
 
 
+/** Set a string valued attribute, entity makes a copy.
+ * If value is NULL clear the attribute.
+ */
+qd_error_t qd_entity_set_string(qd_entity_t *entity, const char* attribute, const char *value);
+
+/** Set a string valued attribute from a printf format */
+qd_error_t qd_entity_set_stringf(qd_entity_t *entity, const char* attribute, const char *format, ...);
+
+/** Set an integer valued attribute. */
+qd_error_t qd_entity_set_long(qd_entity_t *entity, const char* attribute, long value);
+
+/** Set a boolean valued attribute. */
+qd_error_t qd_entity_set_bool(qd_entity_t *entity, const char *attribute, bool value);
+
+/** Set an integer valued attribute. If value is NULL clear the attribute. */
+qd_error_t qd_entity_set_longp(qd_entity_t *entity, const char* attribute, const long *value);
+
+/** Set a boolean valued attribute. If value is NULL clear the attribute. */
+qd_error_t qd_entity_set_boolp(qd_entity_t *entity, const char *attribute, const bool *value);
+
+/** Clear the attribute  */
+qd_error_t qd_entity_clear(qd_entity_t *entity, const char *attribute);
+
+/**
+ * Set the attribute to an empty list. Futher qd_entity_set* calls for the attribute
+ * will append values to the list.
+ */
+qd_error_t qd_entity_set_list(qd_entity_t *entity, const char *attribute);
+
+/// @}
+
 #endif

Modified: qpid/dispatch/trunk/src/error.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/error.c?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/error.c (original)
+++ qpid/dispatch/trunk/src/error.c Fri Oct 17 23:35:35 2014
@@ -19,13 +19,14 @@
 
 #include <Python.h>
 #include <qpid/dispatch/error.h>
+#include <qpid/dispatch/enum.h>
 #include <qpid/dispatch/log.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include "static_assert.h"
 #include "log_private.h"
+#include "aprintf.h"
 
-static const char *error_names[] = {
+static const char *qd_error_names[] = {
  "No Error",
  "Not found",
  "Already exists",
@@ -37,9 +38,7 @@ static const char *error_names[] = {
  "Value",
  "Run Time"
 };
-
-STATIC_ASSERT(sizeof(error_names)/sizeof(error_names[0]) == QD_ERROR_ENUM_COUNT,
-	      error_names_wrong_size);
+ENUM_DEFINE(qd_error, qd_error_names);
 
 #define ERROR_MAX QD_LOG_TEXT_MAX
 const int QD_ERROR_MAX = ERROR_MAX;
@@ -56,19 +55,22 @@ void qd_error_initialize() {
     log_source = qd_log_source("ERROR");
 }
 
-qd_error_t qd_error(qd_error_t code, const char *fmt, ...) {
+qd_error_t qd_error_impl(qd_error_t code, const char *file, int line, const char *fmt, ...) {
     ts.error_code = code;
     if (code) {
-	int i = 0;
-	if (code < QD_ERROR_ENUM_COUNT)
-	    i = snprintf(ts.error_message, ERROR_MAX,"%s: ", error_names[code]);
+        char *begin = ts.error_message;
+        char *end = begin + ERROR_MAX;
+	const char* name = qd_error_name(code);
+        if (name)
+            aprintf(&begin, end, "%s: ", name);
 	else
-	    i = snprintf(ts.error_message, ERROR_MAX, "%d: ", code);
+	    aprintf(&begin, end, "%d: ", code);
 	va_list arglist;
 	va_start(arglist, fmt);
-	vsnprintf(ts.error_message+i, ERROR_MAX-i, fmt, arglist);
+	vaprintf(&begin, end, fmt, arglist);
 	va_end(arglist);
-	qd_log(log_source, QD_LOG_ERROR, "%s", qd_error_message());
+        // NOTE: Use the file/line from the qd_error macro, not this line in error.c
+	qd_log_impl(log_source, QD_LOG_ERROR, file, line, "%s", qd_error_message());
 	return code;
     }
     else
@@ -95,7 +97,9 @@ static void py_set_item(PyObject *dict, 
     Py_DECREF(py_name);
 }
 
-static void log_trace_py(PyObject *type, PyObject *value, PyObject* trace, qd_log_level_t level) {
+static void log_trace_py(PyObject *type, PyObject *value, PyObject* trace, qd_log_level_t level,
+                         const char *file, int line)
+{
     if (!qd_log_enabled(log_source, level)) return;
     if (!(type && value && trace)) return;
 
@@ -116,10 +120,11 @@ static void log_trace_py(PyObject *type,
     Py_DECREF(globals);
     Py_DECREF(locals);
 
+
     if (result) {
 	const char* trace = PyString_AsString(result);
 	if (strlen(trace) < QD_LOG_TEXT_MAX) {
-	    qd_log(log_source, level, "%s", trace);
+	    qd_log_impl(log_source, level, file, line, "%s", trace);
 	} else {
 	    // Keep as much of the the tail of the trace as we can.
 	    const char *tail = trace;
@@ -127,14 +132,14 @@ static void log_trace_py(PyObject *type,
 		tail = strchr(tail, '\n');
 		if (tail) ++tail;
 	    }
-	    qd_log(log_source, level, "Traceback truncated:\n%s", tail ? tail : "");
+	    qd_log_impl(log_source, level, file, line, "Traceback truncated:\n%s", tail ? tail : "");
 	}
 	Py_DECREF(result);
     }
 
 }
 
-qd_error_t qd_error_py() {
+qd_error_t qd_error_py_impl(const char *file, int line) {
     if (PyErr_Occurred()) {
 	PyObject *type, *value, *trace;
 	PyErr_Fetch(&type, &value, &trace); /* Note clears the python error indicator */
@@ -144,13 +149,13 @@ qd_error_t qd_error_py() {
 	PyObject *value_str = value ? PyObject_Str(value) : NULL;
 	const char* str = value_str ? PyString_AsString(value_str) : "Unknown";
 	if (type_name)
-	    qd_error(QD_ERROR_PYTHON, "%s: %s", PyString_AsString(type_name), str);
+	    qd_error_impl(QD_ERROR_PYTHON, file, line, "%s: %s", PyString_AsString(type_name), str);
 	else
-	    qd_error(QD_ERROR_PYTHON, "%s", str);
+	    qd_error_impl(QD_ERROR_PYTHON, file, line, "%s", str);
 	Py_XDECREF(value_str);
 	Py_XDECREF(type_name);
 
-	log_trace_py(type, value, trace, QD_LOG_ERROR);
+	log_trace_py(type, value, trace, QD_LOG_ERROR, file, line);
 
 	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=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/log.c (original)
+++ qpid/dispatch/trunk/src/log.c Fri Oct 17 23:35:35 2014
@@ -19,6 +19,7 @@
 
 #include "log_private.h"
 #include "entity_private.h"
+#include "aprintf.h"
 #include <qpid/dispatch/ctools.h>
 #include <qpid/dispatch/dispatch.h>
 #include <qpid/dispatch/alloc.h>
@@ -133,7 +134,8 @@ struct qd_log_source_t {
     DEQ_LINKS(qd_log_source_t);
     const char *module;
     int mask;
-    int timestamp;
+    int timestamp;              /* boolean or -1 means not set */
+    int source;                 /* boolean or -1 means not set */
     bool syslog;
     log_sink_t *sink;
 };
@@ -196,17 +198,30 @@ static qd_log_source_t* lookup_log_sourc
     return src;
 }
 
-static void write_log(int level, qd_log_source_t *log_source, const char *fmt, ...)
+static bool default_bool(int value, int default_value) {
+    return value == -1 ? default_value : value;
+}
+
+static void write_log(qd_log_source_t *log_source, qd_log_entry_t *entry)
 {
     log_sink_t* sink = log_source->sink ? log_source->sink : default_log_source->sink;
-
     if (!sink) return;
 
     char log_str[LOG_MAX];
-    va_list arglist;
-    va_start(arglist, fmt);
-    vsnprintf(log_str, LOG_MAX, fmt, arglist);
-    va_end(arglist);
+    char *begin = log_str;
+    char *end = log_str + LOG_MAX;
+
+    if (default_bool(log_source->timestamp, default_log_source->timestamp)) {
+        char buf[100];
+        buf[0] = '\0';
+        ctime_r(&entry->time, buf);
+        buf[strlen(buf)-1] = '\0'; /* Get rid of trailng \n */
+	aprintf(&begin, end, "%s ", buf);
+    }
+    aprintf(&begin, end, "%s (%s) %s", entry->module, level_for_bit(entry->level)->name, entry->text);
+    if (default_bool(log_source->source, default_log_source->source))
+	aprintf(&begin, end, " (%s:%d)", entry->file, entry->line);
+    aprintf(&begin, end, "\n");
 
     if (sink->file) {
 	if (fputs(log_str, sink->file) == EOF) {
@@ -218,7 +233,7 @@ static void write_log(int level, qd_log_
 	fflush(sink->file);
     }
     if (sink->syslog) {
-	int syslog_level = level_for_bit(level)->syslog;
+	int syslog_level = level_for_bit(entry->level)->syslog;
 	if (syslog_level != -1)
 	    syslog(syslog_level, "%s", log_str);
     }
@@ -236,6 +251,7 @@ static qd_log_source_t *qd_log_source_lh
 	log_source->module = module;
 	log_source->mask = -1;
 	log_source->timestamp = -1;
+	log_source->source = -1;
 	log_source->sink = 0;
         DEQ_INSERT_TAIL(source_list, log_source);
     }
@@ -273,22 +289,12 @@ void qd_log_impl(qd_log_source_t *source
     entry->file   = file ? strdup(file) : 0;
     entry->line   = line;
     time(&entry->time);
-
-    char ctime[100];
-    ctime[0] = '\0';
-    bool timestamp = (source->timestamp == -1) ?
-		      default_log_source->timestamp : source->timestamp;
-    assert(timestamp != -1);
-    if (timestamp) {
-	ctime_r(&entry->time, ctime);
-	ctime[24] = '\0';
-	strcat(ctime, " ");
-    }
     va_list ap;
     va_start(ap, fmt);
     vsnprintf(entry->text, TEXT_MAX, fmt, ap);
     va_end(ap);
-    write_log(level, source, "%s%s (%s) %s\n", ctime, entry->module, level_for_bit(level)->name, entry->text);
+
+    write_log(source, entry);
 
     sys_mutex_lock(log_lock);
     DEQ_INSERT_TAIL(entries, entry);
@@ -314,6 +320,7 @@ void qd_log_initialize(void)
     // Only report errors until we have configured the logging system.
     default_log_source->mask = levels[INFO].mask;
     default_log_source->timestamp = 1;
+    default_log_source->source = 0;
     default_log_source->sink = log_sink_lh(SINK_STDERR);
     logging_log_source = qd_log_source(SOURCE_LOGGING);
 }

Modified: qpid/dispatch/trunk/src/message.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/message.c?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/message.c (original)
+++ qpid/dispatch/trunk/src/message.c Fri Oct 17 23:35:35 2014
@@ -25,6 +25,7 @@
 #include <qpid/dispatch/log.h>
 #include "message_private.h"
 #include "compose_private.h"
+#include "aprintf.h"
 #include <string.h>
 #include <ctype.h>
 #include <stdio.h>
@@ -67,34 +68,29 @@ void qd_message_initialize() {
 int qd_message_repr_len() { return qd_log_max_len(); }
 
 // Quote non-printable characters suitable for log messages. Output in buffer.
-static int quote(char* bytes, int n, char* buffer, int len) {
-    int i = 0;
-    for (char* p = bytes; p < bytes+n && i < len; ++p) {
-	if (isprint(*p) || isspace(*p)) {
-	    buffer[i++] = *p;
-	}
-	else {
-	    int d = snprintf(buffer+i, len-i, "\\%02hhx", *p);
-	    i += d;
-	}
+static void quote(char* bytes, int n, char **begin, char *end) {
+    for (char* p = bytes; p < bytes+n; ++p) {
+	if (isprint(*p) || isspace(*p))
+            aprintf(begin, end, "%c", (int)*p);
+	else
+            aprintf(begin, end, "\\%02hhx", *p);
     }
-    return i;
 }
 
 /** Copy a message field for use in log messages. Output in buffer. */
-static int copy_field(qd_message_t *msg,  int field, int max, char *pre, char *post, char *buffer, size_t len) {
+static void copy_field(qd_message_t *msg,  int field, int max, char *pre, char *post,
+                       char **begin, char *end)
+{
     qd_field_iterator_t* iter =	qd_message_field_iterator(msg, field);
-    int i = 0;
     if (iter) {
-	i += snprintf(buffer+i, len-i, "%s", pre);
+	aprintf(begin, end, "%s", pre);
 	qd_field_iterator_reset(iter);
-	for (int j = 0; !qd_field_iterator_end(iter) && i < len && j < max; ++j) {
+	for (int j = 0; !qd_field_iterator_end(iter) && j < max; ++j) {
 	    char byte = qd_field_iterator_octet(iter);
-	    i += quote(&byte, 1, buffer+i, len-i);
+	    quote(&byte, 1, begin, end);
 	}
-	i += snprintf(buffer+i, len-i, "%s", post);
+	aprintf(begin, end, "%s", post);
     }
-    return i;
 }
 
 static const char REPR_END[] = "}\0";
@@ -102,14 +98,13 @@ static const char REPR_END[] = "}\0";
 /* TODO aconway 2014-05-13: more detailed message representation. */
 char* qd_message_repr(qd_message_t *msg, char* buffer, size_t len) {
     qd_message_check(msg, QD_DEPTH_BODY);
-    int i = 0;
-    len -= sizeof(REPR_END);	/* Save space for ending */
-    i += snprintf(buffer+i, len-i, "Message(%p){", msg);
-    i += copy_field(msg, QD_FIELD_TO, INT_MAX, "to='", "'", buffer+i, len-i);
-    i += copy_field(msg, QD_FIELD_REPLY_TO, INT_MAX, " reply-to='", "'", buffer+i, len-i);
-    i += copy_field(msg, QD_FIELD_BODY, 16, " body='", "'", buffer+i, len-i);
-    assert(i <= len);
-    strcat(buffer, REPR_END);	/* We saved space at the beginning. */
+    char *begin = buffer;
+    char *end = buffer + len - sizeof(REPR_END); /* Save space for ending */
+    aprintf(&begin, end, "Message(%p){", msg);
+    copy_field(msg, QD_FIELD_TO, INT_MAX, "to='", "'", &begin, end);
+    copy_field(msg, QD_FIELD_REPLY_TO, INT_MAX, " reply-to='", "'", &begin, end);
+    copy_field(msg, QD_FIELD_BODY, 16, " body='", "'", &begin, end);
+    aprintf(&begin, end, "%s", REPR_END);	/* We saved space at the beginning. */
     return buffer;
 }
 

Modified: qpid/dispatch/trunk/src/python_embedded.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/python_embedded.c?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/python_embedded.c (original)
+++ qpid/dispatch/trunk/src/python_embedded.c Fri Oct 17 23:35:35 2014
@@ -17,6 +17,7 @@
  * under the License.
  */
 
+#include "c_entity.h"
 #include <qpid/dispatch/python_embedded.h>
 #include <qpid/dispatch/threading.h>
 #include <qpid/dispatch/log.h>
@@ -679,7 +680,7 @@ static void qd_python_setup(void)
     if ((PyType_Ready(&LogAdapterType) < 0) || (PyType_Ready(&IoAdapterType) < 0)) {
         qd_error_py();
         qd_log(log_source, QD_LOG_ERROR, "Unable to initialize Adapters");
-        assert(0);
+        abort();
     } else {
         PyObject *m = Py_InitModule3("dispatch", empty_methods, "Dispatch Adapter Module");
 

Modified: qpid/dispatch/trunk/src/router_agent.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_agent.c?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_agent.c (original)
+++ qpid/dispatch/trunk/src/router_agent.c Fri Oct 17 23:35:35 2014
@@ -26,18 +26,74 @@
 #include <qpid/dispatch/agent.h>
 #include "dispatch_private.h"
 #include "router_private.h"
+#include "c_entity.h"
 
+static const char *qd_router_mode_names[] = {
+    "standalone",
+    "interior",
+    "edge",
+    "endpoint"
+};
+ENUM_DEFINE(qd_router_mode, qd_router_mode_names);
 
-static const char *qd_router_addr_text(qd_address_t *addr)
+qd_error_t qd_c_entity_update_router(qd_entity_t* entity, void *impl) {
+    qd_dispatch_t *qd = (qd_dispatch_t*) impl;
+    qd_router_t *router = qd->router;
+    if (qd_entity_set_string(entity, "name", router->router_id) == 0 &&
+        qd_entity_set_string(entity, "identity", router->router_id) == 0 &&
+        qd_entity_set_string(entity, "area", router->router_area) == 0 &&
+        qd_entity_set_string(entity, "mode", qd_router_mode_name(router->router_mode)) == 0 &&
+        qd_entity_set_long(entity, "addrCount", DEQ_SIZE(router->addrs)) == 0 &&
+        qd_entity_set_long(entity, "linkCount", DEQ_SIZE(router->links)) == 0 &&
+        qd_entity_set_long(entity, "nodeCount", DEQ_SIZE(router->routers)) == 0
+    )
+        return QD_ERROR_NONE;
+    return qd_error_code();
+}
+
+static const char *address_text(qd_address_t *addr)
 {
-    if (addr) {
-        const unsigned char *text = qd_hash_key_by_handle(addr->hash_handle);
-        if (text)
-            return (const char*) text;
-    }
-    return 0;
+    return addr ? (const char*) qd_hash_key_by_handle(addr->hash_handle) : 0;
 }
 
+qd_error_t qd_c_entity_update_router_address(qd_entity_t* entity, void *impl) {
+    qd_address_t *addr = (qd_address_t*) impl;
+    if ((qd_entity_has(entity, "identity") ||
+         qd_entity_set_string(entity, "identity", address_text(addr)) == 0) &&
+        qd_entity_set_bool(entity, "inProcess", addr->handler != 0) == 0 &&
+        qd_entity_set_long(entity, "subscriberCount", DEQ_SIZE(addr->rlinks)) == 0 &&
+        qd_entity_set_long(entity, "remoteCount", DEQ_SIZE(addr->rnodes)) == 0 &&
+        qd_entity_set_long(entity, "deliveriesIngress", addr->deliveries_ingress) == 0 &&
+        qd_entity_set_long(entity, "deliveriesEgress", addr->deliveries_egress) == 0 &&
+        qd_entity_set_long(entity, "deliveriesTransit", addr->deliveries_transit) == 0 &&
+        qd_entity_set_long(entity, "deliveriesToContainer", addr->deliveries_to_container) == 0 &&
+        qd_entity_set_long(entity, "deliveriesFromContainer", addr->deliveries_from_container) == 0
+    )
+        return QD_ERROR_NONE;
+    return qd_error_code();
+}
+
+#define CHECK(err) if (err != 0) return qd_error_code()
+
+qd_error_t qd_c_entity_update_router_node(qd_entity_t* entity, void *impl) {
+    qd_router_node_t *rnode = (qd_router_node_t*) impl;
+
+    if (!qd_entity_has(entity, "identity")) {
+        CHECK(qd_entity_set_stringf(entity, "identity", "%s-%d", QD_ROUTER_NODE_TYPE, rnode->mask_bit));
+    }
+    CHECK(qd_entity_set_string(entity, "addr", address_text(rnode->owning_addr)));
+    long next_hop = rnode->next_hop ? rnode->next_hop->mask_bit : 0;
+    CHECK(qd_entity_set_longp(entity, "nextHop", rnode->next_hop ? &next_hop : 0));
+    long router_link = rnode->peer_link ? rnode->peer_link->mask_bit : 0;
+    CHECK(qd_entity_set_longp(entity, "routerLink", rnode->peer_link ? &router_link : 0));
+    CHECK(qd_entity_set_list(entity, "validOrigins"));
+    for (uint32_t bit = 1; bit < qd_bitmask_width(); bit++) {
+        if (qd_bitmask_value(rnode->valid_origins, bit)) {
+            CHECK(qd_entity_set_long(entity, "validOrigins", bit));
+        }
+    }
+    return QD_ERROR_NONE;
+}
 
 static void router_attr_name(void *object_handle, void *cor, void *unused)
 {
@@ -86,7 +142,6 @@ static void router_attr_nodeCount(void *
 }
 
 
-static const char *ROUTER_TYPE = "org.apache.qpid.dispatch.router";
 static const qd_agent_attribute_t ROUTER_ATTRIBUTES[] =
     {{"name", router_attr_name, 0},
      {"identity", router_attr_name, 0},
@@ -107,7 +162,6 @@ static void qd_router_query_router(void 
     sys_mutex_unlock(router->lock);
 }
 
-
 static void link_attr_name(void *object_handle, void *cor, void *unused)
 {
     qd_router_link_t *link = (qd_router_link_t*) object_handle;
@@ -140,7 +194,7 @@ static void link_attr_linkDir(void *obje
 static void link_attr_owningAddr(void *object_handle, void *cor, void *unused)
 {
     qd_router_link_t *link = (qd_router_link_t*) object_handle;
-    const char *text = qd_router_addr_text(link->owning_addr);
+    const char *text = address_text(link->owning_addr);
     if (text)
         qd_agent_value_string(cor, 0, text);
     else
@@ -162,7 +216,6 @@ static void link_attr_msgFifoDepth(void 
 }
 
 
-static const char *LINK_TYPE = "org.apache.qpid.dispatch.router.link";
 static const qd_agent_attribute_t LINK_ATTRIBUTES[] =
     {{"name", link_attr_name, 0},
      {"identity", link_attr_name, 0},
@@ -173,6 +226,7 @@ static const qd_agent_attribute_t LINK_A
      {"msgFifoDepth", link_attr_msgFifoDepth, 0},
      {0, 0, 0}};
 
+
 static void qd_router_query_link(void *context, void *cor)
 {
     qd_router_t *router = (qd_router_t*) context;
@@ -188,6 +242,30 @@ static void qd_router_query_link(void *c
     sys_mutex_unlock(router->lock);
 }
 
+static const char *qd_link_type_names[] = { "endpoint", "waypoint", "inter-router", "inter-area" };
+ENUM_DEFINE(qd_link_type, qd_link_type_names);
+
+static const char *qd_router_addr_text(qd_address_t *addr)
+{
+    return addr ? (const char*)qd_hash_key_by_handle(addr->hash_handle) : NULL;
+}
+
+qd_error_t qd_c_entity_update_router_link(qd_entity_t* entity, void *impl)
+{
+    qd_router_link_t *link = (qd_router_link_t*) impl;
+    /* FIXME aconway 2014-10-17: old management used link->bit_mask as name/identity,
+     * but even when prefixed with router.link this is not unique. Let python agent
+     * generate a name for now, revisit with a better name later.
+     */
+    if (!qd_entity_set_string(entity, "linkType", qd_link_type_name(link->link_type)) &&
+        !qd_entity_set_string(entity, "linkDir", (link->link_direction == QD_INCOMING) ? "in": "out") &&
+        !qd_entity_set_string(entity, "owningAddr", qd_router_addr_text(link->owning_addr)) &&
+        !qd_entity_set_long(entity, "eventFifoDepth", DEQ_SIZE(link->event_fifo)) &&
+        !qd_entity_set_long(entity, "msgFifoDepth", DEQ_SIZE(link->msg_fifo))
+    )
+        return QD_ERROR_NONE;
+    return qd_error_code();
+}
 
 static void node_attr_name(void *object_handle, void *cor, void *unused)
 {
@@ -199,7 +277,7 @@ static void node_attr_name(void *object_
 static void node_attr_addr(void *object_handle, void *cor, void *unused)
 {
     qd_router_node_t *node = (qd_router_node_t*) object_handle;
-    qd_agent_value_string(cor, 0, qd_router_addr_text(node->owning_addr));
+    qd_agent_value_string(cor, 0, address_text(node->owning_addr));
 }
 
 
@@ -234,7 +312,6 @@ static void node_attr_validOrigins(void 
 }
 
 
-static const char *NODE_TYPE = "org.apache.qpid.dispatch.router.node";
 static const qd_agent_attribute_t NODE_ATTRIBUTES[] =
     {{"name", node_attr_name, 0},
      {"identity", node_attr_name, 0},
@@ -262,7 +339,7 @@ static void qd_router_query_node(void *c
 static void addr_attr_name(void *object_handle, void *cor, void *unused)
 {
     qd_address_t *addr = (qd_address_t*) object_handle;
-    qd_agent_value_string(cor, 0, qd_router_addr_text(addr));
+    qd_agent_value_string(cor, 0, address_text(addr));
 }
 
 
@@ -322,7 +399,6 @@ static void addr_attr_deliveriesFromCont
 }
 
 
-static const char *ADDRESS_TYPE = "org.apache.qpid.dispatch.router.address";
 static const qd_agent_attribute_t ADDRESS_ATTRIBUTES[] =
     {{"name", addr_attr_name, 0},
      {"identity", addr_attr_name, 0},
@@ -355,13 +431,13 @@ qd_error_t qd_router_agent_setup(qd_rout
 {
     qd_error_clear();
     router->class_router =
-        qd_agent_register_class(router->qd, ROUTER_TYPE, router, ROUTER_ATTRIBUTES, qd_router_query_router);
+        qd_agent_register_class(router->qd, QD_ROUTER_TYPE, router, ROUTER_ATTRIBUTES, qd_router_query_router);
     router->class_link =
-        qd_agent_register_class(router->qd, LINK_TYPE, router, LINK_ATTRIBUTES, qd_router_query_link);
+        qd_agent_register_class(router->qd, QD_ROUTER_LINK_TYPE, router, LINK_ATTRIBUTES, qd_router_query_link);
     router->class_node =
-        qd_agent_register_class(router->qd, NODE_TYPE, router, NODE_ATTRIBUTES, qd_router_query_node);
+        qd_agent_register_class(router->qd, QD_ROUTER_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);
+        qd_agent_register_class(router->qd, QD_ROUTER_ADDRESS_TYPE, router, ADDRESS_ATTRIBUTES, qd_router_query_address);
     return qd_error_code();
 }
 
@@ -369,7 +445,7 @@ qd_error_t qd_router_agent_setup(qd_rout
 void qd_router_build_node_list(qd_dispatch_t *qd, qd_composed_field_t *field)
 {
     qd_router_t *router = qd->router;
-    char         temp[1000];  // FIXME
+    char         temp[1000];
 
     sys_mutex_lock(router->lock);
     qd_router_node_t *rnode = DEQ_HEAD(router->routers);

Modified: qpid/dispatch/trunk/src/router_node.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_node.c?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_node.c (original)
+++ qpid/dispatch/trunk/src/router_node.c Fri Oct 17 23:35:35 2014
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <qpid/dispatch.h>
 #include "dispatch_private.h"
+#include "c_entity.h"
 #include "router_private.h"
 #include "waypoint_private.h"
 
@@ -156,6 +157,7 @@ void qd_router_check_addr(qd_router_t *r
         //
         qd_hash_remove_by_handle2(router->addr_hash, addr->hash_handle, &key);
         DEQ_REMOVE(router->addrs, addr);
+        qd_c_entity_remove(QD_ROUTER_ADDRESS_TYPE, addr);
         qd_hash_handle_free(addr->hash_handle);
         free_qd_address_t(addr);
     }
@@ -1002,6 +1004,7 @@ static int router_incoming_link_handler(
 
     sys_mutex_lock(router->lock);
     rlink->mask_bit = is_router ? qd_router_find_mask_bit_LH(router, link) : 0;
+    qd_c_entity_add(QD_ROUTER_LINK_TYPE, rlink);
     DEQ_INSERT_TAIL(router->links, rlink);
     sys_mutex_unlock(router->lock);
 
@@ -1118,7 +1121,7 @@ static int router_outgoing_link_handler(
         // assign it an ephemeral and routable address.  If it has a non-dynamic
         // address, that address needs to be set up in the address list.
         //
-        char temp_addr[1000]; // FIXME
+        char temp_addr[1000]; // TODO: Use pn_string or aprintf.
 
         if (is_dynamic) {
             qd_router_generate_temp_addr(router, temp_addr, 1000);
@@ -1134,6 +1137,7 @@ static int router_outgoing_link_handler(
             qd_hash_insert(router->addr_hash, iter, addr, &addr->hash_handle);
             DEQ_INSERT_TAIL(router->addrs, addr);
             addr->semantics = semantics;
+            qd_c_entity_add(QD_ROUTER_ADDRESS_TYPE, addr);
         }
 
         rlink->owning_addr = addr;
@@ -1146,7 +1150,7 @@ static int router_outgoing_link_handler(
         //
         propagate = (!is_dynamic) && (DEQ_SIZE(addr->rlinks) == 1);
     }
-
+    qd_c_entity_add(QD_ROUTER_LINK_TYPE, rlink);
     DEQ_INSERT_TAIL(router->links, rlink);
 
     //
@@ -1222,6 +1226,7 @@ static int router_link_detach_handler(vo
     // Remove the link from the master list-of-links.
     //
     DEQ_REMOVE(router->links, rlink);
+    qd_c_entity_remove(QD_ROUTER_LINK_TYPE, rlink);
     sys_mutex_unlock(router->lock);
 
     //
@@ -1229,7 +1234,6 @@ static int router_link_detach_handler(vo
     //
     qd_router_check_addr(router, oaddr, 1);
 
-    // TODO - wrap the free to handle the recursive items
     if (rlink->target)
         free(rlink->target);
     free_qd_router_link_t(rlink);
@@ -1311,6 +1315,7 @@ static void router_outbound_open_handler
     DEQ_INIT(rlink->msg_fifo);
 
     qd_link_set_context(receiver, rlink);
+    qd_c_entity_add(QD_ROUTER_LINK_TYPE, rlink);
     DEQ_INSERT_TAIL(router->links, rlink);
 
     //
@@ -1348,6 +1353,7 @@ static void router_outbound_open_handler
     router->out_links_by_mask_bit[mask_bit] = rlink;
 
     qd_link_set_context(sender, rlink);
+    qd_c_entity_add(QD_ROUTER_LINK_TYPE, rlink);
     DEQ_INSERT_TAIL(router->links, rlink);
     sys_mutex_unlock(router->lock);
 
@@ -1493,8 +1499,8 @@ void qd_router_free(qd_router_t *router)
         }
 
         qd_hash_handle_free(addr->hash_handle);
-
         DEQ_REMOVE_HEAD(router->addrs);
+        qd_c_entity_remove(QD_ROUTER_ADDRESS_TYPE, addr);
         free_qd_address_t(addr);
     }
 
@@ -1528,8 +1534,8 @@ qd_address_t *qd_router_register_address
 {
     char                 addr_string[1000];
     qd_router_t         *router = qd->router;
-    qd_address_t        *addr;
-    qd_field_iterator_t *iter;
+    qd_address_t        *addr = 0;
+    qd_field_iterator_t *iter = 0;
 
     strcpy(addr_string, global ? "M0" : "L");
     strcat(addr_string, address);
@@ -1543,6 +1549,7 @@ qd_address_t *qd_router_register_address
         qd_hash_insert(router->addr_hash, iter, addr, &addr->hash_handle);
         DEQ_ITEM_INIT(addr);
         DEQ_INSERT_TAIL(router->addrs, addr);
+        qd_c_entity_add(QD_ROUTER_ADDRESS_TYPE, addr);
     }
     qd_field_iterator_free(iter);
 
@@ -1553,6 +1560,7 @@ qd_address_t *qd_router_register_address
 
     if (handler)
         qd_log(router->log_source, QD_LOG_INFO, "In-Process Address Registered: %s", address);
+    assert(addr);
     return addr;
 }
 

Modified: qpid/dispatch/trunk/src/router_private.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_private.h?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_private.h (original)
+++ qpid/dispatch/trunk/src/router_private.h Fri Oct 17 23:35:35 2014
@@ -24,6 +24,7 @@
  *@internal
  */
 
+#include <qpid/dispatch/enum.h>
 #include <qpid/dispatch/router.h>
 #include <qpid/dispatch/message.h>
 #include <qpid/dispatch/bitmask.h>
@@ -48,6 +49,7 @@ typedef enum {
     QD_ROUTER_MODE_EDGE,        ///< Edge router.  No transit-router capability.
     QD_ROUTER_MODE_ENDPOINT     ///< No routing except for internal modules (agent, etc.).
 } qd_router_mode_t;
+ENUM_DECLARE(qd_router_mode);
 
 typedef enum {
     QD_LINK_ENDPOINT,   ///< A link to a connected endpoint
@@ -55,7 +57,7 @@ typedef enum {
     QD_LINK_ROUTER,     ///< A link to a peer router in the same area
     QD_LINK_AREA        ///< A link to a peer router in a different area (area boundary)
 } qd_link_type_t;
-
+ENUM_DECLARE(qd_link_type);
 
 typedef struct qd_routed_event_t {
     DEQ_LINKS(struct qd_routed_event_t);

Modified: qpid/dispatch/trunk/src/router_pynode.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/router_pynode.c?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/router_pynode.c (original)
+++ qpid/dispatch/trunk/src/router_pynode.c Fri Oct 17 23:35:35 2014
@@ -26,6 +26,7 @@
 #include "dispatch_private.h"
 #include "router_private.h"
 #include "waypoint_private.h"
+#include "c_entity.h"
 
 static qd_address_semantics_t router_addr_semantics = QD_FANOUT_SINGLE | QD_BIAS_CLOSEST | QD_CONGESTION_DROP | QD_DROP_FOR_SLOW_CONSUMERS | QD_BYPASS_VALID_ORIGINS;
 
@@ -81,6 +82,7 @@ static char *qd_add_router(qd_router_t *
     addr->semantics = router_addr_semantics;
     qd_hash_insert(router->addr_hash, iter, addr, &addr->hash_handle);
     DEQ_INSERT_TAIL(router->addrs, addr);
+    qd_c_entity_add(QD_ROUTER_ADDRESS_TYPE, addr);
     qd_field_iterator_free(iter);
 
     //
@@ -96,6 +98,7 @@ static char *qd_add_router(qd_router_t *
     rnode->valid_origins = qd_bitmask(0);
 
     DEQ_INSERT_TAIL(router->routers, rnode);
+    qd_c_entity_add(QD_ROUTER_NODE_TYPE, rnode);
 
     //
     // Link the router record to the address record.
@@ -139,6 +142,9 @@ static char *qd_del_router(qd_router_t *
     qd_address_t     *oaddr = rnode->owning_addr;
     assert(oaddr);
 
+    qd_c_entity_remove(QD_ROUTER_ADDRESS_TYPE, oaddr);
+    qd_c_entity_remove(QD_ROUTER_NODE_TYPE, rnode);
+
     //
     // Unlink the router node from the address record
     //
@@ -387,6 +393,7 @@ static PyObject* qd_map_destination(PyOb
         addr->semantics = router_semantics_for_addr(router, iter, phase, &unused);
         DEQ_ITEM_INIT(addr);
         DEQ_INSERT_TAIL(router->addrs, addr);
+        qd_c_entity_add(QD_ROUTER_ADDRESS_TYPE, addr);
     }
     qd_field_iterator_free(iter);
 

Modified: qpid/dispatch/trunk/src/server.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/server.c?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/server.c (original)
+++ qpid/dispatch/trunk/src/server.c Fri Oct 17 23:35:35 2014
@@ -21,6 +21,8 @@
 #include <qpid/dispatch/threading.h>
 #include <qpid/dispatch/log.h>
 #include <qpid/dispatch/amqp.h>
+#include "entity_private.h"
+#include "c_entity.h"
 #include "dispatch_private.h"
 #include "server_private.h"
 #include "timer_private.h"
@@ -37,6 +39,14 @@ ALLOC_DEFINE(qd_connector_t);
 ALLOC_DEFINE(qd_connection_t);
 ALLOC_DEFINE(qd_user_fd_t);
 
+static const char *conn_state_names[] = {
+    "connecting",
+    "opening",
+    "operational",
+    "failed",
+    "user"
+};
+ENUM_DEFINE(conn_state, conn_state_names);
 
 static qd_thread_t *thread(qd_server_t *qd_server, int id)
 {
@@ -53,6 +63,44 @@ static qd_thread_t *thread(qd_server_t *
     return thread;
 }
 
+qd_error_t qd_entity_update_connection(qd_entity_t* entity, void *impl);
+
+static qd_error_t connection_entity_update_host(qd_entity_t* entity, qd_connection_t *conn)
+{
+    const qd_server_config_t *config;
+    if (conn->connector) {
+        config = conn->connector->config;
+        char host[strlen(config->host)+strlen(config->port)+2];
+        snprintf(host, sizeof(host), "%s:%s", config->host, config->port);
+        return qd_entity_set_string(entity, "host", host);
+    }
+    else
+        return qd_entity_set_string(entity, "host", pn_connector_name(conn->pn_cxtr));
+}
+
+qd_error_t qd_c_entity_update_connection(qd_entity_t* entity, void *impl)
+{
+    qd_connection_t *conn = (qd_connection_t*)impl;
+    const qd_server_config_t *config =
+        conn->connector ? conn->connector->config : conn->listener->config;
+
+    if ((qd_entity_has(entity, "identity") ||
+         qd_entity_set_string(entity, "identity", pn_connector_name(conn->pn_cxtr)) == 0) &&
+        qd_entity_set_string(entity, "state", conn_state_name(conn->state)) == 0 &&
+        qd_entity_set_string(
+            entity, "container",
+            conn->pn_conn ? pn_connection_remote_container(conn->pn_conn) : 0) == 0 &&
+        connection_entity_update_host(entity, conn) == 0 &&
+        /* FIXME aconway 2014-10-14: change attr name to sasl-mechanisms for consistency? */
+        qd_entity_set_string(entity, "sasl", config->sasl_mechanisms) == 0 &&
+        qd_entity_set_string(entity, "role", config->role) == 0 &&
+        qd_entity_set_string(entity, "dir", conn->connector ? "out" : "in") == 0)
+        return QD_ERROR_NONE;
+    return qd_error_code();
+}
+
+
+
 
 static void thread_process_listeners(qd_server_t *qd_server)
 {
@@ -93,6 +141,7 @@ static void thread_process_listeners(qd_
 
         // qd_server->lock is already locked
         DEQ_INSERT_TAIL(qd_server->connections, ctx);
+        qd_c_entity_add(QD_CONNECTION_TYPE, ctx);
 
         //
         // Get a pointer to the transport so we can insert security components into it
@@ -492,6 +541,7 @@ static void *thread_run(void *arg)
             // Check to see if the connector was closed during processing
             //
             if (pn_connector_closed(cxtr)) {
+                qd_c_entity_remove(QD_CONNECTION_TYPE, ctx);
                 //
                 // Connector is closed.  Free the context and the connector.
                 //
@@ -508,6 +558,7 @@ static void *thread_run(void *arg)
 
                 sys_mutex_lock(qd_server->lock);
                 DEQ_REMOVE(qd_server->connections, ctx);
+
                 pn_connector_free(cxtr);
                 if (conn)
                     pn_connection_free(conn);
@@ -607,6 +658,8 @@ static void cxtr_try_open(void *context)
     sys_mutex_lock(ct->server->lock);
     ctx->pn_cxtr = pn_connector(ct->server->driver, ct->config->host, ct->config->port, (void*) ctx);
     DEQ_INSERT_TAIL(ct->server->connections, ctx);
+    qd_c_entity_add(QD_CONNECTION_TYPE, ctx);
+
     sys_mutex_unlock(ct->server->lock);
 
     ct->ctx   = ctx;
@@ -658,7 +711,7 @@ static void cxtr_try_open(void *context)
 }
 
 
-qd_server_t *qd_server(int thread_count, const char *container_name)
+qd_server_t *qd_server(qd_dispatch_t *qd, int thread_count, const char *container_name)
 {
     int i;
 
@@ -667,6 +720,7 @@ qd_server_t *qd_server(int thread_count,
         return 0;
 
     DEQ_INIT(qd_server->connections);
+    qd_server->qd              = qd;
     qd_server->log_source      = qd_log_source("SERVER");
     qd_server->thread_count    = thread_count;
     qd_server->container_name  = container_name;

Modified: qpid/dispatch/trunk/src/server_private.h
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/server_private.h?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/server_private.h (original)
+++ qpid/dispatch/trunk/src/server_private.h Fri Oct 17 23:35:35 2014
@@ -19,6 +19,7 @@
  * under the License.
  */
 
+#include <qpid/dispatch/enum.h>
 #include <qpid/dispatch/server.h>
 #include <qpid/dispatch/user_fd.h>
 #include <qpid/dispatch/alloc.h>
@@ -43,6 +44,7 @@ typedef enum {
     CONN_STATE_FAILED,
     CONN_STATE_USER
 } conn_state_t;
+ENUM_DECLARE(conn_state);
 
 #define CONTEXT_NO_OWNER -1
 
@@ -127,6 +129,7 @@ DEQ_DECLARE(qd_work_item_t, qd_work_list
 
 
 struct qd_server_t {
+    qd_dispatch_t           *qd;
     int                      thread_count;
     const char              *container_name;
     pn_driver_t             *driver;

Modified: qpid/dispatch/trunk/src/waypoint.c
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/src/waypoint.c?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/src/waypoint.c (original)
+++ qpid/dispatch/trunk/src/waypoint.c Fri Oct 17 23:35:35 2014
@@ -20,6 +20,7 @@
 #include "waypoint_private.h"
 #include "dispatch_private.h"
 #include "router_private.h"
+#include "c_entity.h"
 #include <qpid/dispatch/ctools.h>
 #include <qpid/dispatch/threading.h>
 #include <qpid/dispatch/connection_manager.h>
@@ -68,6 +69,7 @@ static void qd_waypoint_visit_sink_LH(qd
             DEQ_INSERT_TAIL(router->addrs, addr);
             addr->waypoint  = true;
             addr->semantics = router_semantics_for_addr(router, iter, wp->in_phase, &unused);
+            qd_c_entity_add(QD_ROUTER_ADDRESS_TYPE, addr);
         }
 
         wp->in_address = addr;
@@ -97,6 +99,7 @@ static void qd_waypoint_visit_sink_LH(qd
         rlink->target         = 0;
         DEQ_INIT(rlink->event_fifo);
         DEQ_INIT(rlink->msg_fifo);
+        qd_c_entity_add(QD_ROUTER_LINK_TYPE, rlink);
         DEQ_INSERT_TAIL(router->links, rlink);
         qd_link_set_context(wp->out_link, rlink);
         qd_router_add_link_ref_LH(&addr->rlinks, rlink);
@@ -141,6 +144,7 @@ static void qd_waypoint_visit_source_LH(
             DEQ_INSERT_TAIL(router->addrs, addr);
             addr->waypoint  = true;
             addr->semantics = router_semantics_for_addr(router, iter, wp->out_phase, &unused);
+            qd_c_entity_add(QD_ROUTER_ADDRESS_TYPE, addr);
         }
 
         wp->out_address = addr;
@@ -170,6 +174,7 @@ static void qd_waypoint_visit_source_LH(
         rlink->target         = 0;
         DEQ_INIT(rlink->event_fifo);
         DEQ_INIT(rlink->msg_fifo);
+        qd_c_entity_add(QD_ROUTER_LINK_TYPE, rlink);
         DEQ_INSERT_TAIL(router->links, rlink);
         qd_link_set_context(wp->in_link, rlink);
 

Modified: qpid/dispatch/trunk/tests/management/client.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/management/client.py?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/management/client.py (original)
+++ qpid/dispatch/trunk/tests/management/client.py Fri Oct 17 23:35:35 2014
@@ -25,10 +25,10 @@ from qpid_dispatch.management import Url
 class UrlTest(unittest.TestCase):
 
     def test_url(self):
-        url = Url(scheme='amqp', user='me', password='secret', host='myhost', port=1234, path='foobar')
+        url = Url(scheme='amqp', username='me', password='secret', host='myhost', port=1234, path='foobar')
         self.assertEqual(str(url), "amqp://me:secret@myhost:1234/foobar")
         self.assertEqual(
-            [url.scheme, url.user, url.password, url.host, url.port, url.path],
+            [url.scheme, url.username, url.password, url.host, url.port, url.path],
             ['amqp', 'me', 'secret', 'myhost', 1234, 'foobar']
         )
 
@@ -42,22 +42,13 @@ class UrlTest(unittest.TestCase):
         self.assertNotEqual(str(url), "amqp://me:secret@myhost:5555/foobar")
 
         # Check that we allow None for scheme, port
-        url = Url(user='me', password='secret', host='myhost', path='foobar')
+        url = Url(username='me', password='secret', host='myhost', path='foobar')
         self.assertEqual(str(url), "me:secret@myhost/foobar")
         self.assertEqual(
-            [url.scheme, url.user, url.password, url.host, url.port, url.path],
+            [url.scheme, url.username, url.password, url.host, url.port, url.path],
             [None, 'me', 'secret', 'myhost', None, 'foobar']
         )
 
-        # Scheme defaults
-        self.assertEqual(str(Url("me:secret@myhost/foobar").defaults()),
-                         "amqp://me:secret@myhost:5672/foobar")
-        # Correct port for amqps vs. amqps
-        self.assertEqual(str(Url("amqps://me:secret@myhost/foobar").defaults()),
-                         "amqps://me:secret@myhost:5671/foobar")
-        self.assertEqual(str(Url("amqp://me:secret@myhost/foobar").defaults()),
-                         "amqp://me:secret@myhost:5672/foobar")
-
         # Empty string for path
         self.assertEqual(Url("myhost/").path, "")
         self.assertIsNone(Url("myhost").path)

Modified: qpid/dispatch/trunk/tests/management/qdrouter.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/management/qdrouter.py?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/management/qdrouter.py (original)
+++ qpid/dispatch/trunk/tests/management/qdrouter.py Fri Oct 17 23:35:35 2014
@@ -73,21 +73,21 @@ listener {
 
         content = conf._default_ids(content)
         self.assertEqual(content, [
-            ["router", {"mode":"standalone", "name":"router0", "identity":"router0"}],
+            ["router", {"mode":"standalone", "name":"router:0", "identity":"router:0"}],
             ["listener", {"name":"l0", "identity":"l0", "sasl-mechanisms":"ANONYMOUS", "password":"secret"}],
             ["listener", {"name":"l1", "identity":"l1", "sasl-mechanisms":"ANONYMOUS", "port":"1234"}],
-            ["listener", {"name":"listener2", "identity":"listener2", "sasl-mechanisms":"ANONYMOUS", "port":"4567"}]
+            ["listener", {"name":"listener:2", "identity":"listener:2", "sasl-mechanisms":"ANONYMOUS", "port":"4567"}]
         ])
 
         conf.load(conf_text.split("\n"))
         router = conf.by_type('router').next()
-        self.assertEqual(router['name'], 'router0')
-        self.assertEqual(router['identity'], 'router0')
+        self.assertEqual(router['name'], 'router:0')
+        self.assertEqual(router['identity'], 'router:0')
         listeners = list(conf.by_type('listener'))
         self.assertEqual(len(listeners), 3)
         self.assertEqual(listeners[0]['name'], 'l0')
-        self.assertEqual(listeners[2]['name'], 'listener2')
-        self.assertEqual(listeners[2]['identity'], 'listener2')
+        self.assertEqual(listeners[2]['name'], 'listener:2')
+        self.assertEqual(listeners[2]['identity'], 'listener:2')
 
 if __name__ == '__main__':
     unittest.main()

Modified: qpid/dispatch/trunk/tests/management/schema.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/management/schema.py?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/management/schema.py (original)
+++ qpid/dispatch/trunk/tests/management/schema.py Fri Oct 17 23:35:35 2014
@@ -21,7 +21,7 @@
 #pylint: disable=wildcard-import,missing-docstring,too-many-public-methods
 
 import unittest, json
-from qpid_dispatch_internal.management.schema import Schema, BooleanType, EnumType, AttributeType, schema_file, ValidationError, EnumValue, EntityType
+from qpid_dispatch_internal.management.schema import Schema, BooleanType, EnumType, AttributeType, ValidationError, EnumValue, EntityType
 import collections
 
 def replace_od(thing):
@@ -152,14 +152,6 @@ class SchemaTest(unittest.TestCase):
         self.assertEqual({'identity': 'x', 'name': 'y'}, e.validate({'identity': 'x', 'name':'y'}))
         self.assertRaises(ValidationError, e.validate, {})
 
-    qdrouter_json = schema_file('qdrouter.json')
-
-    @staticmethod
-    def load_schema(fname=qdrouter_json):
-        with open(fname) as f:
-            j = json.load(f)
-            return Schema(**j)
-
     def test_schema_dump(self):
         s = Schema(**SCHEMA_1)
         self.maxDiff = None     # pylint: disable=invalid-name

Modified: qpid/dispatch/trunk/tests/run.py.in
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/run.py.in?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/run.py.in (original)
+++ qpid/dispatch/trunk/tests/run.py.in Fri Oct 17 23:35:35 2014
@@ -99,7 +99,7 @@ def is_binary_exe(program):
     p = Popen(['file', '-bi', program], stdout=PIPE, stderr=PIPE)
     return p.communicate()[0].startswith('application/x-executable')
 
-def with_valgrind(args):
+def with_valgrind(args, outfile=None):
     if use_valgrind() and is_binary_exe(find_exe(args[0])):
         opts = ['--leak-check=full',
                 '--demangle=yes',
@@ -107,6 +107,7 @@ def with_valgrind(args):
                 '--num-callers=12',
                 '--error-exitcode=42',
                 '--quiet']
+        if outfile: opts.append('--log-file=%s' % outfile)
         return [valgrind_exe]+opts+args
     return args
 

Modified: qpid/dispatch/trunk/tests/system_test.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/system_test.py?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/system_test.py (original)
+++ qpid/dispatch/trunk/tests/system_test.py Fri Oct 17 23:35:35 2014
@@ -208,7 +208,7 @@ class Process(subprocess.Popen):
     @classmethod
     def unique(cls, name):
         cls.unique_id += 1
-        return name + str(cls.unique_id)
+        return "%s-%s" % (name, cls.unique_id)
 
     def __init__(self, args, name=None, expect=EXIT_OK, **kwargs):
         """
@@ -228,7 +228,7 @@ class Process(subprocess.Popen):
         self.torndown = False
         kwargs.setdefault('stdout', self.out)
         kwargs.setdefault('stderr', subprocess.STDOUT)
-        args = with_valgrind(args)
+        args = with_valgrind(args, self.outfile + '.vg')
         try:
             super(Process, self).__init__(args, **kwargs)
         except Exception, e:
@@ -376,10 +376,11 @@ class Qdrouterd(Process):
         """
         def check():
             # FIXME aconway 2014-06-12: this should be a request by name, not a query.
+            # Need to rationalize addresses in management attributes.
+            # endswith check is because of M0/L/R prefixes
             addrs = self.management.query(
                 type='org.apache.qpid.dispatch.router.address',
                 attribute_names=['name', 'subscriberCount', 'remoteCount']).get_entities()
-            # FIXME aconway 2014-06-12: endswith check is because of M0/L prefixes
             addrs = [a for a in addrs if a['name'].endswith(address)]
             return addrs and addrs[0]['subscriberCount'] >= subscribers and addrs[0]['remoteCount'] >= remotes
         assert retry(check, **retry_kwargs)
@@ -398,6 +399,12 @@ class Qdrouterd(Process):
         wait_ports(self.ports)
         self.wait_connectors()
 
+    def wait_connected(self, router_id):
+        """Wait till this router is connected to router with router-id"""
+        node = Node(self.addresses[0], router_id, timeout=0.2)
+        retry_exception(lambda: node.query('org.apache.qpid.dispatch.router'))
+
+
 class Qpidd(Process):
     """Run a Qpid Daemon"""
 

Modified: qpid/dispatch/trunk/tests/system_tests_management.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/system_tests_management.py?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/system_tests_management.py (original)
+++ qpid/dispatch/trunk/tests/system_tests_management.py Fri Oct 17 23:35:35 2014
@@ -23,19 +23,24 @@ import unittest, system_test, re, os
 from qpid_dispatch.management import Node, ManagementError, Url, BadRequestStatus, NotImplementedStatus, NotFoundStatus, ForbiddenStatus
 from system_test import Qdrouterd, message, retry
 
-LISTENER = 'org.apache.qpid.dispatch.listener'
-CONNECTOR = 'org.apache.qpid.dispatch.connector'
-FIXED_ADDRESS = 'org.apache.qpid.dispatch.fixed-address'
-WAYPOINT = 'org.apache.qpid.dispatch.waypoint'
-DUMMY = 'org.apache.qpid.dispatch.dummy'
+DISPATCH = 'org.apache.qpid.dispatch'
+LISTENER = DISPATCH + '.listener'
+CONNECTOR = DISPATCH + '.connector'
+FIXED_ADDRESS = DISPATCH + '.fixed-address'
+WAYPOINT = DISPATCH + '.waypoint'
+DUMMY = DISPATCH + '.dummy'
+ROUTER = DISPATCH + '.router'
+LINK = ROUTER + '.link'
+ADDRESS = ROUTER + '.address'
+NODE = ROUTER + '.node'
 
-ADDRESS = 'org.apache.qpid.dispatch.router.address'
 
 class ManagementTest(system_test.TestCase): # pylint: disable=too-many-public-methods
 
     @classmethod
     def setUpClass(cls):
         super(ManagementTest, cls).setUpClass()
+        # Stand-alone router
         name = cls.__name__
         cls.log_file = name+".log"
         conf = Qdrouterd.Config([
@@ -52,8 +57,6 @@ class ManagementTest(system_test.TestCas
     def setUp(self):
         super(ManagementTest, self).setUp()
         self.node = self.cleanup(Node(self.router.addresses[0]))
-        # Temporary access to separate new management address.
-        self.node2 = self.cleanup(Node(Url(self.router.addresses[0], path='$management2')))
         self.maxDiff = None
         self.longMessage = True
 
@@ -61,14 +64,12 @@ class ManagementTest(system_test.TestCas
         """Test that various badly formed queries get the proper response"""
         # No operation attribute
         self.assertRaises(BadRequestStatus, self.node.call, self.node.request())
-        # Unknown operation
-        self.assertRaises(NotImplementedStatus, self.node.call, self.node.request(operation="nosuch"))
-        # No entityType or attributeList
-        self.assertRaises(BadRequestStatus, self.node.query)
+        self.assertRaises(NotImplementedStatus, self.node.call,
+                          self.node.request(operation="nosuch", type="org.amqp.management"))
 
     def test_query_type(self):
         """Query with type only"""
-        response = self.node2.query(type=LISTENER)
+        response = self.node.query(type=LISTENER)
         for attr in ['type', 'name', 'identity', 'addr', 'port']:
             self.assertTrue(attr in response.attribute_names)
         for r in response.get_dicts():
@@ -80,7 +81,7 @@ class ManagementTest(system_test.TestCas
     def test_query_type_attributes(self):
         """Query with type and attribute names"""
         attribute_names=['type', 'name', 'port']
-        response = self.node2.query(type=LISTENER, attribute_names=attribute_names)
+        response = self.node.query(type=LISTENER, attribute_names=attribute_names)
         self.assertEqual(attribute_names, response.attribute_names)
         expect = [[LISTENER, 'l%s' % i, str(self.router.ports[i])] for i in xrange(3)]
         for r in expect: # We might have extras in results due to create tests
@@ -90,12 +91,12 @@ class ManagementTest(system_test.TestCas
     def test_query_attributes(self):
         """Query with attributes only"""
         attribute_names=['type', 'name', 'port']
-        response = self.node2.query(attribute_names=attribute_names)
+        response = self.node.query(attribute_names=attribute_names)
         self.assertEqual(attribute_names, response.attribute_names)
         expect = [[LISTENER, 'l%s' % i, str(self.router.ports[i])] for i in xrange(3)]
         for r in expect: # We might have extras in results due to create tests
             self.assertTrue(r in response.results)
-        for name in ['router0', 'log0']:
+        for name in [self.router.name, 'log:0']:
             self.assertTrue([r for r in response.get_dicts() if r['name'] == name],
                             msg="Can't find result with name '%s'" % name)
 
@@ -105,7 +106,7 @@ class ManagementTest(system_test.TestCas
         assert not missing, "Not a subset, missing %s, sub=%s, super=%s"%(missing, small, big)
 
     def assert_create_ok(self, type, name, attributes):
-        entity = self.node2.create(attributes, type, name)
+        entity = self.node.create(attributes, type, name)
         self.assertMapSubset(attributes, entity.attributes)
         return entity
 
@@ -120,20 +121,16 @@ class ManagementTest(system_test.TestCas
         self.assertEqual(entity['addr'], '0.0.0.0')
 
         # Connect via the new listener
-        node3 = self.cleanup(Node(Url(port=port, path='$management')))
-        router = node3.query(type='org.apache.qpid.dispatch.router').get_entities()
+        node3 = self.cleanup(Node(Url(port=port)))
+        router = node3.query(type=ROUTER).get_entities()
         self.assertEqual(self.__class__.router.name, router[0]['name'])
 
     def test_create_log(self):
         """Create a log entity"""
-        # FIXME aconway 2014-07-04: rework log entity.
-        # - allow auto-assigned name/identity? Use module as name/identity?
-        # - 1 entity with full log state, allow updates.
         log = os.path.abspath("test_create_log.log")
-        # FIXME aconway 2014-09-08: PYAGENT->AGENT
-        self.assert_create_ok('log', 'log.1', dict(module='PYAGENT', level="error", output=log))
+        self.assert_create_ok('log', 'log.1', dict(module='AGENT', level="error", output=log))
         # Cause an error and verify it shows up in the log file.
-        self.assertRaises(ManagementError, self.node2.create, type='nosuch', name='nosuch')
+        self.assertRaises(ManagementError, self.node.create, type='nosuch', name='nosuch')
         f = self.cleanup(open(log))
         logstr = f.read()
         self.assertTrue(re.search(r'ValidationError.*nosuch', logstr),
@@ -191,21 +188,21 @@ class ManagementTest(system_test.TestCas
             f.close()
 
     def test_entity(self):
-        entity = self.node2.read(type=LISTENER, name='l0')
+        entity = self.node.read(type=LISTENER, name='l0')
         self.assertEqual('l0', entity.name)
         self.assertEqual('l0', entity.identity)
         self.assertEqual(str(self.router.ports[0]), entity.port)
 
-        entity = self.node2.read(type=LISTENER, identity='l1')
+        entity = self.node.read(type=LISTENER, identity='l1')
         self.assertEqual('l1', entity.name)
         self.assertEqual('l1', entity.identity)
         self.assertEqual(str(self.router.ports[1]), entity.port)
 
         # Bad type
-        self.assertRaises(NotFoundStatus, self.node2.read, type=CONNECTOR, name='l0')
+        self.assertRaises(NotFoundStatus, self.node.read, type=CONNECTOR, name='l0')
 
         # Unknown entity
-        self.assertRaises(NotFoundStatus, self.node2.read, type=LISTENER, name='nosuch')
+        self.assertRaises(NotFoundStatus, self.node.read, type=LISTENER, name='nosuch')
 
         # Update and delete are not allowed by the schema
         self.assertRaises(ForbiddenStatus, entity.update)
@@ -215,7 +212,7 @@ class ManagementTest(system_test.TestCas
         self.assertRaises(ForbiddenStatus, entity.call, 'nosuchop', foo="bar")
 
         # Dummy entity supports all CRUD operations
-        dummy = self.node2.create({'arg1': 'START'}, type=DUMMY, name='MyDummy', )
+        dummy = self.node.create({'arg1': 'START'}, type=DUMMY, name='MyDummy', )
         self.assertEqual(dummy.type, DUMMY)
         self.assertEqual(dummy.name, 'MyDummy')
         self.assertEqual(dummy.arg1, 'START')
@@ -237,7 +234,7 @@ class ManagementTest(system_test.TestCas
             dict(type=DUMMY, name='MyDummy', identity=identity, arg1='one', num1=42),
             dummy.attributes)
 
-        dummy2 = self.node2.read(type=DUMMY, name='MyDummy')
+        dummy2 = self.node.read(type=DUMMY, name='MyDummy')
         self.assertEqual(dummy.attributes, dummy2.attributes)
 
         self.assertEqual({'operation': 'callme', 'foo': 'bar', 'type': DUMMY, 'identity': identity},
@@ -247,19 +244,87 @@ class ManagementTest(system_test.TestCas
         self.assertRaises(BadRequestStatus, dummy.update)
 
         dummy.delete()
-        self.assertRaises(NotFoundStatus, self.node2.read, type=DUMMY, name='MyDummy')
+        self.assertRaises(NotFoundStatus, self.node.read, type=DUMMY, name='MyDummy')
+
+    def test_link(self):
+        """Verify we can find our own reply-to address in links"""
+        response = self.node.query(type=LINK)
+        path = self.node.reply_to.split('/')[-1]
+        mylink = [l for l in response.get_dicts()
+                  if l['owningAddr'] and l['owningAddr'].endswith(path)]
+        self.assertTrue(mylink)
+
+    def test_connection(self):
+        """Verify there is at least one connection"""
+        response = self.node.query(type='connection')
+        self.assertTrue(response.get_dicts())
+
+    def test_router(self):
+        """Verify router counts match entity counts"""
+        entities = self.node.query().get_entities()
+        routers = [e for e in entities if e.type == ROUTER]
+        self.assertEqual(1, len(routers))
+        router = routers[0]
+        self.assertEqual(router.linkCount, len([e for e in entities if e.type == LINK]))
+        self.assertEqual(router.addrCount, len([e for e in entities if e.type == ADDRESS]))
+
+    def test_router_node(self):
+        """Test node entity in a pair of linked routers"""
+        # Pair of linked interior routers
+        conf1 = Qdrouterd.Config([
+            ('log', {'module':'DEFAULT', 'level':'trace', 'output':'router1.log'}),
+            ('router', { 'mode': 'interior', 'router-id': 'router1'}),
+            ('listener', {'port':self.get_port(), 'role':'normal'}),
+            ('listener', {'port':self.get_port(), 'role':'inter-router'})
+        ])
+        conf2 = Qdrouterd.Config([
+            ('log', {'module':'DEFAULT', 'level':'trace', 'output':'router2.log'}),
+            ('router', { 'mode': 'interior', 'router-id': 'router2'}),
+            ('listener', {'port':self.get_port(), 'role':'normal'}),
+            ('connector', {'port':conf1.sections('listener')[1]['port'], 'role':'inter-router'})
+        ])
+        routers = [self.qdrouterd('router1', conf1, wait=False),
+                   self.qdrouterd('router2', conf2, wait=False)]
+        for r in routers: r.wait_ready()
+        routers[0].wait_connected('router2')
+        routers[1].wait_connected('router1')
+
+        nodes = [self.cleanup(Node(Url(r.addresses[0]))) for r in routers]
+
+        class RNodes(list):
+            def __call__(self):
+                self[:] = sum([n.query(type=NODE).get_entities() for n in nodes], [])
+                return self
+        rnodes = RNodes()
+
+        assert retry(lambda: len(rnodes()) >= 2)
+        self.assertEqual(['Rrouter2', 'Rrouter1'], [r.addr for r in rnodes])
+        # FIXME aconway 2014-10-15: verify nextHop and validOrigins updated correctly
+        self.assertEqual([u'amqp:/_topo/0/router2/$management', u'amqp:/_topo/0/router1/$management'],
+                         sum([n.get_mgmt_nodes() for n in nodes], []))
 
-    def test_get_types(self):
-        self.assertRaises(NotImplementedStatus, self.node2.get_types)
 
-    def test_get_attributes(self):
-        self.assertRaises(NotImplementedStatus, self.node2.get_attributes)
+
+    def test_get_types(self):
+        types = self.node.get_types()
+        self.assertIn('org.apache.qpid.dispatch.listener', types)
+        self.assertIn('org.apache.qpid.dispatch.waypoint', types)
+        self.assertIn('org.apache.qpid.dispatch.router.link', types)
 
     def test_get_operations(self):
-        self.assertRaises(NotImplementedStatus, self.node2.get_operations)
+        result = self.node.get_operations(type=DUMMY)
+        self.assertEqual({DUMMY: ["CREATE", "READ", "UPDATE", "DELETE", "CALLME"]}, result)
+        result = self.node.get_operations()
+        for type in LISTENER, WAYPOINT, LINK: self.assertIn(type, result)
+        self.assertEqual(["READ"], result[LINK])
+        self.assertEqual(["CREATE", "READ"], result[WAYPOINT])
 
-    def test_get_mgmt_nodes(self):
-        self.assertRaises(NotImplementedStatus, self.node2.get_mgmt_nodes)
+    def test_get_attributes(self):
+        result = self.node.get_attributes(type=DUMMY)
+        self.assertEqual({DUMMY: [u'arg1', u'arg2', u'num1', u'num2', u'name', u'identity', u'type']}, result)
+        result = self.node.get_attributes()
+        for type in LISTENER, WAYPOINT, LINK: self.assertIn(type, result)
+        for a in ['linkType', 'linkDir', 'owningAddr']: self.assertIn(a, result[LINK])
 
 if __name__ == '__main__':
     unittest.main()

Modified: qpid/dispatch/trunk/tests/system_tests_one_router.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/system_tests_one_router.py?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/system_tests_one_router.py (original)
+++ qpid/dispatch/trunk/tests/system_tests_one_router.py Fri Oct 17 23:35:35 2014
@@ -546,7 +546,7 @@ class RouterTest(TestCase):
         M.recv()
         M.get(response)
 
-        self.assertEqual(response.properties['statusCode'], 200)
+        assert response.properties['statusCode'] == 200, response.properties['statusDescription']
         self.assertEqual(response.correlation_id, "C1")
         self.assertEqual(response.body, [])
 
@@ -578,156 +578,6 @@ class RouterTest(TestCase):
 
         M.stop()
 
-    def test_09a_management_get_types(self):
-        addr  = "amqp:/_local/$management"
-
-        M = Messenger()
-        M.timeout = 2.0
-        M.start()
-        M.route("amqp:/*", self.address+"/$1")
-        sub = M.subscribe("amqp:/#")
-        reply = sub.address
-
-        request  = Message()
-        response = Message()
-
-        ##
-        ## Unrestricted request
-        ##
-        request.address    = addr
-        request.reply_to   = reply
-        request.properties = {u'type':u'org.amqp.management', u'name':u'self', u'operation':u'GET-TYPES'}
-
-        M.put(request)
-        M.send()
-        M.recv()
-        M.get(response)
-
-        self.assertEqual(response.properties['statusCode'], 200)
-        self.assertEqual(response.body.__class__, dict)
-        self.assertTrue('org.apache.qpid.dispatch.router' in response.body.keys())
-        self.assertTrue(len(response.body.keys()) > 2)
-
-        ##
-        ## Restricted Request one match
-        ##
-        request.address    = addr
-        request.reply_to   = reply
-        request.properties = {u'type':u'org.amqp.management', u'name':u'self', u'operation':u'GET-TYPES',
-                              u'entityType':'org.apache.qpid.dispatch.connection'}
-
-        M.put(request)
-        M.send()
-        M.recv()
-        M.get(response)
-
-        self.assertEqual(response.properties['statusCode'], 200)
-        self.assertEqual(response.body.__class__, dict)
-        self.assertTrue('org.apache.qpid.dispatch.connection' in response.body.keys())
-        self.assertEqual(len(response.body.keys()), 1)
-
-        ##
-        ## Restricted Request with no matches
-        ##
-        request.address    = addr
-        request.reply_to   = reply
-        request.properties = {u'type':u'org.amqp.management', u'name':u'self', u'operation':u'GET-TYPES',
-                              u'entityType':'com.profitron.item'}
-
-        M.put(request)
-        M.send()
-        M.recv()
-        M.get(response)
-
-        self.assertEqual(response.properties['statusCode'], 200)
-        self.assertEqual(response.body, {})
-
-        ##
-        ## Error Request
-        ##
-        request.address    = addr
-        request.reply_to   = reply
-        request.properties = {u'type':u'org.amqp.management', u'name':u'self', u'operation':u'GET-TYPES',
-                              u'entityType':['one', 'two']}
-
-        M.put(request)
-        M.send()
-        M.recv()
-        M.get(response)
-
-        self.assertEqual(response.properties['statusCode'], 400)
-
-        M.stop()
-
-
-    def test_09b_management_get_attributes(self):
-        addr  = "amqp:/_local/$management"
-
-        M = Messenger()
-        M.timeout = 2.0
-        M.start()
-        M.route("amqp:/*", self.address+"/$1")
-        sub = M.subscribe("amqp:/#")
-        reply = sub.address
-
-        request  = Message()
-        response = Message()
-
-        ##
-        ## Unrestricted request
-        ##
-        request.address    = addr
-        request.reply_to   = reply
-        request.properties = {u'type':u'org.amqp.management', u'name':u'self', u'operation':u'GET-ATTRIBUTES'}
-
-        M.put(request)
-        M.send()
-        M.recv()
-        M.get(response)
-
-        self.assertEqual(response.properties['statusCode'], 200)
-        self.assertEqual(response.body.__class__, dict)
-        self.assertTrue('org.apache.qpid.dispatch.router' in response.body.keys())
-        self.assertTrue(len(response.body.keys()) > 2)
-        self.assertTrue(response.body['org.apache.qpid.dispatch.router'].__class__, list)
-
-        ##
-        ## Restricted Request with a match
-        ##
-        request.address    = addr
-        request.reply_to   = reply
-        request.properties = {u'type':u'org.amqp.management', u'name':u'self', u'operation':u'GET-ATTRIBUTES',
-                              u'entityType':'org.apache.qpid.dispatch.router'}
-
-        M.put(request)
-        M.send()
-        M.recv()
-        M.get(response)
-
-        self.assertEqual(response.properties['statusCode'], 200)
-        self.assertEqual(response.body.__class__, dict)
-        self.assertTrue('org.apache.qpid.dispatch.router' in response.body.keys())
-        self.assertEqual(len(response.body.keys()), 1)
-        self.assertTrue('mode' in response.body['org.apache.qpid.dispatch.router'])
-
-        ##
-        ## Restricted Request with no matches
-        ##
-        request.address    = addr
-        request.reply_to   = reply
-        request.properties = {u'type':u'org.amqp.management', u'name':u'self', u'operation':u'GET-ATTRIBUTES',
-                              u'entityType':'com.profitron.item'}
-
-        M.put(request)
-        M.send()
-        M.recv()
-        M.get(response)
-
-        self.assertEqual(response.properties['statusCode'], 200)
-        self.assertEqual(response.body, {})
-
-        M.stop()
-
 
     def test_09c_management_get_operations(self):
         addr  = "amqp:/_local/$management"

Modified: qpid/dispatch/trunk/tests/system_tests_qdmanage.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/system_tests_qdmanage.py?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/system_tests_qdmanage.py (original)
+++ qpid/dispatch/trunk/tests/system_tests_qdmanage.py Fri Oct 17 23:35:35 2014
@@ -20,7 +20,7 @@
 import re, json, unittest
 from system_test import TestCase, Process, Qdrouterd
 from subprocess import PIPE, STDOUT
-from copy import copy
+
 
 DUMMY = "org.apache.qpid.dispatch.dummy"
 
@@ -33,28 +33,26 @@ class QdmanageTest(TestCase):
         config = Qdrouterd.Config([
             ('listener', {'port': cls.tester.get_port()})
         ])
-        cls.router = cls.tester.qdrouterd('test-router', config)
+        cls.router = cls.tester.qdrouterd('test-router', config, wait=True)
 
     def run_qdmanage(self, cmd, input=None, expect=Process.EXIT_OK, **kwargs):
         args = filter(None, sum([["--%s" % k.replace('_','-'), v]
                                  for k, v in kwargs.iteritems()], []))
         p = self.popen(
-            ['qdmanage', cmd, '--bus', self.router.hostports[0]+"/$management2",
-             '--indent=-1']+args,
+            ['qdmanage', cmd, '--bus', self.router.hostports[0], '--indent=-1']+args,
             stdin=PIPE, stdout=PIPE, stderr=STDOUT, expect=expect)
         out = p.communicate(input)[0]
-        if expect == Process.EXIT_OK:
-            assert p.returncode == 0, "%s exit %s, output:\n%s" % (p.args, p.returncode, out)
-        else:
-            assert p.returncode != 0, "%s expected to fail but exit 0" %(p.args)
+        try:
+            p.teardown()
+        except Exception, e:
+            raise Exception("%s\n%s" % (e, out))
         return out
 
     def test_help(self):
         self.run_qdmanage('help', r'Usage: qdmanage', expect=Process.EXIT_FAIL)
         for cmd in ['create', 'read', 'update', 'delete', 'query']:
             out = self.run_qdmanage(cmd, help=None)
-            assert re.search('Usage: %s \[options\]' % cmd, out, re.I), \
-                "Can't find '%s' in '%s'" % (regexp, out)
+            assert re.search('Usage: %s \[options\]' % cmd, out, re.I)
 
     def assert_entity_equal(self, expect, actual, copy=None):
         """Copy keys in copy from actual to idenity, then assert maps equal."""
@@ -119,11 +117,12 @@ class QdmanageTest(TestCase):
 
     def test_query(self):
         def long_type(name): return u'org.apache.qpid.dispatch.'+name
-        TYPES=['listener', 'log', 'container', 'router']
+        TYPES=['listener', 'log', 'container', 'router', 'router.link']
         LONG_TYPES=[long_type(name) for name in TYPES]
 
         qall = json.loads(self.run_qdmanage('query'))
-        self.assertTrue(set(LONG_TYPES) <= set([e['type'] for e in qall]))
+        qall_types = set([e['type'] for e in qall])
+        for t in LONG_TYPES: self.assertIn(t, qall_types)
 
         qlistener = json.loads(self.run_qdmanage('query', type='listener'))
         self.assertEqual([long_type('listener')], [e['type'] for e in qlistener])
@@ -132,10 +131,12 @@ class QdmanageTest(TestCase):
         qattr = json.loads(
             self.run_qdmanage('query', attribute_names='["type", "name"]'))
         for e in qattr: self.assertEqual(2, len(e))
-        self.assertEqual(
-            set([(e['name'], e['type']) for e in qall]),
-            set([(e['name'], e['type']) for e in qattr]))
 
+        def name_type(entities):
+            ignore_types = [long_type(t) for t in ['router.link', 'connection', 'router.address']]
+            return set((e['name'], e['type']) for e in entities
+                       if e['type'] not in ignore_types)
+        self.assertEqual(name_type(qall), name_type(qattr))
 
 if __name__ == '__main__':
     unittest.main()

Modified: qpid/dispatch/trunk/tests/system_tests_two_routers.py
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tests/system_tests_two_routers.py?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tests/system_tests_two_routers.py (original)
+++ qpid/dispatch/trunk/tests/system_tests_two_routers.py Fri Oct 17 23:35:35 2014
@@ -19,8 +19,8 @@
 
 import unittest, os
 from proton import Message, PENDING, ACCEPTED, REJECTED, RELEASED, SSLDomain, SSLUnavailable
-from system_test import TestCase, Qdrouterd, retry_exception
-from qpid_dispatch.management import Node
+from system_test import TestCase, Qdrouterd
+
 
 class RouterTest(TestCase):
     @classmethod
@@ -50,12 +50,8 @@ class RouterTest(TestCase):
         router('B', 'client',
                ('connector', {'role': 'inter-router', 'port': cls.routers[0].ports[1]}))
 
-        def query_through(address, router):
-            n = Node(address, router, timeout=0.2)
-            retry_exception(lambda: n.query('org.apache.qpid.dispatch.router'))
-        # Wait till we can query through each router to the other.
-        query_through(cls.routers[0].addresses[0], 'QDR.B')
-        query_through(cls.routers[1].addresses[0], 'QDR.A')
+        cls.routers[0].wait_connected('QDR.B')
+        cls.routers[1].wait_connected('QDR.A')
 
 
     def test_00_discard(self):
@@ -474,8 +470,8 @@ class RouterTest(TestCase):
         M.recv()
         M.get(response)
 
-        self.assertEqual(response.properties['statusCode'], 200)
-        self.assertTrue('amqp:/_topo/0/QDR.B/$management' in response.body)
+        assert response.properties['statusCode'] == 200, response.properties['statusDescription']
+        self.assertIn('amqp:/_topo/0/QDR.B/$management', response.body)
 
         request.address    = "amqp:/_topo/0/QDR.B/$management"
         request.reply_to   = reply

Modified: qpid/dispatch/trunk/tools/qdmanage
URL: http://svn.apache.org/viewvc/qpid/dispatch/trunk/tools/qdmanage?rev=1632696&r1=1632695&r2=1632696&view=diff
==============================================================================
--- qpid/dispatch/trunk/tools/qdmanage (original)
+++ qpid/dispatch/trunk/tools/qdmanage Fri Oct 17 23:35:35 2014
@@ -34,7 +34,9 @@ class QdManage(object):
 
     class Commands(list):
         """Decorator to collect command names."""
-        def __call__(self, func): self.append(func.__name__); return func
+        def __call__(self, func):
+            self.append(func.__name__.replace('_', '-'));
+            return func
 
     commands = Commands()
 
@@ -77,9 +79,9 @@ For help with a command: %s <command> --
         self.op.add_option_group(connection_options(self.op))
         json_group = optparse.OptionGroup(self.op, "JSON Formatting options")
         json_group.add_option("--indent", action="store", type="int", default=2, metavar="<spaces>",
-                           help="Indent for pretty-printing output. -1 means don't pretty-print (default %default)")
+                              help="Indent for pretty-printing output. -1 means don't pretty-print (default %default)")
         self.op.add_option_group(json_group)
-        command = getattr(self, argv[1])
+        command = getattr(self, argv[1].replace('-', '_'))
         command()               # Call the command method
 
     def setup(self, description, call_opts, other_opts=None):



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org