diff options
| author | Aidan Skinner <aidan@apache.org> | 2009-09-09 13:05:43 +0000 |
|---|---|---|
| committer | Aidan Skinner <aidan@apache.org> | 2009-09-09 13:05:43 +0000 |
| commit | c1ebe66bfab328c5192a35c21ea290b5c45f40f5 (patch) | |
| tree | 6e61e50d92442f29287a82c22b54de6beac43b2c /qpid/cpp/bindings | |
| parent | 7b28732091473d93ce7546c70fa1d2dbd685161a (diff) | |
| download | qpid-python-c1ebe66bfab328c5192a35c21ea290b5c45f40f5.tar.gz | |
Merge from trunk
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-network-refactor@812936 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/cpp/bindings')
| -rw-r--r-- | qpid/cpp/bindings/qmf/Makefile.am | 10 | ||||
| -rw-r--r-- | qpid/cpp/bindings/qmf/python/Makefile.am | 9 | ||||
| -rw-r--r-- | qpid/cpp/bindings/qmf/python/python.i | 120 | ||||
| -rw-r--r-- | qpid/cpp/bindings/qmf/python/qmf.py | 854 | ||||
| -rw-r--r-- | qpid/cpp/bindings/qmf/qmfengine.i | 30 | ||||
| -rw-r--r-- | qpid/cpp/bindings/qmf/ruby/Makefile.am | 4 | ||||
| -rw-r--r-- | qpid/cpp/bindings/qmf/ruby/qmf.rb | 1131 | ||||
| -rw-r--r-- | qpid/cpp/bindings/qmf/ruby/ruby.i | 42 | ||||
| -rw-r--r-- | qpid/cpp/bindings/qmf/tests/Makefile.am | 8 | ||||
| -rwxr-xr-x | qpid/cpp/bindings/qmf/tests/agent_ruby.rb | 111 | ||||
| -rw-r--r-- | qpid/cpp/bindings/qmf/tests/python_agent.py | 192 | ||||
| -rwxr-xr-x | qpid/cpp/bindings/qmf/tests/python_console.py | 99 | ||||
| -rwxr-xr-x | qpid/cpp/bindings/qmf/tests/ruby_console.rb | 61 | ||||
| -rwxr-xr-x | qpid/cpp/bindings/qmf/tests/run_interop_tests | 64 |
14 files changed, 2277 insertions, 458 deletions
diff --git a/qpid/cpp/bindings/qmf/Makefile.am b/qpid/cpp/bindings/qmf/Makefile.am index 68312a4208..eebb4b94de 100644 --- a/qpid/cpp/bindings/qmf/Makefile.am +++ b/qpid/cpp/bindings/qmf/Makefile.am @@ -20,6 +20,14 @@ if HAVE_SWIG EXTRA_DIST = qmfengine.i -SUBDIRS = ruby tests +SUBDIRS = tests + +if HAVE_RUBY_DEVEL +SUBDIRS += ruby +endif + +if HAVE_PYTHON_DEVEL +SUBDIRS += python +endif endif diff --git a/qpid/cpp/bindings/qmf/python/Makefile.am b/qpid/cpp/bindings/qmf/python/Makefile.am index 7b3f4d3be7..f51d26bfad 100644 --- a/qpid/cpp/bindings/qmf/python/Makefile.am +++ b/qpid/cpp/bindings/qmf/python/Makefile.am @@ -35,11 +35,12 @@ pylibdir = $(PYTHON_LIB) lib_LTLIBRARIES = _qmfengine.la -_qmfengine_la_LDFLAGS = -avoid-version -module -shrext "$(PYTHON_SO)" -_qmfengine_la_LIBADD = $(PYTHON_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfcommon.la +#_qmfengine_la_LDFLAGS = -avoid-version -module -shrext "$(PYTHON_SO)" +#_qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".so" +_qmfengine_la_LDFLAGS = -avoid-version -module -shared +_qmfengine_la_LIBADD = $(PYTHON_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfagent.la _qmfengine_la_CXXFLAGS = $(INCLUDES) -I$(srcdir)/qmf -I$(PYTHON_INC) -_qmfengine_la_SOURCES = \ - qmfengine.cpp +nodist__qmfengine_la_SOURCES = qmfengine.cpp CLEANFILES = $(generated_file_list) diff --git a/qpid/cpp/bindings/qmf/python/python.i b/qpid/cpp/bindings/qmf/python/python.i index ea14efd4dd..5e25d155f9 100644 --- a/qpid/cpp/bindings/qmf/python/python.i +++ b/qpid/cpp/bindings/qmf/python/python.i @@ -19,17 +19,125 @@ %module qmfengine -// These are probably wrong.. just to get it to compile for now. -%typemap (in) void * -{ - $1 = (void *) $input; + +/* unsigned32 Convert from Python --> C */ +%typemap(in) uint32_t { + if (PyInt_Check($input)) { + $1 = (uint32_t) PyInt_AsUnsignedLongMask($input); + } else if (PyLong_Check($input)) { + $1 = (uint32_t) PyLong_AsUnsignedLong($input); + } else { + SWIG_exception_fail(SWIG_ValueError, "unknown integer type"); + } +} + +/* unsinged32 Convert from C --> Python */ +%typemap(out) uint32_t { + $result = PyInt_FromLong((long)$1); +} + + +/* unsigned16 Convert from Python --> C */ +%typemap(in) uint16_t { + if (PyInt_Check($input)) { + $1 = (uint16_t) PyInt_AsUnsignedLongMask($input); + } else if (PyLong_Check($input)) { + $1 = (uint16_t) PyLong_AsUnsignedLong($input); + } else { + SWIG_exception_fail(SWIG_ValueError, "unknown integer type"); + } +} + +/* unsigned16 Convert from C --> Python */ +%typemap(out) uint16_t { + $result = PyInt_FromLong((long)$1); +} + + +/* signed32 Convert from Python --> C */ +%typemap(in) int32_t { + if (PyInt_Check($input)) { + $1 = (int32_t) PyInt_AsLong($input); + } else if (PyLong_Check($input)) { + $1 = (int32_t) PyLong_AsLong($input); + } else { + SWIG_exception_fail(SWIG_ValueError, "unknown integer type"); + } +} + +/* signed32 Convert from C --> Python */ +%typemap(out) int32_t { + $result = PyInt_FromLong((long)$1); +} + + +/* unsigned64 Convert from Python --> C */ +%typemap(in) uint64_t { +%#ifdef HAVE_LONG_LONG + if (PyLong_Check($input)) { + $1 = (uint64_t)PyLong_AsUnsignedLongLong($input); + } else if (PyInt_Check($input)) { + $1 = (uint64_t)PyInt_AsUnsignedLongLongMask($input); + } else +%#endif + { + SWIG_exception_fail(SWIG_ValueError, "unsupported integer size - uint64_t input too large"); + } +} + +/* unsigned64 Convert from C --> Python */ +%typemap(out) uint64_t { +%#ifdef HAVE_LONG_LONG + $result = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)$1); +%#else + SWIG_exception_fail(SWIG_ValueError, "unsupported integer size - uint64_t output too large"); +%#endif +} + +/* signed64 Convert from Python --> C */ +%typemap(in) int64_t { +%#ifdef HAVE_LONG_LONG + if (PyLong_Check($input)) { + $1 = (int64_t)PyLong_AsLongLong($input); + } else if (PyInt_Check($input)) { + $1 = (int64_t)PyInt_AsLong($input); + } else +%#endif + { + SWIG_exception_fail(SWIG_ValueError, "unsupported integer size - int64_t input too large"); + } +} + +/* signed64 Convert from C --> Python */ +%typemap(out) int64_t { +%#ifdef HAVE_LONG_LONG + $result = PyLong_FromLongLong((PY_LONG_LONG)$1); +%#else + SWIG_exception_fail(SWIG_ValueError, "unsupported integer size - int64_t output too large"); +%#endif } -%typemap (out) void * -{ + +/* Convert from Python --> C */ +%typemap(in) void * { + $1 = (void *)$input; +} + +/* Convert from C --> Python */ +%typemap(out) void * { $result = (PyObject *) $1; + Py_INCREF($result); +} + +%typemap (typecheck, precedence=SWIG_TYPECHECK_UINT64) uint64_t { + $1 = PyLong_Check($input) ? 1 : 0; } +%typemap (typecheck, precedence=SWIG_TYPECHECK_UINT32) uint32_t { + $1 = PyInt_Check($input) ? 1 : 0; +} + + %include "../qmfengine.i" diff --git a/qpid/cpp/bindings/qmf/python/qmf.py b/qpid/cpp/bindings/qmf/python/qmf.py new file mode 100644 index 0000000000..265f204852 --- /dev/null +++ b/qpid/cpp/bindings/qmf/python/qmf.py @@ -0,0 +1,854 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +import sys +import socket +import os +from threading import Thread +from threading import RLock +import qmfengine +from qmfengine import (ACCESS_READ_CREATE, ACCESS_READ_ONLY, ACCESS_READ_WRITE) +from qmfengine import (CLASS_EVENT, CLASS_OBJECT) +from qmfengine import (DIR_IN, DIR_IN_OUT, DIR_OUT) +from qmfengine import (TYPE_ABSTIME, TYPE_ARRAY, TYPE_BOOL, TYPE_DELTATIME, + TYPE_DOUBLE, TYPE_FLOAT, TYPE_INT16, TYPE_INT32, TYPE_INT64, + TYPE_INT8, TYPE_LIST, TYPE_LSTR, TYPE_MAP, TYPE_OBJECT, + TYPE_REF, TYPE_SSTR, TYPE_UINT16, TYPE_UINT32, TYPE_UINT64, + TYPE_UINT8, TYPE_UUID) + + + ##============================================================================== + ## CONNECTION + ##============================================================================== + +class ConnectionSettings: + #attr_reader :impl + def __init__(self, url=None): + if url: + self.impl = qmfengine.ConnectionSettings(url) + else: + self.impl = qmfengine.ConnectionSettings() + + + def set_attr(self, key, val): + if type(val) == str: + _v = qmfengine.Value(TYPE_LSTR) + _v.setString(val) + elif type(val) == bool: + _v = qmfengine.Value(TYPE_BOOL) + _v.setBool(val) + elif type(val) == int: + _v = qmfengine.Value(TYPE_UINT32) + _v.setUint(val) + else: + raise ArgumentError("Value for attribute '%s' has unsupported type: %s" % ( key, type(val))) + + self.impl.setAttr(key, _v) + + + +class ConnectionHandler: + def conn_event_connected(self): None + def conn_event_disconnected(self, error): None + def sess_event_session_closed(self, context, error): None + def sess_event_recv(self, context, message): None + + + +class Connection(Thread): + def __init__(self, settings): + Thread.__init__(self) + self._lock = RLock() + self.impl = qmfengine.ResilientConnection(settings.impl) + self._sockEngine, self._sock = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM) + self.impl.setNotifyFd(self._sockEngine.fileno()) + self._new_conn_handlers = [] + self._conn_handlers = [] + self.start() + + + def add_conn_handler(self, handler): + self._lock.acquire() + try: + self._new_conn_handlers.append(handler) + finally: + self._lock.release() + self._sockEngine.send("x") + + + def run(self): + eventImpl = qmfengine.ResilientConnectionEvent() + connected = False + new_handlers = [] + bt_count = 0 + + while True: + # print "Waiting for socket data" + self._sock.recv(1) + + self._lock.acquire() + try: + new_handlers = self._new_conn_handlers + self._new_conn_handlers = [] + finally: + self._lock.release() + + for nh in new_handlers: + self._conn_handlers.append(nh) + if connected: + nh.conn_event_connected() + + new_handlers = [] + + valid = self.impl.getEvent(eventImpl) + while valid: + try: + if eventImpl.kind == qmfengine.ResilientConnectionEvent.CONNECTED: + connected = True + for h in self._conn_handlers: + h.conn_event_connected() + + elif eventImpl.kind == qmfengine.ResilientConnectionEvent.DISCONNECTED: + connected = False + for h in self._conn_handlers: + h.conn_event_disconnected(eventImpl.errorText) + + elif eventImpl.kind == qmfengine.ResilientConnectionEvent.SESSION_CLOSED: + eventImpl.sessionContext.handler.sess_event_session_closed(eventImpl.sessionContext, eventImpl.errorText) + + elif eventImpl.kind == qmfengine.ResilientConnectionEvent.RECV: + eventImpl.sessionContext.handler.sess_event_recv(eventImpl.sessionContext, eventImpl.message) + + except: + import traceback + print "Event Exception:", sys.exc_info() + if bt_count < 2: + traceback.print_exc() + traceback.print_stack() + bt_count += 1 + + self.impl.popEvent() + valid = self.impl.getEvent(eventImpl) + + + +class Session: + def __init__(self, conn, label, handler): + self._conn = conn + self._label = label + self.handler = handler + self.handle = qmfengine.SessionHandle() + result = self._conn.impl.createSession(label, self, self.handle) + + + def __del__(self): + self._conn.impl.destroySession(self.handle) + + + + ##============================================================================== + ## OBJECTS + ##============================================================================== + +class QmfObject: + # attr_reader :impl, :object_class + def __init__(self, cls): + self.object_class = cls + self.impl = qmfengine.Object(self.object_class.impl) + + + def __del__(self): + self.impl.destroy() + + + def object_id(self): + return ObjectId(self.impl.getObjectId()) + + + def set_object_id(self, oid): + self.impl.setObjectId(oid.impl) + + + def get_attr(self, name): + val = self._value(name) + vType = val.getType() + if vType == TYPE_UINT8: return val.asUint() + elif vType == TYPE_UINT16: return val.asUint() + elif vType == TYPE_UINT32: return val.asUint() + elif vType == TYPE_UINT64: return val.asUint64() + elif vType == TYPE_SSTR: return val.asString() + elif vType == TYPE_LSTR: return val.asString() + elif vType == TYPE_ABSTIME: return val.asInt64() + elif vType == TYPE_DELTATIME: return val.asUint64() + elif vType == TYPE_REF: return val.asObjectId() + elif vType == TYPE_BOOL: return val.asBool() + elif vType == TYPE_FLOAT: return val.asFloat() + elif vType == TYPE_DOUBLE: return val.asDouble() + elif vType == TYPE_UUID: return val.asUuid() + elif vType == TYPE_INT8: return val.asInt() + elif vType == TYPE_INT16: return val.asInt() + elif vType == TYPE_INT32: return val.asInt() + elif vType == TYPE_INT64: return val.asInt64() + else: + # when TYPE_MAP + # when TYPE_OBJECT + # when TYPE_LIST + # when TYPE_ARRAY + print "Unsupported type for get_attr?", val.getType() + return None + + + def set_attr(self, name, v): + val = self._value(name) + vType = val.getType() + if vType == TYPE_UINT8: return val.setUint(v) + elif vType == TYPE_UINT16: return val.setUint(v) + elif vType == TYPE_UINT32: return val.setUint(v) + elif vType == TYPE_UINT64: return val.setUint64(v) + elif vType == TYPE_SSTR: + if v: return val.setString(v) + else: return val.setString('') + elif vType == TYPE_LSTR: + if v: return val.setString(v) + else: return val.setString('') + elif vType == TYPE_ABSTIME: return val.setInt64(v) + elif vType == TYPE_DELTATIME: return val.setUint64(v) + elif vType == TYPE_REF: return val.setObjectId(v.impl) + elif vType == TYPE_BOOL: return val.setBool(v) + elif vType == TYPE_FLOAT: return val.setFloat(v) + elif vType == TYPE_DOUBLE: return val.setDouble(v) + elif vType == TYPE_UUID: return val.setUuid(v) + elif vType == TYPE_INT8: return val.setInt(v) + elif vType == TYPE_INT16: return val.setInt(v) + elif vType == TYPE_INT32: return val.setInt(v) + elif vType == TYPE_INT64: return val.setInt64(v) + else: + # when TYPE_MAP + # when TYPE_OBJECT + # when TYPE_LIST + # when TYPE_ARRAY + print "Unsupported type for get_attr?", val.getType() + return None + + + def __getitem__(self, name): + return self.get_attr(name) + + + def __setitem__(self, name, value): + self.set_attr(name, value) + + + def inc_attr(self, name, by=1): + self.set_attr(name, self.get_attr(name) + by) + + + def dec_attr(self, name, by=1): + self.set_attr(name, self.get_attr(name) - by) + + + def _value(self, name): + val = self.impl.getValue(name) + if not val: + raise ArgumentError("Attribute '%s' not defined for class %s" % (name, self.object_class.impl.getName())) + return val + + + +class ConsoleObject(QmfObject): + # attr_reader :current_time, :create_time, :delete_time + def __init__(self, cls): + QmfObject.__init__(self, cls) + + + def update(self): pass + def mergeUpdate(self, newObject): pass + def is_deleted(self): + return self.delete_time > 0 + def index(self): pass + def method_missing(self, name, *args): pass + + + +class ObjectId: + def __init__(self, impl=None): + if impl: + self.impl = impl + else: + self.impl = qmfengine.ObjectId() + + + def object_num_high(self): + return self.impl.getObjectNumHi() + + + def object_num_low(self): + return self.impl.getObjectNumLo() + + + def __eq__(self, other): + if self.__class__ != other.__class__: return False + return (self.impl.getObjectNumHi() == other.impl.getObjectNumHi() and + self.impl.getObjectNumLo() == other.impl.getObjectNumLo()) + + + def __ne__(self, other): + return not self.__eq__(other) + + + +class Arguments: + def __init__(self, map): + self.map = map + self._by_hash = {} + key_count = self.map.keyCount() + a = 0 + while a < key_count: + self._by_hash[self.map.key(a)] = self.by_key(self.map.key(a)) + a += 1 + + + def __getitem__(self, key): + return self._by_hash[key] + + + def __setitem__(self, key, value): + self._by_hash[key] = value + self.set(key, value) + + + def __iter__(self): + return _by_hash.__iter__ + + + def by_key(self, key): + val = self.map.byKey(key) + vType = val.getType() + if vType == TYPE_UINT8: return val.asUint() + elif vType == TYPE_UINT16: return val.asUint() + elif vType == TYPE_UINT32: return val.asUint() + elif vType == TYPE_UINT64: return val.asUint64() + elif vType == TYPE_SSTR: return val.asString() + elif vType == TYPE_LSTR: return val.asString() + elif vType == TYPE_ABSTIME: return val.asInt64() + elif vType == TYPE_DELTATIME: return val.asUint64() + elif vType == TYPE_REF: return val.asObjectId() + elif vType == TYPE_BOOL: return val.asBool() + elif vType == TYPE_FLOAT: return val.asFloat() + elif vType == TYPE_DOUBLE: return val.asDouble() + elif vType == TYPE_UUID: return val.asUuid() + elif vType == TYPE_INT8: return val.asInt() + elif vType == TYPE_INT16: return val.asInt() + elif vType == TYPE_INT32: return val.asInt() + elif vType == TYPE_INT64: return val.asInt64() + else: + # when TYPE_MAP + # when TYPE_OBJECT + # when TYPE_LIST + # when TYPE_ARRAY + print "Unsupported Type for Get?", val.getType() + return None + + + def set(self, key, value): + val = self.map.byKey(key) + vType = val.getType() + if vType == TYPE_UINT8: return val.setUint(value) + elif vType == TYPE_UINT16: return val.setUint(value) + elif vType == TYPE_UINT32: return val.setUint(value) + elif vType == TYPE_UINT64: return val.setUint64(value) + elif vType == TYPE_SSTR: + if value: + return val.setString(value) + else: + return val.setString('') + elif vType == TYPE_LSTR: + if value: + return val.setString(value) + else: + return val.setString('') + elif vType == TYPE_ABSTIME: return val.setInt64(value) + elif vType == TYPE_DELTATIME: return val.setUint64(value) + elif vType == TYPE_REF: return val.setObjectId(value.impl) + elif vType == TYPE_BOOL: return val.setBool(value) + elif vType == TYPE_FLOAT: return val.setFloat(value) + elif vType == TYPE_DOUBLE: return val.setDouble(value) + elif vType == TYPE_UUID: return val.setUuid(value) + elif vType == TYPE_INT8: return val.setInt(value) + elif vType == TYPE_INT16: return val.setInt(value) + elif vType == TYPE_INT32: return val.setInt(value) + elif vType == TYPE_INT64: return val.setInt64(value) + else: + # when TYPE_MAP + # when TYPE_OBJECT + # when TYPE_LIST + # when TYPE_ARRAY + print "Unsupported Type for Set?", val.getType() + return None + + + +class Query: + def __init__(self, i=None): + if i: + self.impl = i + else: + self.impl = qmfengine.Query() + + + def package_name(self): return self.impl.getPackage() + def class_name(self): return self.impl.getClass() + def object_id(self): + _objid = self.impl.getObjectId() + if _objid: + return ObjectId(_objid) + else: + return None + OPER_AND = qmfengine.Query.OPER_AND + OPER_OR = qmfengine.Query.OPER_OR + + + + ##============================================================================== + ## SCHEMA + ##============================================================================== + + + +class SchemaArgument: + #attr_reader :impl + def __init__(self, name, typecode, kwargs={}): + self.impl = qmfengine.SchemaArgument(name, typecode) + if kwargs.has_key("dir"): self.impl.setDirection(kwargs["dir"]) + if kwargs.has_key("unit"): self.impl.setUnit(kwargs["unit"]) + if kwargs.has_key("desc"): self.impl.setDesc(kwargs["desc"]) + + + +class SchemaMethod: + # attr_reader :impl + def __init__(self, name, kwargs={}): + self.impl = qmfengine.SchemaMethod(name) + if kwargs.has_key("desc"): self.impl.setDesc(kwargs["desc"]) + self._arguments = [] + + + def add_argument(self, arg): + self._arguments.append(arg) + self.impl.addArgument(arg.impl) + + +class SchemaProperty: + #attr_reader :impl + def __init__(self, name, typecode, kwargs={}): + self.impl = qmfengine.SchemaProperty(name, typecode) + if kwargs.has_key("access"): self.impl.setAccess(kwargs["access"]) + if kwargs.has_key("index"): self.impl.setIndex(kwargs["index"]) + if kwargs.has_key("optional"): self.impl.setOptional(kwargs["optional"]) + if kwargs.has_key("unit"): self.impl.setUnit(kwargs["unit"]) + if kwargs.has_key("desc"): self.impl.setDesc(kwargs["desc"]) + + + def name(self): + return self.impl.getName() + + + +class SchemaStatistic: + # attr_reader :impl + def __init__(self, name, typecode, kwargs={}): + self.impl = qmfengine.SchemaStatistic(name, typecode) + if kwargs.has_key("unit"): self.impl.setUnit(kwargs["unit"]) + if kwargs.has_key("desc"): self.impl.setDesc(kwargs["desc"]) + + + +class SchemaClassKey: + #attr_reader :impl + def __init__(self, i): + self.impl = i + + + def get_package(self): + self.impl.getPackageName() + + + def get_class(self): + self.impl.getClassName() + + + +class SchemaObjectClass: + # attr_reader :impl + def __init__(self, package, name, kwargs={}): + self.impl = qmfengine.SchemaObjectClass(package, name) + self._properties = [] + self._statistics = [] + self._methods = [] + + + def add_property(self, prop): + self._properties.append(prop) + self.impl.addProperty(prop.impl) + + + def add_statistic(self, stat): + self._statistics.append(stat) + self.impl.addStatistic(stat.impl) + + + def add_method(self, meth): + self._methods.append(meth) + self.impl.addMethod(meth.impl) + + + def name(self): + return self.impl.getName() + + + def properties(self): + return self._properties + + +class SchemaEventClass: + # attr_reader :impl + def __init__(self, package, name, kwargs={}): + self.impl = qmfengine.SchemaEventClass(package, name) + if kwargs.has_key("desc"): self.impl.setDesc(kwargs["desc"]) + self._arguments = [] + + + def add_argument(self, arg): + self._arguments.append(arg) + self.impl.addArgument(arg.impl) + + + + ##============================================================================== + ## CONSOLE + ##============================================================================== + + + +class ConsoleHandler: + def agent_added(self, agent): pass + def agent_deleted(self, agent): pass + def new_package(self, package): pass + def new_class(self, class_key): pass + def object_update(self, obj, hasProps, hasStats): pass + def event_received(self, event): pass + def agent_heartbeat(self, agent, timestamp): pass + def method_response(self, resp): pass + def broker_info(self, broker): pass + + + +class Console: + # attr_reader :impl + def initialize(handler=None, kwargs={}): + self._handler = handler + self.impl = qmfengine.ConsoleEngine() + self._event = qmfengine.ConsoleEvent() + self._broker_list = [] + + + def add_connection(self, conn): + broker = Broker(self, conn) + self._broker_list.append(broker) + return broker + + + def del_connection(self, broker): pass + + + def get_packages(self): pass + + + def get_classes(self, package): pass + + + def get_schema(self, class_key): pass + + + def bind_package(self, package): pass + + + def bind_class(self, kwargs = {}): pass + + + def get_agents(self, broker=None): pass + + + def get_objects(self, query, kwargs = {}): pass + + + def start_sync(self, query): pass + + + def touch_sync(self, sync): pass + + + def end_sync(self, sync): pass + + + def do_console_events(self): + count = 0 + valid = self.impl.getEvent(self._event) + while valid: + count += 1 + print "Console Event:", self._event.kind + if self._event.kind == qmfengine.ConsoleEvent.AGENT_ADDED: + pass + elif self._event.kind == qmfengine.ConsoleEvent.AGENT_DELETED: + pass + elif self._event.kind == qmfengine.ConsoleEvent.NEW_PACKAGE: + pass + elif self._event.kind == qmfengine.ConsoleEvent.NEW_CLASS: + pass + elif self._event.kind == qmfengine.ConsoleEvent.OBJECT_UPDATE: + pass + elif self._event.kind == qmfengine.ConsoleEvent.EVENT_RECEIVED: + pass + elif self._event.kind == qmfengine.ConsoleEvent.AGENT_HEARTBEAT: + pass + elif self._event.kind == qmfengine.ConsoleEvent.METHOD_RESPONSE: + pass + + self.impl.popEvent() + valid = self.impl.getEvent(self._event) + return count + + + +class Broker(ConnectionHandler): + # attr_reader :impl + def __init__(self, console, conn): + self._console = console + self._conn = conn + self._session = None + self._event = qmfengine.BrokerEvent() + self._xmtMessage = qmfengine.Message() + self.impl = qmfengine.BrokerProxy(self._console.impl) + self._console.impl.addConnection(self.impl, self) + self._conn.add_conn_handler(self) + + + def do_broker_events(self): + count = 0 + valid = self.impl.getEvent(self._event) + while valid: + count += 1 + print "Broker Event: ", self._event.kind + if self._event.kind == qmfengine.BrokerEvent.BROKER_INFO: + pass + elif self._event.kind == qmfengine.BrokerEvent.DECLARE_QUEUE: + self._conn.impl.declareQueue(self._session.handle, self._event.name) + elif self._event.kind == qmfengine.BrokerEvent.DELETE_QUEUE: + self._conn.impl.deleteQueue(self._session.handle, self._event.name) + elif self._event.kind == qmfengine.BrokerEvent.BIND: + self._conn.impl.bind(self._session.handle, self._event.exchange, self._event.name, self._event.bindingKey) + elif self._event.kind == qmfengine.BrokerEvent.UNBIND: + self._conn.impl.unbind(self._session.handle, self._event.exchange, self._event.name, self._event.bindingKey) + elif self._event.kind == qmfengine.BrokerEvent.SETUP_COMPLETE: + self.impl.startProtocol() + + self.impl.popEvent() + valid = self.impl.getEvent(self._event) + + return count + + + def do_broker_messages(self): + count = 0 + valid = self.impl.getXmtMessage(self._xmtMessage) + while valid: + count += 1 + self._conn.impl.sendMessage(self._session.handle, self._xmtMessage) + self.impl.popXmt() + valid = self.impl.getXmtMessage(self._xmtMessage) + + return count + + + def do_events(self): + while True: + ccnt = self._console.do_console_events() + bcnt = do_broker_events() + mcnt = do_broker_messages() + if ccnt == 0 and bcnt == 0 and mcnt == 0: + break; + + + def conn_event_connected(self): + print "Console Connection Established..." + self._session = Session(self._conn, "qmfc-%s.%d" % (socket.gethostname(), os.getpid()), self) + self.impl.sessionOpened(self._session.handle) + self.do_events() + + + def conn_event_disconnected(self, error): + print "Console Connection Lost" + pass + + + def sess_event_session_closed(self, context, error): + print "Console Session Lost" + self.impl.sessionClosed() + + + def sess_event_recv(self, context, message): + self.impl.handleRcvMessage(message) + self.do_events() + + + + ##============================================================================== + ## AGENT + ##============================================================================== + + + +class AgentHandler: + def get_query(self, context, query, userId): None + def method_call(self, context, name, object_id, args, userId): None + + + +class Agent(ConnectionHandler): + def __init__(self, handler, label=""): + if label == "": + self._agentLabel = "rb-%s.%d" % (socket.gethostname(), os.getpid()) + else: + self._agentLabel = label + self._conn = None + self._handler = handler + self.impl = qmfengine.AgentEngine(self._agentLabel) + self._event = qmfengine.AgentEvent() + self._xmtMessage = qmfengine.Message() + + + def set_connection(self, conn): + self._conn = conn + self._conn.add_conn_handler(self) + + + def register_class(self, cls): + self.impl.registerClass(cls.impl) + + + def alloc_object_id(self, low = 0, high = 0): + return ObjectId(self.impl.allocObjectId(low, high)) + + + def query_response(self, context, obj): + self.impl.queryResponse(context, obj.impl) + + + def query_complete(self, context): + self.impl.queryComplete(context) + + + def method_response(self, context, status, text, arguments): + self.impl.methodResponse(context, status, text, arguments.map) + + + def do_agent_events(self): + count = 0 + valid = self.impl.getEvent(self._event) + while valid: + count += 1 + if self._event.kind == qmfengine.AgentEvent.GET_QUERY: + self._handler.get_query(self._event.sequence, + Query(self._event.query), + self._event.authUserId) + + elif self._event.kind == qmfengine.AgentEvent.START_SYNC: + pass + elif self._event.kind == qmfengine.AgentEvent.END_SYNC: + pass + elif self._event.kind == qmfengine.AgentEvent.METHOD_CALL: + args = Arguments(self._event.arguments) + self._handler.method_call(self._event.sequence, self._event.name, + ObjectId(self._event.objectId), + args, self._event.authUserId) + + elif self._event.kind == qmfengine.AgentEvent.DECLARE_QUEUE: + self._conn.impl.declareQueue(self._session.handle, self._event.name) + + elif self._event.kind == qmfengine.AgentEvent.DELETE_QUEUE: + self._conn.impl.deleteQueue(self._session.handle, self._event.name) + + elif self._event.kind == qmfengine.AgentEvent.BIND: + self._conn.impl.bind(self._session.handle, self._event.exchange, + self._event.name, self._event.bindingKey) + + elif self._event.kind == qmfengine.AgentEvent.UNBIND: + self._conn.impl.unbind(self._session.handle, self._event.exchange, + self._event.name, self._event.bindingKey) + + elif self._event.kind == qmfengine.AgentEvent.SETUP_COMPLETE: + self.impl.startProtocol() + + self.impl.popEvent() + valid = self.impl.getEvent(self._event) + return count + + + def do_agent_messages(self): + count = 0 + valid = self.impl.getXmtMessage(self._xmtMessage) + while valid: + count += 1 + self._conn.impl.sendMessage(self._session.handle, self._xmtMessage) + self.impl.popXmt() + valid = self.impl.getXmtMessage(self._xmtMessage) + return count + + + def do_events(self): + while True: + ecnt = self.do_agent_events() + mcnt = self.do_agent_messages() + if ecnt == 0 and mcnt == 0: + break + + + def conn_event_connected(self): + print "Agent Connection Established..." + self._session = Session(self._conn, + "qmfa-%s.%d" % (socket.gethostname(), os.getpid()), + self) + self.impl.newSession() + self.do_events() + + + def conn_event_disconnected(self, error): + print "Agent Connection Lost" + pass + + + def sess_event_session_closed(self, context, error): + print "Agent Session Lost" + pass + + + def sess_event_recv(self, context, message): + self.impl.handleRcvMessage(message) + self.do_events() + + diff --git a/qpid/cpp/bindings/qmf/qmfengine.i b/qpid/cpp/bindings/qmf/qmfengine.i index 3c67d92031..d3500c9b8f 100644 --- a/qpid/cpp/bindings/qmf/qmfengine.i +++ b/qpid/cpp/bindings/qmf/qmfengine.i @@ -19,24 +19,24 @@ %{ -#include "Agent.h" -#include <ResilientConnection.h> +#include "qmf/AgentEngine.h" +#include "qmf/ConsoleEngine.h" +#include "qmf/ResilientConnection.h" %} - -%include <Query.h> -%include <Message.h> -%include <Agent.h> -%include <ResilientConnection.h> -%include <Typecode.h> -%include <Schema.h> -%include <Value.h> -%include <ObjectId.h> -%include <Object.h> - -%include <qpid/client/ClientImportExport.h> -%include <qpid/client/ConnectionSettings.h> +%include <qmf/QmfImportExport.h> +%include <qmf/Query.h> +%include <qmf/Message.h> +%include <qmf/AgentEngine.h> +%include <qmf/ConsoleEngine.h> +%include <qmf/ConnectionSettings.h> +%include <qmf/ResilientConnection.h> +%include <qmf/Typecode.h> +%include <qmf/Schema.h> +%include <qmf/Value.h> +%include <qmf/ObjectId.h> +%include <qmf/Object.h> %inline { diff --git a/qpid/cpp/bindings/qmf/ruby/Makefile.am b/qpid/cpp/bindings/qmf/ruby/Makefile.am index 532fdb6875..0537dd1cd8 100644 --- a/qpid/cpp/bindings/qmf/ruby/Makefile.am +++ b/qpid/cpp/bindings/qmf/ruby/Makefile.am @@ -19,7 +19,7 @@ if HAVE_RUBY_DEVEL -INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src/qmf -I$(top_srcdir)/src -I$(top_builddir)/src +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src EXTRA_DIST = ruby.i BUILT_SOURCES = qmfengine.cpp @@ -36,7 +36,7 @@ rubylibarchdir = $(RUBY_LIB_ARCH) rubylibarch_LTLIBRARIES = qmfengine.la qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".$(RUBY_DLEXT)" -qmfengine_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfcommon.la +qmfengine_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfagent.la qmfengine_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH) nodist_qmfengine_la_SOURCES = qmfengine.cpp diff --git a/qpid/cpp/bindings/qmf/ruby/qmf.rb b/qpid/cpp/bindings/qmf/ruby/qmf.rb index 7ee447c675..21fbf6c157 100644 --- a/qpid/cpp/bindings/qmf/ruby/qmf.rb +++ b/qpid/cpp/bindings/qmf/ruby/qmf.rb @@ -20,517 +20,846 @@ require 'qmfengine' require 'thread' require 'socket' +require 'monitor' module Qmf - # Pull all the TYPE_* constants into Qmf namespace. Maybe there's an easier way? - Qmfengine.constants.each do |c| - if c.index('TYPE_') == 0 or c.index('ACCESS_') == 0 or c.index('DIR_') == 0 - const_set(c, Qmfengine.const_get(c)) - end + # Pull all the TYPE_* constants into Qmf namespace. Maybe there's an easier way? + Qmfengine.constants.each do |c| + if c.index('TYPE_') == 0 or c.index('ACCESS_') == 0 or c.index('DIR_') == 0 or c.index('CLASS_') == 0 + const_set(c, Qmfengine.const_get(c)) end + end + + ##============================================================================== + ## CONNECTION + ##============================================================================== - class ConnectionSettings < Qmfengine::ConnectionSettings + class ConnectionSettings + attr_reader :impl + + def initialize(url = nil) + if url + @impl = Qmfengine::ConnectionSettings.new(url) + else + @impl = Qmfengine::ConnectionSettings.new() + end end - class ConnectionEvent - def conn_event_connected(); end - def conn_event_disconnected(error); end - def conn_event_session_closed(context, error); end - def conn_event_recv(context, message); end + def set_attr(key, val) + if val.class == String + v = Qmfengine::Value.new(TYPE_LSTR) + v.setString(val) + elsif val.class == TrueClass or val.class == FalseClass + v = Qmfengine::Value.new(TYPE_BOOL) + v.setBool(val) + elsif val.class == Fixnum + v = Qmfengine::Value.new(TYPE_UINT32) + v.setUint(val) + else + raise ArgumentError, "Value for attribute '#{key}' has unsupported type: #{val.class}" + end + + @impl.setAttr(key, v) end + end - class Query - attr_reader :impl - def initialize(i) - @impl = i - end + class ConnectionHandler + def conn_event_connected(); end + def conn_event_disconnected(error); end + def sess_event_session_closed(context, error); end + def sess_event_recv(context, message); end + end - def package_name - @impl.getPackage - end + class Connection + include MonitorMixin - def class_name - @impl.getClass - end + attr_reader :impl - def object_id - objid = @impl.getObjectId - if objid.class == NilClass - return nil - end - return ObjectId.new(objid) + def initialize(settings) + super() + @impl = Qmfengine::ResilientConnection.new(settings.impl) + @sockEngine, @sock = Socket::socketpair(Socket::PF_UNIX, Socket::SOCK_STREAM, 0) + @impl.setNotifyFd(@sockEngine.fileno) + @new_conn_handlers = [] + @conn_handlers = [] + + @thread = Thread.new do + run end end - class AgentHandler - def get_query(context, query, userId); end - def method_call(context, name, object_id, args, userId); end + def add_conn_handler(handler) + synchronize do + @new_conn_handlers << handler + end + @sockEngine.write("x") end - class Connection - attr_reader :impl + def run() + eventImpl = Qmfengine::ResilientConnectionEvent.new + connected = nil + new_handlers = nil + bt_count = 0 - def initialize(settings, event_handler = nil, delay_min = 1, delay_max = 128, delay_factor = 2) - @impl = Qmfengine::ResilientConnection.new(settings, delay_min, delay_max, delay_factor) - @sockEngine, @sock = Socket::socketpair(Socket::PF_UNIX, Socket::SOCK_STREAM, 0) - @impl.setNotifyFd(@sockEngine.fileno) - @new_conn_handlers = Array.new - @conn_handlers = Array.new - @sess_handlers = Array.new + while :true + @sock.read(1) - @thread = Thread.new do - run + synchronize do + new_handlers = @new_conn_handlers + @new_conn_handlers = [] end - end - - def add_conn_handler(handler) - @new_conn_handlers.push(handler) - @sockEngine.write("x") - end - def add_sess_handler(handler) - @sess_handlers.push(handler) - end - - def run() - event = Qmfengine::ResilientConnectionEvent.new - connected = nil - while :true - @sock.read(1) + new_handlers.each do |nh| + @conn_handlers << nh + nh.conn_event_connected() if connected + end + new_handlers = nil - @new_conn_handlers.each do |nh| - @conn_handlers.push(nh) - nh.conn_event_connected() if connected - end - @new_conn_handlers = Array.new - - valid = @impl.getEvent(event) - while valid - begin - case event.kind - when Qmfengine::ResilientConnectionEvent::CONNECTED - connected = :true - @conn_handlers.each { |h| h.conn_event_connected() } - when Qmfengine::ResilientConnectionEvent::DISCONNECTED - connected = nil - @conn_handlers.each { |h| h.conn_event_disconnected(event.errorText) } - when Qmfengine::ResilientConnectionEvent::SESSION_CLOSED - event.sessionContext.handler.sess_event_session_closed(event.sessionContext, event.errorText) - when Qmfengine::ResilientConnectionEvent::RECV - event.sessionContext.handler.sess_event_recv(event.sessionContext, event.message) - end - rescue Exception => ex - puts "Event Exception: #{ex}" + valid = @impl.getEvent(eventImpl) + while valid + begin + case eventImpl.kind + when Qmfengine::ResilientConnectionEvent::CONNECTED + connected = :true + @conn_handlers.each { |h| h.conn_event_connected() } + when Qmfengine::ResilientConnectionEvent::DISCONNECTED + connected = nil + @conn_handlers.each { |h| h.conn_event_disconnected(eventImpl.errorText) } + when Qmfengine::ResilientConnectionEvent::SESSION_CLOSED + eventImpl.sessionContext.handler.sess_event_session_closed(eventImpl.sessionContext, eventImpl.errorText) + when Qmfengine::ResilientConnectionEvent::RECV + eventImpl.sessionContext.handler.sess_event_recv(eventImpl.sessionContext, eventImpl.message) + end + rescue Exception => ex + puts "Event Exception: #{ex}" + if bt_count < 2 puts ex.backtrace + bt_count += 1 end - @impl.popEvent - valid = @impl.getEvent(event) end + @impl.popEvent + valid = @impl.getEvent(eventImpl) end end end + end - class Session - attr_reader :handle, :handler + class Session + attr_reader :handle, :handler - def initialize(conn, label, handler) - @conn = conn - @label = label - @handler = handler - @handle = Qmfengine::SessionHandle.new - @conn.add_sess_handler(@handler) - result = @conn.impl.createSession(label, self, @handle) - end + def initialize(conn, label, handler) + @conn = conn + @label = label + @handler = handler + @handle = Qmfengine::SessionHandle.new + result = @conn.impl.createSession(label, self, @handle) end - class ObjectId - attr_reader :impl - def initialize(impl=nil) - if impl - @impl = impl - else - @impl = Qmfengine::ObjectId.new - end - end - def object_num_high - return @impl.getObjectNumHi - end - def object_num_low - return @impl.getObjectNumLo - end + def destroy() + @conn.impl.destroySession(@handle) end + end - class Arguments - attr_reader :map - def initialize(map) - @map = map - @by_hash = {} - key_count = @map.keyCount - a = 0 - while a < key_count - @by_hash[@map.key(a)] = by_key(@map.key(a)) - a += 1 - end - end + ##============================================================================== + ## OBJECTS + ##============================================================================== - def [] (key) - return @by_hash[key] - end + class QmfObject + attr_reader :impl, :object_class + def initialize(cls) + @object_class = cls + @impl = Qmfengine::Object.new(@object_class.impl) + end - def []= (key, value) - @by_hash[key] = value - set(key, value) - end + def destroy + @impl.destroy + end - def each - @by_hash.each { |k, v| yield(k, v) } - end + def object_id + return ObjectId.new(@impl.getObjectId) + end - def by_key(key) - val = @map.byKey(key) - case val.getType - when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.asUint - when TYPE_UINT64 then val.asUint64 - when TYPE_SSTR, TYPE_LSTR then val.asString - when TYPE_ABSTIME then val.asInt64 - when TYPE_DELTATIME then val.asUint64 - when TYPE_REF then val.asObjectId - when TYPE_BOOL then val.asBool - when TYPE_FLOAT then val.asFloat - when TYPE_DOUBLE then val.asDouble - when TYPE_UUID then val.asUuid - when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.asInt - when TYPE_INT64 then val.asInt64 - when TYPE_MAP - when TYPE_OBJECT - when TYPE_LIST - when TYPE_ARRAY - end - end + def set_object_id(oid) + @impl.setObjectId(oid.impl) + end - def set(key, value) - val = @map.byKey(key) - case val.getType - when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.setUint(value) - when TYPE_UINT64 then val.setUint64(value) - when TYPE_SSTR, TYPE_LSTR then value ? val.setString(value) : val.setString('') - when TYPE_ABSTIME then val.setInt64(value) - when TYPE_DELTATIME then val.setUint64(value) - when TYPE_REF then val.setObjectId(value.impl) - when TYPE_BOOL then value ? val.setBool(value) : val.setBool(0) - when TYPE_FLOAT then val.setFloat(value) - when TYPE_DOUBLE then val.setDouble(value) - when TYPE_UUID then val.setUuid(value) - when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.setInt(value) - when TYPE_INT64 then val.setInt64(value) - when TYPE_MAP - when TYPE_OBJECT - when TYPE_LIST - when TYPE_ARRAY - end + def get_attr(name) + val = value(name) + case val.getType + when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.asUint + when TYPE_UINT64 then val.asUint64 + when TYPE_SSTR, TYPE_LSTR then val.asString + when TYPE_ABSTIME then val.asInt64 + when TYPE_DELTATIME then val.asUint64 + when TYPE_REF then val.asObjectId + when TYPE_BOOL then val.asBool + when TYPE_FLOAT then val.asFloat + when TYPE_DOUBLE then val.asDouble + when TYPE_UUID then val.asUuid + when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.asInt + when TYPE_INT64 then val.asInt64 + when TYPE_MAP + when TYPE_OBJECT + when TYPE_LIST + when TYPE_ARRAY end end - class Agent - def initialize(handler, label="") - if label == "" - @agentLabel = "rb-%s.%d" % [Socket.gethostname, Process::pid] - else - @agentLabel = label - end - @conn = nil - @handler = handler - @impl = Qmfengine::Agent.new(@agentLabel) - @event = Qmfengine::AgentEvent.new - @xmtMessage = Qmfengine::Message.new + def set_attr(name, v) + val = value(name) + case val.getType + when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.setUint(v) + when TYPE_UINT64 then val.setUint64(v) + when TYPE_SSTR, TYPE_LSTR then v ? val.setString(v) : val.setString('') + when TYPE_ABSTIME then val.setInt64(v) + when TYPE_DELTATIME then val.setUint64(v) + when TYPE_REF then val.setObjectId(v.impl) + when TYPE_BOOL then v ? val.setBool(v) : val.setBool(0) + when TYPE_FLOAT then val.setFloat(v) + when TYPE_DOUBLE then val.setDouble(v) + when TYPE_UUID then val.setUuid(v) + when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.setInt(v) + when TYPE_INT64 then val.setInt64(v) + when TYPE_MAP + when TYPE_OBJECT + when TYPE_LIST + when TYPE_ARRAY end + end - def set_connection(conn) - @conn = conn - @conn.add_conn_handler(self) - end + def [](name) + get_attr(name) + end - def register_class(cls) - @impl.registerClass(cls.impl) - end + def []=(name, value) + set_attr(name, value) + end - def alloc_object_id(low = 0, high = 0) - ObjectId.new(@impl.allocObjectId(low, high)) - end + def inc_attr(name, by=1) + set_attr(name, get_attr(name) + by) + end - def query_response(context, object) - @impl.queryResponse(context, object.impl) - end + def dec_attr(name, by=1) + set_attr(name, get_attr(name) - by) + end - def query_complete(context) - @impl.queryComplete(context) + private + def value(name) + val = @impl.getValue(name.to_s) + if val.nil? + raise ArgumentError, "Attribute '#{name}' not defined for class #{@object_class.impl.getName}" end + return val + end + end - def method_response(context, status, text, arguments) - @impl.methodResponse(context, status, text, arguments.map) - end + class ConsoleObject < QmfObject + attr_reader :current_time, :create_time, :delete_time - def do_agent_events() - count = 0 - valid = @impl.getEvent(@event) - while valid - count += 1 - case @event.kind - when Qmfengine::AgentEvent::GET_QUERY - @handler.get_query(@event.sequence, Query.new(@event.query), @event.authUserId) - when Qmfengine::AgentEvent::START_SYNC - when Qmfengine::AgentEvent::END_SYNC - when Qmfengine::AgentEvent::METHOD_CALL - args = Arguments.new(@event.arguments) - @handler.method_call(@event.sequence, @event.name, ObjectId.new(@event.objectId), - args, @event.authUserId) - when Qmfengine::AgentEvent::DECLARE_QUEUE - @conn.impl.declareQueue(@session.handle, @event.name) - when Qmfengine::AgentEvent::DELETE_QUEUE - @conn.impl.deleteQueue(@session.handle, @event.name) - when Qmfengine::AgentEvent::BIND - @conn.impl.bind(@session.handle, @event.exchange, @event.name, @event.bindingKey) - when Qmfengine::AgentEvent::UNBIND - @conn.impl.unbind(@session.handle, @event.exchange, @event.name, @event.bindingKey) - when Qmfengine::AgentEvent::SETUP_COMPLETE - @impl.startProtocol() - end - @impl.popEvent - valid = @impl.getEvent(@event) - end - return count - end + def initialize(cls) + super(cls) + end - def do_agent_messages() - count = 0 - valid = @impl.getXmtMessage(@xmtMessage) - while valid - count += 1 - @conn.impl.sendMessage(@session.handle, @xmtMessage) - @impl.popXmt - valid = @impl.getXmtMessage(@xmtMessage) - end - return count - end + def update() + end - def do_events() - begin - ecnt = do_agent_events - mcnt = do_agent_messages - end until ecnt == 0 and mcnt == 0 - end + def mergeUpdate(newObject) + end - def conn_event_connected() - puts "Agent Connection Established..." - @session = Session.new(@conn, "qmfa-%s.%d" % [Socket.gethostname, Process::pid], self) - @impl.newSession - do_events - end + def deleted?() + @delete_time > 0 + end - def conn_event_disconnected(error) - puts "Agent Connection Lost" - end + def index() + end - def sess_event_session_closed(context, error) - puts "Agent Session Lost" - end + def method_missing(name, *args) + end + end - def sess_event_recv(context, message) - @impl.handleRcvMessage(message) - do_events + class ObjectId + attr_reader :impl + def initialize(impl=nil) + if impl + @impl = impl + else + @impl = Qmfengine::ObjectId.new end end - class SchemaArgument - attr_reader :impl - def initialize(name, typecode, kwargs={}) - @impl = Qmfengine::SchemaArgument.new(name, typecode) - @impl.setDirection(kwargs[:dir]) if kwargs.include?(:dir) - @impl.setUnit(kwargs[:unit]) if kwargs.include?(:unit) - @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) - end + def object_num_high + return @impl.getObjectNumHi end - class SchemaMethod - attr_reader :impl - def initialize(name, kwargs={}) - @impl = Qmfengine::SchemaMethod.new(name) - @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) - @arguments = [] - end + def object_num_low + return @impl.getObjectNumLo + end - def add_argument(arg) - @arguments << arg - @impl.addArgument(arg.impl) + def ==(other) + return (@impl.getObjectNumHi == other.impl.getObjectNumHi) && + (@impl.getObjectNumLo == other.impl.getObjectNumLo) + end + end + + class Arguments + attr_reader :map + def initialize(map) + @map = map + @by_hash = {} + key_count = @map.keyCount + a = 0 + while a < key_count + @by_hash[@map.key(a)] = by_key(@map.key(a)) + a += 1 end end - class SchemaProperty - attr_reader :impl - def initialize(name, typecode, kwargs={}) - @impl = Qmfengine::SchemaProperty.new(name, typecode) - @impl.setAccess(kwargs[:access]) if kwargs.include?(:access) - @impl.setIndex(kwargs[:index]) if kwargs.include?(:index) - @impl.setOptional(kwargs[:optional]) if kwargs.include?(:optional) - @impl.setUnit(kwargs[:unit]) if kwargs.include?(:unit) - @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) + def [] (key) + return @by_hash[key] + end + + def []= (key, value) + @by_hash[key] = value + set(key, value) + end + + def each + @by_hash.each { |k, v| yield(k, v) } + end + + def by_key(key) + val = @map.byKey(key) + case val.getType + when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.asUint + when TYPE_UINT64 then val.asUint64 + when TYPE_SSTR, TYPE_LSTR then val.asString + when TYPE_ABSTIME then val.asInt64 + when TYPE_DELTATIME then val.asUint64 + when TYPE_REF then val.asObjectId + when TYPE_BOOL then val.asBool + when TYPE_FLOAT then val.asFloat + when TYPE_DOUBLE then val.asDouble + when TYPE_UUID then val.asUuid + when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.asInt + when TYPE_INT64 then val.asInt64 + when TYPE_MAP + when TYPE_OBJECT + when TYPE_LIST + when TYPE_ARRAY end + end - def name - @impl.getName + def set(key, value) + val = @map.byKey(key) + case val.getType + when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.setUint(value) + when TYPE_UINT64 then val.setUint64(value) + when TYPE_SSTR, TYPE_LSTR then value ? val.setString(value) : val.setString('') + when TYPE_ABSTIME then val.setInt64(value) + when TYPE_DELTATIME then val.setUint64(value) + when TYPE_REF then val.setObjectId(value.impl) + when TYPE_BOOL then value ? val.setBool(value) : val.setBool(0) + when TYPE_FLOAT then val.setFloat(value) + when TYPE_DOUBLE then val.setDouble(value) + when TYPE_UUID then val.setUuid(value) + when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.setInt(value) + when TYPE_INT64 then val.setInt64(value) + when TYPE_MAP + when TYPE_OBJECT + when TYPE_LIST + when TYPE_ARRAY end end + end - class SchemaStatistic - attr_reader :impl - def initialize(name, typecode, kwargs={}) - @impl = Qmfengine::SchemaStatistic.new(name, typecode) - @impl.setUnit(kwargs[:unit]) if kwargs.include?(:unit) - @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) + class Query + attr_reader :impl + def initialize(i) + @impl = i + end + + def package_name + @impl.getPackage + end + + def class_name + @impl.getClass + end + + def object_id + objid = @impl.getObjectId + if objid.class == NilClass + return nil end + return ObjectId.new(objid) + end + end + + ##============================================================================== + ## SCHEMA + ##============================================================================== + + class SchemaArgument + attr_reader :impl + def initialize(name, typecode, kwargs={}) + @impl = Qmfengine::SchemaArgument.new(name, typecode) + @impl.setDirection(kwargs[:dir]) if kwargs.include?(:dir) + @impl.setUnit(kwargs[:unit]) if kwargs.include?(:unit) + @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) + end + end + + class SchemaMethod + attr_reader :impl + def initialize(name, kwargs={}) + @impl = Qmfengine::SchemaMethod.new(name) + @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) + @arguments = [] + end + + def add_argument(arg) + @arguments << arg + @impl.addArgument(arg.impl) + end + end + + class SchemaProperty + attr_reader :impl + def initialize(name, typecode, kwargs={}) + @impl = Qmfengine::SchemaProperty.new(name, typecode) + @impl.setAccess(kwargs[:access]) if kwargs.include?(:access) + @impl.setIndex(kwargs[:index]) if kwargs.include?(:index) + @impl.setOptional(kwargs[:optional]) if kwargs.include?(:optional) + @impl.setUnit(kwargs[:unit]) if kwargs.include?(:unit) + @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) + end + + def name + @impl.getName + end + end + + class SchemaStatistic + attr_reader :impl + def initialize(name, typecode, kwargs={}) + @impl = Qmfengine::SchemaStatistic.new(name, typecode) + @impl.setUnit(kwargs[:unit]) if kwargs.include?(:unit) + @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) end + end - class SchemaObjectClass - attr_reader :impl - def initialize(package, name, kwargs={}) + class SchemaClassKey + attr_reader :impl + def initialize(i) + @impl = i + end + + def get_package() + @impl.getPackageName() + end + + def get_class() + @impl.getClassName() + end + end + + class SchemaObjectClass + attr_reader :impl + def initialize(package='', name='', kwargs={}) + @properties = [] + @statistics = [] + @methods = [] + if kwargs.include?(:impl) + @impl = kwargs[:impl] + else @impl = Qmfengine::SchemaObjectClass.new(package, name) - @properties = [] - @statistics = [] - @methods = [] end + end - def add_property(prop) - @properties << prop - @impl.addProperty(prop.impl) - end + def add_property(prop) + @properties << prop + @impl.addProperty(prop.impl) + end - def add_statistic(stat) - @statistics << stat - @impl.addStatistic(stat.impl) - end + def add_statistic(stat) + @statistics << stat + @impl.addStatistic(stat.impl) + end - def add_method(meth) - @methods << meth - @impl.addMethod(meth.impl) - end + def add_method(meth) + @methods << meth + @impl.addMethod(meth.impl) + end - def name - @impl.getName - end + def name + @impl.getClassKey.getClassName + end - def properties - unless @properties - @properties = [] - @impl.getPropertyCount.times do |i| - @properties << @impl.getProperty(i) - end + def properties + unless @properties + @properties = [] + @impl.getPropertyCount.times do |i| + @properties << @impl.getProperty(i) end - return @properties end + return @properties end - - class SchemaEventClass - attr_reader :impl - def initialize(package, name, kwargs={}) + end + + class SchemaEventClass + attr_reader :impl + def initialize(package='', name='', kwargs={}) + @arguments = [] + if kwargs.include?(:impl) + @impl = kwargs[:impl] + else @impl = Qmfengine::SchemaEventClass.new(package, name) @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) - @arguments = [] end + end - def add_argument(arg) - @arguments << arg - @impl.addArgument(arg.impl) - end + def add_argument(arg) + @arguments << arg + @impl.addArgument(arg.impl) end - class QmfObject - attr_reader :impl, :object_class - def initialize(cls) - @object_class = cls - @impl = Qmfengine::Object.new(@object_class.impl) - end + def name + @impl.getClassKey.getClassName + end + end + + ##============================================================================== + ## CONSOLE + ##============================================================================== + + class ConsoleHandler + def agent_added(agent); end + def agent_deleted(agent); end + def new_package(package); end + def new_class(class_key); end + def object_update(object, hasProps, hasStats); end + def event_received(event); end + def agent_heartbeat(agent, timestamp); end + def method_response(resp); end + def broker_info(broker); end + end + + class Console + attr_reader :impl + + def initialize(handler = nil, kwargs={}) + @handler = handler + @impl = Qmfengine::ConsoleEngine.new + @event = Qmfengine::ConsoleEvent.new + @broker_list = [] + end - def destroy - @impl.destroy - end + def add_connection(conn) + broker = Broker.new(self, conn) + @broker_list << broker + return broker + end - def object_id - return ObjectId.new(@impl.getObjectId) - end + def del_connection(broker) + end - def set_object_id(oid) - @impl.setObjectId(oid.impl) + def get_packages() + plist = [] + count = @impl.packageCount + for i in 0...count + plist << @impl.getPackageName(i) end + return plist + end - def get_attr(name) - val = value(name) - case val.getType - when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.asUint - when TYPE_UINT64 then val.asUint64 - when TYPE_SSTR, TYPE_LSTR then val.asString - when TYPE_ABSTIME then val.asInt64 - when TYPE_DELTATIME then val.asUint64 - when TYPE_REF then val.asObjectId - when TYPE_BOOL then val.asBool - when TYPE_FLOAT then val.asFloat - when TYPE_DOUBLE then val.asDouble - when TYPE_UUID then val.asUuid - when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.asInt - when TYPE_INT64 then val.asInt64 - when TYPE_MAP - when TYPE_OBJECT - when TYPE_LIST - when TYPE_ARRAY + def get_classes(package, kind=CLASS_OBJECT) + clist = [] + count = @impl.classCount(package) + for i in 0...count + key = @impl.getClass(package, i) + class_kind = @impl.getClassKind(key) + if class_kind == kind + if kind == CLASS_OBJECT + clist << SchemaObjectClass.new('', '', :impl => @impl.getObjectClass(key)) + elsif kind == CLASS_EVENT + clist << SchemaEventClass.new('', '', :impl => @impl.getEventClass(key)) + end end end - def set_attr(name, v) - val = value(name) - case val.getType - when TYPE_UINT8, TYPE_UINT16, TYPE_UINT32 then val.setUint(v) - when TYPE_UINT64 then val.setUint64(v) - when TYPE_SSTR, TYPE_LSTR then v ? val.setString(v) : val.setString('') - when TYPE_ABSTIME then val.setInt64(v) - when TYPE_DELTATIME then val.setUint64(v) - when TYPE_REF then val.setObjectId(v.impl) - when TYPE_BOOL then v ? val.setBool(v) : val.setBool(0) - when TYPE_FLOAT then val.setFloat(v) - when TYPE_DOUBLE then val.setDouble(v) - when TYPE_UUID then val.setUuid(v) - when TYPE_INT8, TYPE_INT16, TYPE_INT32 then val.setInt(v) - when TYPE_INT64 then val.setInt64(v) - when TYPE_MAP - when TYPE_OBJECT - when TYPE_LIST - when TYPE_ARRAY + return clist + end + + def get_schema(class_key) + end + + def bind_package(package) + end + + def bind_class(kwargs = {}) + end + + def get_agents(broker = nil) + end + + def get_objects(query, kwargs = {}) + end + + def start_sync(query) + end + + def touch_sync(sync) + end + + def end_sync(sync) + end + + def do_console_events() + count = 0 + valid = @impl.getEvent(@event) + while valid + count += 1 + puts "Console Event: #{@event.kind}" + case @event.kind + when Qmfengine::ConsoleEvent::AGENT_ADDED + when Qmfengine::ConsoleEvent::AGENT_DELETED + when Qmfengine::ConsoleEvent::NEW_PACKAGE + when Qmfengine::ConsoleEvent::NEW_CLASS + when Qmfengine::ConsoleEvent::OBJECT_UPDATE + when Qmfengine::ConsoleEvent::EVENT_RECEIVED + when Qmfengine::ConsoleEvent::AGENT_HEARTBEAT + when Qmfengine::ConsoleEvent::METHOD_RESPONSE end + @impl.popEvent + valid = @impl.getEvent(@event) end + return count + end + end + + class Broker < ConnectionHandler + include MonitorMixin + attr_reader :impl + + def initialize(console, conn) + super() + @console = console + @conn = conn + @session = nil + @cv = new_cond + @stable = nil + @event = Qmfengine::BrokerEvent.new + @xmtMessage = Qmfengine::Message.new + @impl = Qmfengine::BrokerProxy.new(@console.impl) + @console.impl.addConnection(@impl, self) + @conn.add_conn_handler(self) + end - def [](name) - get_attr(name) + def waitForStable(timeout = nil) + synchronize do + return if @stable + if timeout + unless @cv.wait(timeout) { @stable } + raise "Timed out waiting for broker connection to become stable" + end + else + while not @stable + @cv.wait + end + end end + end - def []=(name, value) - set_attr(name, value) + def do_broker_events() + count = 0 + valid = @impl.getEvent(@event) + while valid + count += 1 + puts "Broker Event: #{@event.kind}" + case @event.kind + when Qmfengine::BrokerEvent::BROKER_INFO + when Qmfengine::BrokerEvent::DECLARE_QUEUE + @conn.impl.declareQueue(@session.handle, @event.name) + when Qmfengine::BrokerEvent::DELETE_QUEUE + @conn.impl.deleteQueue(@session.handle, @event.name) + when Qmfengine::BrokerEvent::BIND + @conn.impl.bind(@session.handle, @event.exchange, @event.name, @event.bindingKey) + when Qmfengine::BrokerEvent::UNBIND + @conn.impl.unbind(@session.handle, @event.exchange, @event.name, @event.bindingKey) + when Qmfengine::BrokerEvent::SETUP_COMPLETE + @impl.startProtocol + when Qmfengine::BrokerEvent::STABLE + synchronize do + @stable = :true + @cv.signal + end + end + @impl.popEvent + valid = @impl.getEvent(@event) end + return count + end - def inc_attr(name, by=1) - set_attr(name, get_attr(name) + by) + def do_broker_messages() + count = 0 + valid = @impl.getXmtMessage(@xmtMessage) + while valid + count += 1 + @conn.impl.sendMessage(@session.handle, @xmtMessage) + @impl.popXmt + valid = @impl.getXmtMessage(@xmtMessage) end + return count + end + + def do_events() + begin + ccnt = @console.do_console_events + bcnt = do_broker_events + mcnt = do_broker_messages + end until ccnt == 0 and bcnt == 0 and mcnt == 0 + end - def dec_attr(name, by=1) - set_attr(name, get_attr(name) - by) + def conn_event_connected() + puts "Console Connection Established..." + @session = Session.new(@conn, "qmfc-%s.%d" % [Socket.gethostname, Process::pid], self) + @impl.sessionOpened(@session.handle) + do_events + end + + def conn_event_disconnected(error) + puts "Console Connection Lost" + end + + def sess_event_session_closed(context, error) + puts "Console Session Lost" + @impl.sessionClosed() + end + + def sess_event_recv(context, message) + @impl.handleRcvMessage(message) + do_events + end + end + + ##============================================================================== + ## AGENT + ##============================================================================== + + class AgentHandler + def get_query(context, query, userId); end + def method_call(context, name, object_id, args, userId); end + end + + class Agent < ConnectionHandler + def initialize(handler, label="") + if label == "" + @agentLabel = "rb-%s.%d" % [Socket.gethostname, Process::pid] + else + @agentLabel = label + end + @conn = nil + @handler = handler + @impl = Qmfengine::AgentEngine.new(@agentLabel) + @event = Qmfengine::AgentEvent.new + @xmtMessage = Qmfengine::Message.new + end + + def set_connection(conn) + @conn = conn + @conn.add_conn_handler(self) + end + + def register_class(cls) + @impl.registerClass(cls.impl) + end + + def alloc_object_id(low = 0, high = 0) + ObjectId.new(@impl.allocObjectId(low, high)) + end + + def query_response(context, object) + @impl.queryResponse(context, object.impl) + end + + def query_complete(context) + @impl.queryComplete(context) + end + + def method_response(context, status, text, arguments) + @impl.methodResponse(context, status, text, arguments.map) + end + + def do_agent_events() + count = 0 + valid = @impl.getEvent(@event) + while valid + count += 1 + case @event.kind + when Qmfengine::AgentEvent::GET_QUERY + @handler.get_query(@event.sequence, Query.new(@event.query), @event.authUserId) + when Qmfengine::AgentEvent::START_SYNC + when Qmfengine::AgentEvent::END_SYNC + when Qmfengine::AgentEvent::METHOD_CALL + args = Arguments.new(@event.arguments) + @handler.method_call(@event.sequence, @event.name, ObjectId.new(@event.objectId), + args, @event.authUserId) + when Qmfengine::AgentEvent::DECLARE_QUEUE + @conn.impl.declareQueue(@session.handle, @event.name) + when Qmfengine::AgentEvent::DELETE_QUEUE + @conn.impl.deleteQueue(@session.handle, @event.name) + when Qmfengine::AgentEvent::BIND + @conn.impl.bind(@session.handle, @event.exchange, @event.name, @event.bindingKey) + when Qmfengine::AgentEvent::UNBIND + @conn.impl.unbind(@session.handle, @event.exchange, @event.name, @event.bindingKey) + when Qmfengine::AgentEvent::SETUP_COMPLETE + @impl.startProtocol() + end + @impl.popEvent + valid = @impl.getEvent(@event) end + return count + end - private - def value(name) - val = @impl.getValue(name.to_s) - if val.nil? - raise ArgumentError, "Attribute '#{name}' not defined for class #{@object_class.impl.getName}" - end - return val + def do_agent_messages() + count = 0 + valid = @impl.getXmtMessage(@xmtMessage) + while valid + count += 1 + @conn.impl.sendMessage(@session.handle, @xmtMessage) + @impl.popXmt + valid = @impl.getXmtMessage(@xmtMessage) end + return count + end + + def do_events() + begin + ecnt = do_agent_events + mcnt = do_agent_messages + end until ecnt == 0 and mcnt == 0 + end + + def conn_event_connected() + puts "Agent Connection Established..." + @session = Session.new(@conn, "qmfa-%s.%d" % [Socket.gethostname, Process::pid], self) + @impl.newSession + do_events + end + + def conn_event_disconnected(error) + puts "Agent Connection Lost" + end + + def sess_event_session_closed(context, error) + puts "Agent Session Lost" + end + + def sess_event_recv(context, message) + @impl.handleRcvMessage(message) + do_events end + end end diff --git a/qpid/cpp/bindings/qmf/ruby/ruby.i b/qpid/cpp/bindings/qmf/ruby/ruby.i index a8a2a87a97..b7fed403bd 100644 --- a/qpid/cpp/bindings/qmf/ruby/ruby.i +++ b/qpid/cpp/bindings/qmf/ruby/ruby.i @@ -38,17 +38,33 @@ %typemap (out) uint16_t { - $result = UINT2NUM((unsigned short) $1); + $result = UINT2NUM((uint16_t) $1); } %typemap (in) uint32_t { - $1 = NUM2UINT ($input); + if (TYPE($input) == T_BIGNUM) + $1 = NUM2UINT($input); + else + $1 = FIX2UINT($input); } %typemap (out) uint32_t { - $result = UINT2NUM((unsigned int) $1); + $result = UINT2NUM((uint32_t) $1); +} + +%typemap (in) int32_t +{ + if (TYPE($input) == T_BIGNUM) + $1 = NUM2INT($input); + else + $1 = FIX2INT($input); +} + +%typemap (out) int32_t +{ + $result = INT2NUM((int32_t) $1); } %typemap (typecheck, precedence=SWIG_TYPECHECK_INTEGER) uint32_t { @@ -57,12 +73,28 @@ %typemap (in) uint64_t { - $1 = NUM2ULONG ($input); + if (TYPE($input) == T_BIGNUM) + $1 = NUM2ULL($input); + else + $1 = (uint64_t) FIX2LONG($input); } %typemap (out) uint64_t { - $result = ULONG2NUM((unsigned long) $1); + $result = ULL2NUM((uint64_t) $1); +} + +%typemap (in) int64_t +{ + if (TYPE($input) == T_BIGNUM) + $1 = NUM2LL($input); + else + $1 = (int64_t) FIX2LONG($input); +} + +%typemap (out) int64_t +{ + $result = LL2NUM((int64_t) $1); } %typemap (typecheck, precedence=SWIG_TYPECHECK_INTEGER) uint64_t { diff --git a/qpid/cpp/bindings/qmf/tests/Makefile.am b/qpid/cpp/bindings/qmf/tests/Makefile.am index 1ff8a64bed..182771e16b 100644 --- a/qpid/cpp/bindings/qmf/tests/Makefile.am +++ b/qpid/cpp/bindings/qmf/tests/Makefile.am @@ -18,4 +18,10 @@ # TESTS = run_interop_tests -EXTRA_DIST = run_interop_tests + +EXTRA_DIST = \ + agent_ruby.rb \ + python_agent.py \ + python_console.py \ + ruby_console.rb \ + run_interop_tests diff --git a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb index d395810cb6..75de2b5fa1 100755 --- a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb +++ b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb @@ -29,13 +29,34 @@ class Model @parent_class = Qmf::SchemaObjectClass.new("org.apache.qpid.qmf", "parent") @parent_class.add_property(Qmf::SchemaProperty.new("name", Qmf::TYPE_SSTR, :index => true)) @parent_class.add_property(Qmf::SchemaProperty.new("state", Qmf::TYPE_SSTR)) + + @parent_class.add_property(Qmf::SchemaProperty.new("uint64val", Qmf::TYPE_UINT64)) @parent_class.add_property(Qmf::SchemaProperty.new("uint32val", Qmf::TYPE_UINT32)) + @parent_class.add_property(Qmf::SchemaProperty.new("uint16val", Qmf::TYPE_UINT16)) + @parent_class.add_property(Qmf::SchemaProperty.new("uint8val", Qmf::TYPE_UINT8)) + + @parent_class.add_property(Qmf::SchemaProperty.new("int64val", Qmf::TYPE_INT64)) + @parent_class.add_property(Qmf::SchemaProperty.new("int32val", Qmf::TYPE_INT32)) + @parent_class.add_property(Qmf::SchemaProperty.new("int16val", Qmf::TYPE_INT16)) + @parent_class.add_property(Qmf::SchemaProperty.new("int8val", Qmf::TYPE_INT8)) + @parent_class.add_statistic(Qmf::SchemaStatistic.new("queryCount", Qmf::TYPE_UINT32, :unit => "query", :desc => "Query count")) + method = Qmf::SchemaMethod.new("echo", :desc => "Check responsiveness of the agent object") + method.add_argument(Qmf::SchemaArgument.new("sequence", Qmf::TYPE_UINT32, :dir => Qmf::DIR_IN_OUT)) + @parent_class.add_method(method) + + method = Qmf::SchemaMethod.new("set_numerics", :desc => "Set the numeric values in the object") + method.add_argument(Qmf::SchemaArgument.new("test", Qmf::TYPE_SSTR, :dir => Qmf::DIR_IN)) + @parent_class.add_method(method) + method = Qmf::SchemaMethod.new("create_child", :desc => "Create a new child object") method.add_argument(Qmf::SchemaArgument.new("child_name", Qmf::TYPE_LSTR, :dir => Qmf::DIR_IN)) method.add_argument(Qmf::SchemaArgument.new("child_ref", Qmf::TYPE_REF, :dir => Qmf::DIR_OUT)) + @parent_class.add_method(method) + method = Qmf::SchemaMethod.new("probe_userid", :desc => "Return the user-id for this method call") + method.add_argument(Qmf::SchemaArgument.new("userid", Qmf::TYPE_SSTR, :dir => Qmf::DIR_OUT)) @parent_class.add_method(method) @child_class = Qmf::SchemaObjectClass.new("org.apache.qpid.qmf", "child") @@ -55,24 +76,83 @@ class App < Qmf::AgentHandler #@parent.inc_attr("queryCount") if query.class_name == 'parent' @agent.query_response(context, @parent) + elsif query.object_id == @parent_oid + @agent.query_response(context, @parent) end @agent.query_complete(context) end def method_call(context, name, object_id, args, userId) # puts "Method: user=#{userId} context=#{context} method=#{name} object_num=#{object_id.object_num_low if object_id} args=#{args}" - oid = @agent.alloc_object_id(2) - args['child_ref'] = oid - @child = Qmf::QmfObject.new(@model.child_class) - @child.set_attr("name", args.by_key("child_name")) - @child.set_object_id(oid) - @agent.method_response(context, 0, "OK", args) + + if name == "echo" + @agent.method_response(context, 0, "OK", args) + + elsif name == "set_numerics" + retCode = 0 + retText = "OK" + + if args['test'] == "big" + @parent.set_attr("uint64val", 0x9494949449494949) + @parent.set_attr("uint32val", 0xa5a55a5a) + @parent.set_attr("uint16val", 0xb66b) + @parent.set_attr("uint8val", 0xc7) + + @parent.set_attr("int64val", 1000000000000000000) + @parent.set_attr("int32val", 1000000000) + @parent.set_attr("int16val", 10000) + @parent.set_attr("int8val", 100) + + elsif args['test'] == "small" + @parent.set_attr("uint64val", 4) + @parent.set_attr("uint32val", 5) + @parent.set_attr("uint16val", 6) + @parent.set_attr("uint8val", 7) + + @parent.set_attr("int64val", 8) + @parent.set_attr("int32val", 9) + @parent.set_attr("int16val", 10) + @parent.set_attr("int8val", 11) + + elsif args['test'] == "negative" + @parent.set_attr("uint64val", 0) + @parent.set_attr("uint32val", 0) + @parent.set_attr("uint16val", 0) + @parent.set_attr("uint8val", 0) + + @parent.set_attr("int64val", -10000000000) + @parent.set_attr("int32val", -100000) + @parent.set_attr("int16val", -1000) + @parent.set_attr("int8val", -100) + + else + retCode = 1 + retText = "Invalid argument value for test" + end + + @agent.method_response(context, retCode, retText, args) + + elsif name == "create_child" + oid = @agent.alloc_object_id(2) + args['child_ref'] = oid + @child = Qmf::QmfObject.new(@model.child_class) + @child.set_attr("name", args.by_key("child_name")) + @child.set_object_id(oid) + @agent.method_response(context, 0, "OK", args) + + elsif name == "probe_userid" + args['userid'] = userId + @agent.method_response(context, 0, "OK", args) + + else + @agent.method_response(context, 1, "Unimplemented Method: #{name}", args) + end end def main @settings = Qmf::ConnectionSettings.new - @settings.host = ARGV[0] if ARGV.size > 0 - @settings.port = ARGV[1].to_i if ARGV.size > 1 + @settings.set_attr("host", ARGV[0]) if ARGV.size > 0 + @settings.set_attr("port", ARGV[1].to_i) if ARGV.size > 1 @connection = Qmf::Connection.new(@settings) @agent = Qmf::Agent.new(self) @@ -84,10 +164,19 @@ class App < Qmf::AgentHandler @parent = Qmf::QmfObject.new(@model.parent_class) @parent.set_attr("name", "Parent One") @parent.set_attr("state", "OPERATIONAL") - @parent.set_attr("uint32val", 0xa5a5a5a5) - oid = @agent.alloc_object_id(1) - @parent.set_object_id(oid) + @parent.set_attr("uint64val", 0) + @parent.set_attr("uint32val", 0) + @parent.set_attr("uint16val", 0) + @parent.set_attr("uint8val", 0) + + @parent.set_attr("int64val", 0) + @parent.set_attr("int32val", 0) + @parent.set_attr("int16val", 0) + @parent.set_attr("int8val", 0) + + @parent_oid = @agent.alloc_object_id(1) + @parent.set_object_id(@parent_oid) sleep end diff --git a/qpid/cpp/bindings/qmf/tests/python_agent.py b/qpid/cpp/bindings/qmf/tests/python_agent.py new file mode 100644 index 0000000000..f6cb51cbf5 --- /dev/null +++ b/qpid/cpp/bindings/qmf/tests/python_agent.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + + +import qmf +import sys +import time + + +class Model: + # attr_reader :parent_class, :child_class + def __init__(self): + self.parent_class = qmf.SchemaObjectClass("org.apache.qpid.qmf", "parent") + self.parent_class.add_property(qmf.SchemaProperty("name", qmf.TYPE_SSTR, {"index":True})) + self.parent_class.add_property(qmf.SchemaProperty("state", qmf.TYPE_SSTR)) + + self.parent_class.add_property(qmf.SchemaProperty("uint64val", qmf.TYPE_UINT64)) + self.parent_class.add_property(qmf.SchemaProperty("uint32val", qmf.TYPE_UINT32)) + self.parent_class.add_property(qmf.SchemaProperty("uint16val", qmf.TYPE_UINT16)) + self.parent_class.add_property(qmf.SchemaProperty("uint8val", qmf.TYPE_UINT8)) + + self.parent_class.add_property(qmf.SchemaProperty("int64val", qmf.TYPE_INT64)) + self.parent_class.add_property(qmf.SchemaProperty("int32val", qmf.TYPE_INT32)) + self.parent_class.add_property(qmf.SchemaProperty("int16val", qmf.TYPE_INT16)) + self.parent_class.add_property(qmf.SchemaProperty("int8val", qmf.TYPE_INT8)) + + self.parent_class.add_statistic(qmf.SchemaStatistic("queryCount", qmf.TYPE_UINT32, {"unit":"query", "desc":"Query count"})) + + _method = qmf.SchemaMethod("echo", {"desc":"Check responsiveness of the agent object"}) + _method.add_argument(qmf.SchemaArgument("sequence", qmf.TYPE_UINT32, {"dir":qmf.DIR_IN_OUT})) + self.parent_class.add_method(_method) + + _method = qmf.SchemaMethod("set_numerics", {"desc":"Set the numeric values in the object"}) + _method.add_argument(qmf.SchemaArgument("test", qmf.TYPE_SSTR, {"dir":qmf.DIR_IN})) + self.parent_class.add_method(_method) + + _method = qmf.SchemaMethod("create_child", {"desc":"Create a new child object"}) + _method.add_argument(qmf.SchemaArgument("child_name", qmf.TYPE_LSTR, {"dir":qmf.DIR_IN})) + _method.add_argument(qmf.SchemaArgument("child_ref", qmf.TYPE_REF, {"dir":qmf.DIR_OUT})) + self.parent_class.add_method(_method) + + _method = qmf.SchemaMethod("probe_userid", {"desc":"Return the user-id for this method call"}) + _method.add_argument(qmf.SchemaArgument("userid", qmf.TYPE_SSTR, {"dir":qmf.DIR_OUT})) + self.parent_class.add_method(_method) + + self.child_class = qmf.SchemaObjectClass("org.apache.qpid.qmf", "child") + self.child_class.add_property(qmf.SchemaProperty("name", qmf.TYPE_SSTR, {"index":True})) + + + def register(self, agent): + agent.register_class(self.parent_class) + agent.register_class(self.child_class) + + + +class App(qmf.AgentHandler): + def get_query(self, context, query, userId): + # puts "Query: user=#{userId} context=#{context} class=#{query.class_name} object_num=#{query.object_id.object_num_low if query.object_id}" + self._parent.inc_attr("queryCount") + if query.class_name() == 'parent': + self._agent.query_response(context, self._parent) + elif query.object_id() == self._parent_oid: + self._agent.query_response(context, self._parent) + self._agent.query_complete(context) + + + def method_call(self, context, name, object_id, args, userId): + # puts "Method: user=#{userId} context=#{context} method=#{name} object_num=#{object_id.object_num_low if object_id} args=#{args}" + # oid = self._agent.alloc_object_id(2) + # args['child_ref'] = oid + # self._child = qmf.QmfObject(self._model.child_class) + # self._child.set_attr("name", args.by_key("child_name")) + # self._child.set_object_id(oid) + # self._agent.method_response(context, 0, "OK", args) + if name == "echo": + self._agent.method_response(context, 0, "OK", args) + + elif name == "set_numerics": + _retCode = 0 + _retText = "OK" + + if args['test'] == "big": + self._parent.set_attr("uint64val", 0x9494949449494949) + self._parent.set_attr("uint32val", 0xa5a55a5a) + self._parent.set_attr("uint16val", 0xb66b) + self._parent.set_attr("uint8val", 0xc7) + + self._parent.set_attr("int64val", 1000000000000000000) + self._parent.set_attr("int32val", 1000000000) + self._parent.set_attr("int16val", 10000) + self._parent.set_attr("int8val", 100) + + elif args['test'] == "small": + self._parent.set_attr("uint64val", 4) + self._parent.set_attr("uint32val", 5) + self._parent.set_attr("uint16val", 6) + self._parent.set_attr("uint8val", 7) + + self._parent.set_attr("int64val", 8) + self._parent.set_attr("int32val", 9) + self._parent.set_attr("int16val", 10) + self._parent.set_attr("int8val", 11) + + elif args['test'] == "negative": + self._parent.set_attr("uint64val", 0) + self._parent.set_attr("uint32val", 0) + self._parent.set_attr("uint16val", 0) + self._parent.set_attr("uint8val", 0) + + self._parent.set_attr("int64val", -10000000000) + self._parent.set_attr("int32val", -100000) + self._parent.set_attr("int16val", -1000) + self._parent.set_attr("int8val", -100) + + else: + _retCode = 1 + _retText = "Invalid argument value for test" + + self._agent.method_response(context, _retCode, _retText, args) + + elif name == "create_child": + _oid = self._agent.alloc_object_id(2) + args['child_ref'] = _oid + self._child = qmf.QmfObject(self._model.child_class) + self._child.set_attr("name", args["child_name"]) + self._child.set_object_id(_oid) + self._agent.method_response(context, 0, "OK", args) + + elif name == "probe_userid": + args['userid'] = userId + self._agent.method_response(context, 0, "OK", args) + + else: + self._agent.method_response(context, 1, "Unimplemented Method: %s" % name, args) + + + def main(self): + self._settings = qmf.ConnectionSettings() + if len(sys.argv) > 1: + self._settings.set_attr("host", sys.argv[1]) + if len(sys.argv) > 2: + self._settings.set_attr("port", int(sys.argv[2])) + self._connection = qmf.Connection(self._settings) + self._agent = qmf.Agent(self) + + self._model = Model() + self._model.register(self._agent) + + self._agent.set_connection(self._connection) + + self._parent = qmf.QmfObject(self._model.parent_class) + self._parent.set_attr("name", "Parent One") + self._parent.set_attr("state", "OPERATIONAL") + + self._parent.set_attr("uint64val", 0) + self._parent.set_attr("uint32val", 0) + self._parent.set_attr("uint16val", 0) + self._parent.set_attr("uint8val", 0) + + self._parent.set_attr("int64val", 0) + self._parent.set_attr("int32val", 0) + self._parent.set_attr("int16val", 0) + self._parent.set_attr("int8val", 0) + + self._parent_oid = self._agent.alloc_object_id(1) + self._parent.set_object_id(self._parent_oid) + + while True: # there may be a better way, but + time.sleep(1000) # I'm a python noob... + + + +app = App() +app.main() + diff --git a/qpid/cpp/bindings/qmf/tests/python_console.py b/qpid/cpp/bindings/qmf/tests/python_console.py index 7a8a2cb9fe..bcd3063fe3 100755 --- a/qpid/cpp/bindings/qmf/tests/python_console.py +++ b/qpid/cpp/bindings/qmf/tests/python_console.py @@ -36,16 +36,109 @@ class QmfInteropTests(TestBase010): agents = qmf.getObjects(_class="agent") sleep(1) count += 1 - if count > 5: + if count > 10: self.fail("Timed out waiting for remote agent") - def test_B_basic_types(self): + def test_B_basic_method_invocation(self): self.startQmf(); qmf = self.qmf parents = qmf.getObjects(_class="parent") self.assertEqual(len(parents), 1) - self.assertEqual(parents[0].uint32val, 0xA5A5A5A5) + parent = parents[0] + for seq in range(10): + result = parent.echo(seq) + self.assertEqual(result.status, 0) + self.assertEqual(result.text, "OK") + self.assertEqual(result.sequence, seq) + + result = parent.set_numerics("bogus") + self.assertEqual(result.status, 1) + self.assertEqual(result.text, "Invalid argument value for test") + + def test_C_basic_types_numeric_big(self): + self.startQmf(); + qmf = self.qmf + + parents = qmf.getObjects(_class="parent") + self.assertEqual(len(parents), 1) + parent = parents[0] + + result = parent.set_numerics("big") + self.assertEqual(result.status, 0) + self.assertEqual(result.text, "OK") + + parent.update() + + self.assertEqual(parent.uint64val, 0x9494949449494949) + self.assertEqual(parent.uint32val, 0xA5A55A5A) + self.assertEqual(parent.uint16val, 0xB66B) + self.assertEqual(parent.uint8val, 0xC7) + + self.assertEqual(parent.int64val, 1000000000000000000) + self.assertEqual(parent.int32val, 1000000000) + self.assertEqual(parent.int16val, 10000) + self.assertEqual(parent.int8val, 100) + + def test_C_basic_types_numeric_small(self): + self.startQmf(); + qmf = self.qmf + + parents = qmf.getObjects(_class="parent") + self.assertEqual(len(parents), 1) + parent = parents[0] + + result = parent.set_numerics("small") + self.assertEqual(result.status, 0) + self.assertEqual(result.text, "OK") + + parent.update() + + self.assertEqual(parent.uint64val, 4) + self.assertEqual(parent.uint32val, 5) + self.assertEqual(parent.uint16val, 6) + self.assertEqual(parent.uint8val, 7) + + self.assertEqual(parent.int64val, 8) + self.assertEqual(parent.int32val, 9) + self.assertEqual(parent.int16val, 10) + self.assertEqual(parent.int8val, 11) + + def test_C_basic_types_numeric_negative(self): + self.startQmf(); + qmf = self.qmf + + parents = qmf.getObjects(_class="parent") + self.assertEqual(len(parents), 1) + parent = parents[0] + + result = parent.set_numerics("negative") + self.assertEqual(result.status, 0) + self.assertEqual(result.text, "OK") + + parent.update() + + self.assertEqual(parent.uint64val, 0) + self.assertEqual(parent.uint32val, 0) + self.assertEqual(parent.uint16val, 0) + self.assertEqual(parent.uint8val, 0) + + self.assertEqual(parent.int64val, -10000000000) + self.assertEqual(parent.int32val, -100000) + self.assertEqual(parent.int16val, -1000) + self.assertEqual(parent.int8val, -100) + + def test_D_userid_for_method(self): + self.startQmf(); + qmf = self.qmf + + parents = qmf.getObjects(_class="parent") + self.assertEqual(len(parents), 1) + parent = parents[0] + + result = parent.probe_userid() + self.assertEqual(result.status, 0) + self.assertEqual(result.userid, "guest") def getProperty(self, msg, name): for h in msg.headers: diff --git a/qpid/cpp/bindings/qmf/tests/ruby_console.rb b/qpid/cpp/bindings/qmf/tests/ruby_console.rb new file mode 100755 index 0000000000..fb48c29566 --- /dev/null +++ b/qpid/cpp/bindings/qmf/tests/ruby_console.rb @@ -0,0 +1,61 @@ +#!/usr/bin/ruby + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +require 'qmf' +require 'socket' + +class App < Qmf::ConsoleHandler + + def main + @settings = Qmf::ConnectionSettings.new + @settings.set_attr("host", ARGV[0]) if ARGV.size > 0 + @settings.set_attr("port", ARGV[1].to_i) if ARGV.size > 1 + @connection = Qmf::Connection.new(@settings) + @qmf = Qmf::Console.new + + @broker = @qmf.add_connection(@connection) + @broker.waitForStable + + packages = @qmf.get_packages + puts "----- Packages -----" + packages.each do |p| + puts p + puts " ----- Object Classes -----" + classes = @qmf.get_classes(p) + classes.each do |c| + puts " #{c.name}" + end + puts " ----- Event Classes -----" + classes = @qmf.get_classes(p, Qmf::CLASS_EVENT) + classes.each do |c| + puts " #{c.name}" + end + end + puts "-----" + + sleep + end +end + +app = App.new +app.main + + diff --git a/qpid/cpp/bindings/qmf/tests/run_interop_tests b/qpid/cpp/bindings/qmf/tests/run_interop_tests index e6fc872dbb..01d7221ac6 100755 --- a/qpid/cpp/bindings/qmf/tests/run_interop_tests +++ b/qpid/cpp/bindings/qmf/tests/run_interop_tests @@ -28,6 +28,9 @@ BROKER_DIR=${BUILD_DIR}/src API_DIR=${BUILD_DIR}/bindings/qmf SPEC_DIR=${QPID_DIR}/specs +RUBY_LIB_DIR=${API_DIR}/ruby/.libs +PYTHON_LIB_DIR=${API_DIR}/python/.libs + trap stop_broker INT TERM QUIT start_broker() { @@ -41,7 +44,7 @@ stop_broker() { } start_ruby_agent() { - ruby -I${MY_DIR}/../ruby -I${API_DIR}/ruby/.libs ${MY_DIR}/agent_ruby.rb localhost $BROKER_PORT & + ruby -I${MY_DIR}/../ruby -I${RUBY_LIB_DIR} ${MY_DIR}/agent_ruby.rb localhost $BROKER_PORT & AGENT_PID=$! } @@ -49,19 +52,62 @@ stop_ruby_agent() { kill $AGENT_PID } +start_python_agent() { + PYTHONPATH="${MY_DIR}/../python:${API_DIR}/python:${PYTHON_LIB_DIR}" python ${MY_DIR}/python_agent.py localhost $BROKER_PORT & + PY_AGENT_PID=$! +} + +stop_python_agent() { + kill $PY_AGENT_PID +} + +TESTS_FAILED=0 + if test -d ${PYTHON_DIR} ; then start_broker echo "Running qmf interop tests using broker on port $BROKER_PORT" PYTHONPATH=${PYTHON_DIR}:${MY_DIR} export PYTHONPATH - echo " Ruby Agent vs. Pure-Python Console" - start_ruby_agent - echo " Ruby agent started at pid $AGENT_PID" - ${PYTHON_DIR}/qpid-python-test -m python_console -b localhost:$BROKER_PORT $@ - RETCODE=$? - stop_ruby_agent + + if test -d ${PYTHON_LIB_DIR} ; then + echo " Python Agent (external storage) vs. Pure-Python Console" + start_python_agent + echo " Python agent started at pid $PY_AGENT_PID" + ${PYTHON_DIR}/qpid-python-test -m python_console -b localhost:$BROKER_PORT $@ + RETCODE=$? + stop_python_agent + if test x$RETCODE != x0; then + echo "FAIL qmf interop tests (Python Agent)"; + TESTS_FAILED=1 + fi + fi + + if test -d ${RUBY_LIB_DIR} ; then + echo " Ruby Agent (external storage) vs. Pure-Python Console" + start_ruby_agent + echo " Ruby agent started at pid $AGENT_PID" + ${PYTHON_DIR}/qpid-python-test -m python_console -b localhost:$BROKER_PORT $@ + RETCODE=$? + stop_ruby_agent + if test x$RETCODE != x0; then + echo "FAIL qmf interop tests (Ruby Agent)"; + TESTS_FAILED=1 + fi + fi + + # Also against the Pure-Python console: + # Ruby agent (internal storage) + # Python agent (external and internal) + # C++ agent (external and internal) + # + # Other consoles against the same set of agents: + # Wrapped Python console + # Ruby console + # C++ console + stop_broker - if test x$RETCODE != x0; then - echo "FAIL qmf interop tests"; exit 1; + if test x$TESTS_FAILED != x0; then + echo "TEST FAILED!" + exit 1 fi fi |
