diff options
Diffstat (limited to 'cpp/bindings/qmf2/ruby/qmf2.rb')
| -rw-r--r-- | cpp/bindings/qmf2/ruby/qmf2.rb | 855 |
1 files changed, 0 insertions, 855 deletions
diff --git a/cpp/bindings/qmf2/ruby/qmf2.rb b/cpp/bindings/qmf2/ruby/qmf2.rb deleted file mode 100644 index c14ecba4e1..0000000000 --- a/cpp/bindings/qmf2/ruby/qmf2.rb +++ /dev/null @@ -1,855 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT 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 'cqmf2' -require 'cqpid' -require 'thread' -require 'socket' -require 'monitor' - -module Qmf2 - - Cqmf2.constants.each do |c| - if c.index('AGENT_') == 0 or c.index('CONSOLE_') == 0 or - c.index('SCHEMA_') == 0 or c.index('SEV_') == 0 or c.index('QUERY') == 0 - const_set(c, Cqmf2.const_get(c)) - end - end - - SCHEMA_TYPE_DATA = Cqmf2::SCHEMA_TYPE_DATA() - SCHEMA_TYPE_EVENT = Cqmf2::SCHEMA_TYPE_EVENT() - - SCHEMA_DATA_VOID = Cqmf2::SCHEMA_DATA_VOID() - SCHEMA_DATA_BOOL = Cqmf2::SCHEMA_DATA_BOOL() - SCHEMA_DATA_INT = Cqmf2::SCHEMA_DATA_INT() - SCHEMA_DATA_FLOAT = Cqmf2::SCHEMA_DATA_FLOAT() - SCHEMA_DATA_STRING = Cqmf2::SCHEMA_DATA_STRING() - SCHEMA_DATA_MAP = Cqmf2::SCHEMA_DATA_MAP() - SCHEMA_DATA_LIST = Cqmf2::SCHEMA_DATA_LIST() - SCHEMA_DATA_UUID = Cqmf2::SCHEMA_DATA_UUID() - - ACCESS_READ_CREATE = Cqmf2::ACCESS_READ_CREATE() - ACCESS_READ_WRITE = Cqmf2::ACCESS_READ_WRITE() - ACCESS_READ_ONLY = Cqmf2::ACCESS_READ_ONLY() - - DIR_IN = Cqmf2::DIR_IN() - DIR_OUT = Cqmf2::DIR_OUT() - DIR_IN_OUT = Cqmf2::DIR_IN_OUT() - - SEV_EMERG = Cqmf2::SEV_EMERG() - SEV_ALERT = Cqmf2::SEV_ALERT() - SEV_CRIT = Cqmf2::SEV_CRIT() - SEV_ERROR = Cqmf2::SEV_ERROR() - SEV_WARN = Cqmf2::SEV_WARN() - SEV_NOTICE = Cqmf2::SEV_NOTICE() - SEV_INFORM = Cqmf2::SEV_INFORM() - SEV_DEBUG = Cqmf2::SEV_DEBUG() - - ##============================================================================== - ## EXCEPTIONS - ##============================================================================== - - class QmfAgentException < RuntimeError - attr :data - - def initialize(data) - @data = data - end - - def to_s - "QmfAgentException: #{@data}" - end - end - - ##============================================================================== - ## AGENT HANDLER - ##============================================================================== - - class AgentHandler - - def initialize(session) - @_session = session - @_running = false - @_thread = nil - end - - ## - ## Call the "start" method to run the handler on a new thread. - ## - def start - @_thread = Thread.new do - run - end - end - - ## - ## Request that the running thread complete and exit. - ## - def cancel - @_running = false - @_thread.join if @_thread - @_thread = nil - end - - ## - ## Call the "run" method only if you want the handler to run on your own thread. - ## - def run - @_running = true - event = Cqmf2::AgentEvent.new - while @_running do - valid = @_session.impl.nextEvent(event, Cqpid::Duration.SECOND) - if valid and @_running - case event.getType - when Cqmf2::AGENT_AUTH_QUERY - yes = authorize_query(Query.new(event.getQuery()), event.getUserId()) - if yes == true - @_session.impl.authAccept(event) - else - @_session.impl.authReject(event) - end - - when Cqmf2::AGENT_QUERY - context = QueryContext.new(@_session, event) - get_query(context, Query.new(event.getQuery()), event.getUserId()) - - when Cqmf2::AGENT_METHOD - context = MethodContext.new(@_session, event) - begin - method_call(context, event.getMethodName(), event.getDataAddr(), event.getArguments(), event.getUserId()) - rescue Exception => ex - @_session.impl.raiseException(event, "#{ex}") - end - - end - end - end - end - - - ## - ## The following methods are intended to be overridden in a sub-class. They are - ## handlers for events that occur on QMF consoles. - ## - - # - # This method will only be invoked if the "allow-queries" option is enabled on the - # agent session. When invoked, it provides the query and the authenticated user-id - # of the querying client. - # - # This method must return true if the query is permitted, false otherwise. - # - def authorize_query(query, user_id); end - - # - # This method will only be invoked if the "external" option is "True" on the agent - # session. When invoked, the method should begin the process of responding to a data - # query. The authenticated user-id of the requestor is provided for informational - # purposes. The 'context' variable is used to provide the results back to the requestor. - # - # For each matching Data object, call context.response(data). When the query is complete, - # call context.complete(). After completing the query, you should not use 'context' any - # longer. - # - # Note: It is not necessary to process the query synchronously. If desired, this method - # may store the context for asynchronous processing or pass it to another thread for - # processing. There is no restriction on the number of contexts that may be in-flight - # concurrently. - # - def get_query(context, query, user_id); end - - # - # This method is invoked when a console calls a QMF method on the agent. Supplied are - # a context for the response, the method name, the data address of the data object being - # called, the input arguments (a dictionary), and the caller's authenticated user-id. - # - # A method call can end one of two ways: Successful completion, in which the output - # arguments (if any) are supplied; and Exceptional completion if there is an error. - # - # Successful Completion: - # For each output argument, assign the value directly to context (context.arg1 = "value") - # Once arguments are assigned, call context._success(). - # - # Exceptional Completion: - # Method 1: Call context._exception(data) where 'data' is a string or a Data object. - # Method 2: Raise an exception (raise "Error Text") synchronously in the method body. - # - # Note: Like get_query, method_call may process methods synchronously or asynchronously. - # This method may store the context for later asynchronous processing. There is no - # restriction on the number of contexts that may be in-flight concurrently. - # - # However, "Method 2" for Exceptional Completion can only be done synchronously. - # - def method_call(context, method_name, data_addr, args, user_id); end - end - - class QueryContext - def initialize(agent, context) - @agent = agent - @context = context - end - - def response(data) - @agent.impl.response(@context, data.impl) - end - - def complete - @agent.impl.complete(@context) - end - end - - class MethodContext - def initialize(agent, context) - @agent = agent - @context = context - end - - def _success - @agent.impl.methodSuccess(@context) - end - - def _exception(ex) - if ex.class == Data - @agent.impl.raiseException(@context, ex.impl) - else - @agent.impl.raiseException(@context, ex) - end - end - - def method_missing(name_in, *args) - name = name_in.to_s - if name[name.length - 1] == 61 - name = name[0..name.length - 2] - @context.impl.addReturnArgument(name, args[0]) - else - super.method_missing(name_in, args) - end - end - end - - ##============================================================================== - ## CONSOLE HANDLER - ##============================================================================== - - class ConsoleHandler - - def initialize(session) - @_session = session - @_running = false - @_thread = nil - end - - ## - ## Call the "start" method to run the handler on a new thread. - ## - def start - @_thread = Thread.new do - run - end - end - - ## - ## Request that the running thread complete and exit. - ## - def cancel - @_running = false - @_thread.join if @_thread - @_thread = nil - end - - ## - ## Call the "run" method only if you want the handler to run on your own thread. - ## - def run - @_running = true - event = Cqmf2::ConsoleEvent.new - while @_running do - valid = @_session.impl.nextEvent(event, Cqpid::Duration.SECOND) - if valid and @_running - case event.getType - when Cqmf2::CONSOLE_AGENT_ADD - agent_added(Agent.new(event.getAgent)) - - when Cqmf2::CONSOLE_AGENT_DEL - reason = :filter - reason = :aged if event.getAgentDelReason == Cqmf2::AGENT_DEL_AGED - agent_deleted(Agent.new(event.getAgent), reason) - - when Cqmf2::CONSOLE_AGENT_RESTART - agent_restarted(Agent.new(event.getAgent)) - - when Cqmf2::CONSOLE_AGENT_SCHEMA_UPDATE - agent_schema_updated(Agent.new(event.getAgent)) - - when Cqmf2::CONSOLE_EVENT - event_raised(Agent.new(event.getAgent), Data.new(event.getData(0)), event.getTimestamp, event.getSeverity) - - end - end - end - end - - - ## - ## The following methods are intended to be overridden in a sub-class. They are - ## handlers for events that occur on QMF consoles. - ## - - # - # A new agent, whose attributes match the console's agent filter, has been discovered. - # - def agent_added(agent); end - - # - # A known agent has been removed from the agent list. There are two possible reasons - # for agent deletion: - # - # 1) :aged - The agent hasn't been heard from for the maximum age interval and is - # presumed dead. - # 2) :filter - The agent no longer matches the console's agent-filter and has been - # effectively removed from the agent list. Such occurrences are likely - # to be seen immediately after setting the filter to a new value. - # - def agent_deleted(agent, reason); end - - # - # An agent-restart was detected. This occurs when the epoch number advertised by the - # agent changes. It indicates that the agent in question was shut-down/crashed and - # restarted. - # - def agent_restarted(agent); end - - # - # The agent has registered new schema information which can now be queried, if desired. - # - def agent_schema_updated(agent); end - - # - # An agent raised an event. The 'data' argument is a Data object that contains the - # content of the event. - # - def event_raised(agent, data, timestamp, severity); end - end - - ##============================================================================== - ## CONSOLE SESSION - ##============================================================================== - - class ConsoleSession - attr_reader :impl - - ## The options string is of the form "{key:value,key:value}". The following keys are supported: - ## - ## domain:NAME - QMF Domain to join [default: "default"] - ## max-agent-age:N - Maximum time, in minutes, that we will tolerate not hearing from - ## an agent before deleting it [default: 5] - ## listen-on-direct:{True,False} - If True: Listen on legacy direct-exchange address for backward compatibility [default] - ## If False: Listen only on the routable direct address - ## strict-security:{True,False} - If True: Cooperate with the broker to enforce strict access control to the network - ## - If False: Operate more flexibly with regard to use of messaging facilities [default] - ## - def initialize(connection, options="") - @impl = Cqmf2::ConsoleSession.new(connection, options) - end - - def set_domain(domain) @impl.setDomain(domain) end - def set_agent_filter(filter) @impl.setAgentFilter(filter) end - - def open() @impl.open end - def close() @impl.close end - - def agents - result = [] - count = @impl.getAgentCount - for i in 0...count - result << Agent.new(@impl.getAgent(i)) - end - return result - end - - def connected_broker_agent - Agent.new(@impl.getConnectedBrokerAgent) - end - end - - ##============================================================================== - ## AGENT SESSION - ##============================================================================== - - class AgentSession - attr_reader :impl - - ## The options string is of the form "{key:value,key:value}". The following keys are supported: - ## - ## interval:N - Heartbeat interval in seconds [default: 60] - ## external:{True,False} - Use external data storage (queries and subscriptions are pass-through) [default: False] - ## allow-queries:{True,False} - If True: automatically allow all queries [default] - ## If False: generate an AUTH_QUERY event to allow per-query authorization - ## allow-methods:{True,False} - If True: automatically allow all methods [default] - ## If False: generate an AUTH_METHOD event to allow per-method authorization - ## max-subscriptions:N - Maximum number of concurrent subscription queries permitted [default: 64] - ## min-sub-interval:N - Minimum publish interval (in milliseconds) permitted for a subscription [default: 3000] - ## sub-lifetime:N - Lifetime (in seconds with no keepalive) for a subscription [default: 300] - ## public-events:{True,False} - If True: QMF events are sent to the topic exchange [default] - ## If False: QMF events are only sent to authorized subscribers - ## listen-on-direct:{True,False} - If True: Listen on legacy direct-exchange address for backward compatibility [default] - ## If False: Listen only on the routable direct address - ## strict-security:{True,False} - If True: Cooperate with the broker to enforce strict access control to the network - ## - If False: Operate more flexibly with regard to use of messaging facilities [default] - ## - def initialize(connection, options="") - @impl = Cqmf2::AgentSession.new(connection, options) - end - - def set_domain(val) @impl.setDomain(val) end - def set_vendor(val) @impl.setVendor(val) end - def set_product(val) @impl.setProduct(val) end - def set_instance(val) @impl.setInstance(val) end - def set_attribute(key, val) @impl.setAttribute(key, val) end - def open() @impl.open end - def close() @impl.close end - def register_schema(cls) @impl.registerSchema(cls.impl) end - - def add_data(data, name="", persistent=false) - DataAddr.new(@impl.addData(data.impl, name, persistent)) - end - - def del_data(addr) - @impl.del_data(addr.impl) - end - - def raise_event(data, severity=nil) - if !severity - @impl.raiseEvent(data.impl) - else - @impl.raiseEvent(data.impl, severity) - end - end - end - - ##============================================================================== - ## AGENT PROXY - ##============================================================================== - - class Agent - attr_reader :impl - - def initialize(impl) - @impl = impl - end - - def name() @impl.getName end - def epoch() @impl.getEpoch end - def vendor() @impl.getVendor end - def product() @impl.getProduct end - def instance() @impl.getInstance end - def attributes() @impl.getAttributes end - - def to_s - "#{vendor}:#{product}:#{instance}" - end - - def query(q, timeout=30) - if q.class == Query - q_arg = q.impl - else - q_arg = q - end - dur = Cqpid::Duration.new(Cqpid::Duration.SECOND.getMilliseconds * timeout) - result = @impl.query(q_arg, dur) - raise QmfAgentException.new(Data.new(result.getData(0))) if result.getType == Cqmf2::CONSOLE_EXCEPTION - raise "Protocol error, expected CONSOLE_QUERY_RESPONSE, got #{result.getType}" if result.getType != Cqmf2::CONSOLE_QUERY_RESPONSE - data_list = [] - count = result.getDataCount - for i in 0...count - data_list << Data.new(result.getData(i)) - end - return data_list - end - - def load_schema_info(timeout=30) - dur = Cqpid::Duration.new(Cqpid::Duration.SECOND.getMilliseconds * timeout) - @impl.querySchema(dur) - end - - def packages - result = [] - count = @impl.getPackageCount - for i in 0...count - result << @impl.getPackage(i) - end - return result - end - - def schema_ids(package) - result = [] - count = @impl.getSchemaIdCount(package) - for i in 0...count - result << SchemaId.new(@impl.getSchemaId(package, i)) - end - return result - end - - def schema(sid, timeout=30) - dur = Cqpid::Duration.new(Cqpid::Duration.SECOND.getMilliseconds * timeout) - Schema.new(@impl.getSchema(sid.impl, dur)) - end - end - - ##============================================================================== - ## QUERY - ##============================================================================== - - class Query - attr_reader :impl - def initialize(arg1, arg2=nil, arg3=nil) - if arg1.class == Qmf2::DataAddr - @impl = Cqmf2::Query.new(arg1.impl) - end - end - - def addr() DataAddr.new(@impl.getDataAddr()) end - def schema_id() SchemaId.new(@impl.getSchemaId()) end - def predicate() @impl.getPredicate() end - - def matches?(data) - map = data - map = data.properties if data.class == Data - @impl.matchesPredicate(map) - end - end - - ##============================================================================== - ## DATA - ##============================================================================== - - class Data - attr_reader :impl - - def initialize(arg=nil) - @schema = nil - if arg == nil - @impl = Cqmf2::Data.new - elsif arg.class == Cqmf2::Data - @impl = arg - elsif arg.class == Schema - @impl = Cqmf2::Data.new(arg.impl) - @schema = arg - else - raise "Unsupported initializer for Data" - end - end - - def to_s - "#{@impl.getProperties}" - end - - def schema_id - if @impl.hasSchema - return SchemaId.new(@impl.getSchemaId) - end - return nil - end - - def set_addr(addr) - @impl.setAddr(addr.impl) - end - - def addr - if @impl.hasAddr - return DataAddr.new(@impl.getAddr) - end - return nil - end - - def agent - return Agent.new(@impl.getAgent) - end - - def update(timeout=5) - dur = Cqpid::Duration.new(Cqpid::Duration.SECOND.getMilliseconds * timeout) - agent = @impl.getAgent - query = Cqmf2::Query.new(@impl.getAddr) - result = agent.query(query, dur) - raise "Update query failed" if result.getType != Cqmf2::CONSOLE_QUERY_RESPONSE - raise "Object no longer exists on agent" if result.getDataCount == 0 - @impl = Cqmf2::Data.new(result.getData(0)) - return nil - end - - def properties - return @impl.getProperties - end - - def get_attr(name) - @impl.getProperty(name) - end - - def set_attr(name, v) - @impl.setProperty(name, v) - end - - def [](name) - get_attr(name) - end - - def []=(name, value) - set_attr(name, value) - end - - def _get_schema - unless @schema - raise "Data object has no schema" unless @impl.hasSchema - @schema = Schema.new(@impl.getAgent.getSchema(@impl.getSchemaId)) - end - end - - def method_missing(name_in, *args) - # - # Convert the name to a string and determine if it represents an - # attribute assignment (i.e. "attr=") - # - name = name_in.to_s - attr_set = (name[name.length - 1] == 61) - name = name[0..name.length - 2] if attr_set - - # - # We'll be needing the schema to determine how to proceed. Get the schema. - # Note that this call may block if the remote agent needs to be queried - # for the schema (i.e. the schema isn't in the local cache). - # - _get_schema - - # - # If the name matches a property name, set or return the value of the property. - # - @schema.properties.each do |prop| - if prop.name == name - if attr_set - return set_attr(name, args[0]) - else - return get_attr(name) - end - end - end - - # - # If we still haven't found a match for the name, check to see if - # it matches a method name. If so, marshall the arguments and invoke - # the method. - # - @schema.methods.each do |method| - if method.name == name - raise "Sets not permitted on methods" if attr_set - result = @impl.getAgent.callMethod(name, _marshall(method, args), @impl.getAddr) - if result.getType == Cqmf2::CONSOLE_EXCEPTION - raise QmfAgentException, result.getData(0) - end - return result.getArguments - end - end - - # - # This name means nothing to us, pass it up the line to the parent - # class's handler. - # - super.method_missing(name_in, args) - end - - # - # Convert a Ruby array of arguments (positional) into a Value object of type "map". - # - private - def _marshall(schema, args) - count = 0 - schema.arguments.each do |arg| - if arg.direction == DIR_IN || arg.direction == DIR_IN_OUT - count += 1 - end - end - raise "Wrong number of arguments: expecter #{count}, got #{arge.length}" if count != args.length - map = {} - count = 0 - schema.arguments.each do |arg| - if arg.direction == DIR_IN || arg.direction == DIR_IN_OUT - map[arg.name] = args[count] - count += 1 - end - end - return map - end - end - - ##============================================================================== - ## DATA ADDRESS - ##============================================================================== - - class DataAddr - attr_reader :impl - - def initialize(arg, agentName="") - if arg.class == Hash - @impl = Cqmf2::DataAddr.new(arg) - elsif arg.class == Cqmf2::DataAddr - @impl = arg - else - @impl = Cqmf2::DataAddr.new(arg, agentName) - end - end - - def ==(other) - return @impl == other.impl - end - - def as_map() @impl.asMap end - def agent_name() @impl.getAgentName end - def name() @impl.getName end - def agent_epoch() @impl.getAgentEpoch end - end - - ##============================================================================== - ## SCHEMA ID - ##============================================================================== - - class SchemaId - attr_reader :impl - def initialize(impl) - @impl = impl - end - - def type() @impl.getType end - def package_name() @impl.getPackageName end - def class_name() @impl.getName end - def hash() @impl.getHash end - end - - ##============================================================================== - ## SCHEMA - ##============================================================================== - - class Schema - attr_reader :impl - def initialize(arg, packageName="", className="", kwargs={}) - if arg.class == Cqmf2::Schema - @impl = arg - else - @impl = Cqmf2::Schema.new(arg, packageName, className) - @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) - @impl.setDefaultSeverity(kwargs[:sev]) if kwargs.include?(:sev) - end - end - - def finalize() @impl.finalize end - def schema_id() SchemaId.new(@impl.getSchemaId) end - def desc() @impl.getDesc end - def sev() @impl.getDefaultSeverity end - def add_property(prop) @impl.addProperty(prop.impl) end - def add_method(meth) @impl.addMethod(meth.impl) end - - def properties - result = [] - count = @impl.getPropertyCount - for i in 0...count - result << SchemaProperty.new(@impl.getProperty(i)) - end - return result - end - - def methods - result = [] - count = @impl.getMethodCount - for i in 0...count - result << SchemaMethod.new(@impl.getMethod(i)) - end - return result - end - end - - ##============================================================================== - ## SCHEMA PROPERTY - ##============================================================================== - - class SchemaProperty - attr_reader :impl - - def initialize(arg, dtype=nil, kwargs={}) - if arg.class == Cqmf2::SchemaProperty - @impl = arg - else - @impl = Cqmf2::SchemaProperty.new(arg, dtype) - @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) - @impl.setSubtype(kwargs[:subtype]) if kwargs.include?(:subtype) - @impl.setDirection(kwargs[:direction]) if kwargs.include?(:direction) - end - end - - def name() @impl.getName end - def access() @impl.getAccess end - def index?() @impl.isIndex end - def optional?() @impl.isOptional end - def unit() @impl.getUnit end - def desc() @impl.getDesc end - def subtype() @impl.getSubtype end - def direction() @impl.getDirection end - - def to_s - name - end - end - - ##============================================================================== - ## SCHEMA METHOD - ##============================================================================== - - class SchemaMethod - attr_reader :impl - - def initialize(arg, kwargs={}) - if arg.class == Cqmf2::SchemaMethod - @impl = arg - else - @impl = Cqmf2::SchemaMethod.new(arg) - @impl.setDesc(kwargs[:desc]) if kwargs.include?(:desc) - end - end - - def name() @impl.getName end - def desc() @impl.getDesc end - def add_argument(arg) @impl.addArgument(arg.impl) end - - def arguments - result = [] - count = @impl.getArgumentCount - for i in 0...count - result << SchemaProperty.new(@impl.getArgument(i)) - end - return result - end - - def to_s - name - end - end -end - - |
