summaryrefslogtreecommitdiff
path: root/qpid/doc/book/src/QMF-Python-Console-Tutorial.xml
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2012-04-26 16:19:39 +0000
committerRobert Godfrey <rgodfrey@apache.org>2012-04-26 16:19:39 +0000
commit7bbd90cb5c991f263213c51aa91afa818b709fc7 (patch)
treeb0bee7e2980e0ef5768d6afbd7f04e5d0e561e7a /qpid/doc/book/src/QMF-Python-Console-Tutorial.xml
parent5581d0ee8a46fea4cd0edef87bf6b439c2d7a6b3 (diff)
downloadqpid-python-7bbd90cb5c991f263213c51aa91afa818b709fc7.tar.gz
QPID-3722 : Tidy up the document generation. Split docs by book, remove monolithic book, use makefile to build
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1330925 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/doc/book/src/QMF-Python-Console-Tutorial.xml')
-rw-r--r--qpid/doc/book/src/QMF-Python-Console-Tutorial.xml894
1 files changed, 0 insertions, 894 deletions
diff --git a/qpid/doc/book/src/QMF-Python-Console-Tutorial.xml b/qpid/doc/book/src/QMF-Python-Console-Tutorial.xml
deleted file mode 100644
index 2cb802671b..0000000000
--- a/qpid/doc/book/src/QMF-Python-Console-Tutorial.xml
+++ /dev/null
@@ -1,894 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
- 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.
-
--->
-
-<section><title>
- QMF Python Console Tutorial
- </title>
- <itemizedlist>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-PrerequisiteInstallQpidMessaging"/>
- </para></listitem>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-SynchronousConsoleOperations"/>
- </para></listitem>
- <listitem><para>
- <itemizedlist>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-CreatingaQMFConsoleSessionandAttachingtoaBroker"/>
- </para></listitem>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-AccessingManagedObjects"/>
- </para></listitem>
- <listitem><para>
- <itemizedlist>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-ViewingPropertiesandStatisticsofanObject"/>
- </para></listitem>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-InvokingMethodsonanObject"/>
- </para></listitem>
- </itemizedlist>
- </para></listitem>
- </itemizedlist>
- </para></listitem>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-AsynchronousConsoleOperations"/>
- </para></listitem>
- <listitem><para>
- <itemizedlist>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-CreatingaConsoleClasstoReceiveAsynchronousData"/>
- </para></listitem>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-ReceivingEvents"/>
- </para></listitem>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-ReceivingObjects"/>
- </para></listitem>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-AsynchronousMethodCallsandMethodTimeouts"/>
- </para></listitem>
- </itemizedlist>
- </para></listitem>
- <listitem><para>
- <xref linkend="QMFPythonConsoleTutorial-DiscoveringwhatKindsofObjectsareAvailable"/>
- </para></listitem>
- </itemizedlist>
- <section role="h1" id="QMFPythonConsoleTutorial-PrerequisiteInstallQpidMessaging"><title>
- Prerequisite
- - Install Qpid Messaging
- </title>
-
- <para>
- QMF uses AMQP Messaging (QPid) as its means of communication. To
- use QMF, Qpid messaging must be installed somewhere in the
- network. Qpid can be downloaded as source from Apache, is
- packaged with a number of Linux distributions, and can be
- purchased from commercial vendors that use Qpid. Please see
- <ulink url="http://qpid.apache.org">http://qpid.apache.org</ulink>for
- information as to where to get Qpid Messaging.
- </para><para>
- Qpid Messaging includes a message broker (qpidd) which typically
- runs as a daemon on a system. It also includes client bindings in
- various programming languages. The Python-language client library
- includes the QMF console libraries needed for this tutorial.
- </para><para>
- Please note that Qpid Messaging has two broker implementations.
- One is implemented in C++ and the other in Java. At press time,
- QMF is supported only by the C++ broker.
- </para><para>
- If the goal is to get the tutorial examples up and running as
- quickly as possible, all of the Qpid components can be installed
- on a single system (even a laptop). For more realistic
- deployments, the broker can be deployed on a server and the
- client/QMF libraries installed on other systems.
- </para>
-<!--h1--></section>
-
- <section role="h1" id="QMFPythonConsoleTutorial-SynchronousConsoleOperations"><title>
- Synchronous
- Console Operations
- </title>
-
- <para>
- The Python console API for QMF can be used in a synchronous
- style, an asynchronous style, or a combination of both.
- Synchronous operations are conceptually simple and are well
- suited for user-interactive tasks. All operations are performed
- in the context of a Python function call. If communication over
- the message bus is required to complete an operation, the
- function call blocks and waits for the expected result (or
- timeout failure) before returning control to the caller.
- </para><section role="h2" id="QMFPythonConsoleTutorial-CreatingaQMFConsoleSessionandAttachingtoaBroker"><title>
- Creating a QMF Console Session and Attaching to a Broker
- </title>
-
- <para>
- For the purposes of this tutorial, code examples will be shown as
- they are entered in an interactive python session.
- </para>
- <programlisting>
-$ python
-Python 2.5.2 (r252:60911, Sep 30 2008, 15:41:38)
-[GCC 4.3.2 20080917 (Red Hat 4.3.2-4)] on linux2
-Type "help", "copyright", "credits" or "license" for more information.
-&gt;&gt;&gt;
-</programlisting>
- <para>
- We will begin by importing the required libraries. If the Python
- client is properly installed, these libraries will be found
- normally by the Python interpreter.
- </para>
- <programlisting>
-&gt;&gt;&gt; from qmf.console import Session
-</programlisting>
- <para>
- We must now create a <emphasis>Session</emphasis> object to manage this QMF
- console session.
- </para>
- <programlisting>
-&gt;&gt;&gt; sess = Session()
-</programlisting>
- <para>
- If no arguments are supplied to the creation of <emphasis>Session</emphasis>,
- it defaults to synchronous-only operation. It also defaults to
- user-management of connections. More on this in a moment.
- </para><para>
- We will now establish a connection to the messaging broker. If
- the broker daemon is running on the local host, simply use the
- following:
- </para>
- <programlisting>
-&gt;&gt;&gt; broker = sess.addBroker()
-</programlisting>
- <para>
- If the messaging broker is on a remote host, supply the URL to
- the broker in the <emphasis>addBroker</emphasis> function call. Here's how to
- connect to a local broker using the URL.
- </para>
- <programlisting>
-&gt;&gt;&gt; broker = sess.addBroker("amqp://localhost")
-</programlisting>
- <para>
- The call to <emphasis>addBroker</emphasis> is synchronous and will return
- only after the connection has been successfully established or
- has failed. If a failure occurs, <emphasis>addBroker</emphasis> will raise an
- exception that can be handled by the console script.
- </para>
- <programlisting>
-&gt;&gt;&gt; try:
-... broker = sess.addBroker("amqp://localhost:1000")
-... except:
-... print "Connection Failed"
-...
-Connection Failed
-&gt;&gt;&gt;
-</programlisting>
- <para>
- This operation fails because there is no Qpid Messaging broker
- listening on port 1000 (the default port for qpidd is 5672).
- </para><para>
- If preferred, the QMF session can manage the connection for you.
- In this case, <emphasis>addBroker</emphasis> returns immediately and the
- session attempts to establish the connection in the background.
- This will be covered in detail in the section on asynchronous
- operations.
- </para>
-<!--h2--></section>
-
- <section role="h2" id="QMFPythonConsoleTutorial-AccessingManagedObjects"><title>
- Accessing
- Managed Objects
- </title>
-
- <para>
- The Python console API provides access to remotely managed
- objects via a <emphasis>proxy</emphasis> model. The API gives the client an
- object that serves as a proxy representing the "real" object
- being managed on the agent application. Operations performed on
- the proxy result in the same operations on the real object.
- </para><para>
- The following examples assume prior knowledge of the kinds of
- objects that are actually available to be managed. There is a
- section later in this tutorial that describes how to discover
- what is manageable on the QMF bus.
- </para><para>
- Proxy objects are obtained by calling the
- <emphasis>Session.getObjects</emphasis> function.
- </para><para>
- To illustrate, we'll get a list of objects representing queues in
- the message broker itself.
- </para>
- <programlisting>
-&gt;&gt;&gt; queues = sess.getObjects(_class="queue", _package="org.apache.qpid.broker")
-</programlisting>
- <para>
- <emphasis>queues</emphasis> is an array of proxy objects representing real
- queues on the message broker. A proxy object can be printed to
- display a description of the object.
- </para>
- <programlisting>
-&gt;&gt;&gt; for q in queues:
-... print q
-...
-org.apache.qpid.broker:queue[0-1537-1-0-58] 0-0-1-0-1152921504606846979:reply-localhost.localdomain.32004
-org.apache.qpid.broker:queue[0-1537-1-0-61] 0-0-1-0-1152921504606846979:topic-localhost.localdomain.32004
-&gt;&gt;&gt;
-</programlisting>
- <section role="h3" id="QMFPythonConsoleTutorial-ViewingPropertiesandStatisticsofanObject"><title>
- Viewing Properties and Statistics of an Object
- </title>
-
- <para>
- Let us now focus our attention on one of the queue objects.
- </para>
- <programlisting>
-&gt;&gt;&gt; queue = queues[0]
-</programlisting>
- <para>
- The attributes of an object are partitioned into
- <emphasis>properties</emphasis> and <emphasis>statistics</emphasis>. Though the
- distinction is somewhat arbitrary, <emphasis>properties</emphasis> tend to
- be fairly static and may also be large and <emphasis>statistics</emphasis>
- tend to change rapidly and are relatively small (counters, etc.).
- </para><para>
- There are two ways to view the properties of an object. An array
- of properties can be obtained using the <emphasis>getProperties</emphasis>
- function:
- </para>
- <programlisting>
-&gt;&gt;&gt; props = queue.getProperties()
-&gt;&gt;&gt; for prop in props:
-... print prop
-...
-(vhostRef, 0-0-1-0-1152921504606846979)
-(name, u'reply-localhost.localdomain.32004')
-(durable, False)
-(autoDelete, True)
-(exclusive, True)
-(arguments, {})
-&gt;&gt;&gt;
-</programlisting>
- <para>
- The <emphasis>getProperties</emphasis> function returns an array of tuples.
- Each tuple consists of the property descriptor and the property
- value.
- </para><para>
- A more convenient way to access properties is by using the
- attribute of the proxy object directly:
- </para>
- <programlisting>
-&gt;&gt;&gt; queue.autoDelete
-True
-&gt;&gt;&gt; queue.name
-u'reply-localhost.localdomain.32004'
-&gt;&gt;&gt;
-</programlisting>
- <para>
- Statistics are accessed in the same way:
- </para>
- <programlisting>
-&gt;&gt;&gt; stats = queue.getStatistics()
-&gt;&gt;&gt; for stat in stats:
-... print stat
-...
-(msgTotalEnqueues, 53)
-(msgTotalDequeues, 53)
-(msgTxnEnqueues, 0)
-(msgTxnDequeues, 0)
-(msgPersistEnqueues, 0)
-(msgPersistDequeues, 0)
-(msgDepth, 0)
-(byteDepth, 0)
-(byteTotalEnqueues, 19116)
-(byteTotalDequeues, 19116)
-(byteTxnEnqueues, 0)
-(byteTxnDequeues, 0)
-(bytePersistEnqueues, 0)
-(bytePersistDequeues, 0)
-(consumerCount, 1)
-(consumerCountHigh, 1)
-(consumerCountLow, 1)
-(bindingCount, 2)
-(bindingCountHigh, 2)
-(bindingCountLow, 2)
-(unackedMessages, 0)
-(unackedMessagesHigh, 0)
-(unackedMessagesLow, 0)
-(messageLatencySamples, 0)
-(messageLatencyMin, 0)
-(messageLatencyMax, 0)
-(messageLatencyAverage, 0)
-&gt;&gt;&gt;
-</programlisting>
- <para>
- or alternatively:
- </para>
- <programlisting>
-&gt;&gt;&gt; queue.byteTotalEnqueues
-19116
-&gt;&gt;&gt;
-</programlisting>
- <para>
- The proxy objects do not automatically track changes that occur
- on the real objects. For example, if the real queue enqueues more
- bytes, viewing the <emphasis>byteTotalEnqueues</emphasis> statistic will show
- the same number as it did the first time. To get updated data on
- a proxy object, use the <emphasis>update</emphasis> function call:
- </para>
- <programlisting>
-&gt;&gt;&gt; queue.update()
-&gt;&gt;&gt; queue.byteTotalEnqueues
-19783
-&gt;&gt;&gt;
-</programlisting>
-
- <note><title>Be Advised</title>
- <para>
- The <emphasis>update</emphasis> method was added after the M4 release
- of Qpid/Qmf. It may not be available in your
- distribution.
- </para>
- </note>
-<!--h3--></section>
-
- <section role="h3" id="QMFPythonConsoleTutorial-InvokingMethodsonanObject"><title>
- Invoking
- Methods on an Object
- </title>
-
- <para>
- Up to this point, we have used the QMF Console API to find
- managed objects and view their attributes, a read-only activity.
- The next topic to illustrate is how to invoke a method on a
- managed object. Methods allow consoles to control the managed
- agents by either triggering a one-time action or by changing the
- values of attributes in an object.
- </para><para>
- First, we'll cover some background information about methods. A
- <emphasis>QMF object class</emphasis> (of which a <emphasis>QMF object</emphasis> is an
- instance), may have zero or more methods. To obtain a list of
- methods available for an object, use the <emphasis>getMethods</emphasis>
- function.
- </para>
- <programlisting>
-&gt;&gt;&gt; methodList = queue.getMethods()
-</programlisting>
- <para>
- <emphasis>getMethods</emphasis> returns an array of method descriptors (of
- type qmf.console.SchemaMethod). To get a summary of a method, you
- can simply print it. The _<emphasis>repr</emphasis>_ function returns a
- string that looks like a function prototype.
- </para>
- <programlisting>
-&gt;&gt;&gt; print methodList
-[purge(request)]
-&gt;&gt;&gt;
-</programlisting>
- <para>
- For the purposes of illustration, we'll use a more interesting
- method available on the <emphasis>broker</emphasis> object which represents
- the connected Qpid message broker.
- </para>
- <programlisting>
-&gt;&gt;&gt; br = sess.getObjects(_class="broker", _package="org.apache.qpid.broker")[0]
-&gt;&gt;&gt; mlist = br.getMethods()
-&gt;&gt;&gt; for m in mlist:
-... print m
-...
-echo(sequence, body)
-connect(host, port, durable, authMechanism, username, password, transport)
-queueMoveMessages(srcQueue, destQueue, qty)
-&gt;&gt;&gt;
-</programlisting>
- <para>
- We have just learned that the <emphasis>broker</emphasis> object has three
- methods: <emphasis>echo</emphasis>, <emphasis>connect</emphasis>, and
- <emphasis>queueMoveMessages</emphasis>. We'll use the <emphasis>echo</emphasis> method to
- "ping" the broker.
- </para>
- <programlisting>
-&gt;&gt;&gt; result = br.echo(1, "Message Body")
-&gt;&gt;&gt; print result
-OK (0) - {'body': u'Message Body', 'sequence': 1}
-&gt;&gt;&gt; print result.status
-0
-&gt;&gt;&gt; print result.text
-OK
-&gt;&gt;&gt; print result.outArgs
-{'body': u'Message Body', 'sequence': 1}
-&gt;&gt;&gt;
-</programlisting>
- <para>
- In the above example, we have invoked the <emphasis>echo</emphasis> method on
- the instance of the broker designated by the proxy "br" with a
- sequence argument of 1 and a body argument of "Message Body". The
- result indicates success and contains the output arguments (in
- this case copies of the input arguments).
- </para><para>
- To be more precise... Calling <emphasis>echo</emphasis> on the proxy causes
- the input arguments to be marshalled and sent to the remote agent
- where the method is executed. Once the method execution
- completes, the output arguments are marshalled and sent back to
- the console to be stored in the method result.
- </para><para>
- You are probably wondering how you are supposed to know what
- types the arguments are and which arguments are input, which are
- output, or which are both. This will be addressed later in the
- "Discovering what Kinds of Objects are Available" section.
- </para>
-<!--h3--></section>
-<!--h2--></section>
-<!--h1--></section>
-
- <section role="h1" id="QMFPythonConsoleTutorial-AsynchronousConsoleOperations"><title>
- Asynchronous
- Console Operations
- </title>
-
- <para>
- QMF is built on top of a middleware messaging layer (Qpid
- Messaging). Because of this, QMF can use some communication
- patterns that are difficult to implement using network transports
- like UDP, TCP, or SSL. One of these patterns is called the
- <emphasis>Publication and Subscription</emphasis> pattern (pub-sub for
- short). In the pub-sub pattern, data sources <emphasis>publish</emphasis>
- information without a particular destination in mind. Data sinks
- (destinations) <emphasis>subscribe</emphasis> using a set of criteria that
- describes what kind of data they are interested in receiving.
- Data published by a source may be received by zero, one, or many
- subscribers.
- </para><para>
- QMF uses the pub-sub pattern to distribute events, object
- creation and deletion, and changes to properties and statistics.
- A console application using the QMF Console API can receive these
- asynchronous and unsolicited events and updates. This is useful
- for applications that store and analyze events and/or statistics.
- It is also useful for applications that react to certain events
- or conditions.
- </para><para>
- Note that console applications may always use the synchronous
- mechanisms.
- </para>
-
- <section role="h2" id="QMFPythonConsoleTutorial-CreatingaConsoleClasstoReceiveAsynchronousData"><title>
- Creating a Console Class to Receive Asynchronous Data
- </title>
-
- <para>
- Asynchronous API operation occurs when the console application
- supplies a <emphasis>Console</emphasis> object to the session manager. The
- <emphasis>Console</emphasis> object (which overrides the
- <emphasis>qmf.console.Console</emphasis> class) handles all asynchronously
- arriving data. The <emphasis>Console</emphasis> class has the following
- methods. Any number of these methods may be overridden by the
- console application. Any method that is not overridden defaults
- to a null handler which takes no action when invoked.
- </para><table><title>QMF Python Console Class Methods</title><tgroup cols="3">
- <tbody>
- <row>
- <entry>
- Method
- </entry>
- <entry>
- Arguments
- </entry>
- <entry>
- Invoked when...
- </entry>
- </row>
- <row>
- <entry>
- brokerConnected
- </entry>
- <entry>
- broker
- </entry>
- <entry>
- a connection to a broker is established
- </entry>
- </row>
- <row>
- <entry>
- brokerDisconnected
- </entry>
- <entry>
- broker
- </entry>
- <entry>
- a connection to a broker is lost
- </entry>
- </row>
- <row>
- <entry>
- newPackage
- </entry>
- <entry>
- name
- </entry>
- <entry>
- a new package is seen on the QMF bus
- </entry>
- </row>
- <row>
- <entry>
- newClass
- </entry>
- <entry>
- kind, classKey
- </entry>
- <entry>
- a new class (event or object) is seen on the QMF bus
- </entry>
- </row>
- <row>
- <entry>
- newAgent
- </entry>
- <entry>
- agent
- </entry>
- <entry>
- a new agent appears on the QMF bus
- </entry>
- </row>
- <row>
- <entry>
- delAgent
- </entry>
- <entry>
- agent
- </entry>
- <entry>
- an agent disconnects from the QMF bus
- </entry>
- </row>
- <row>
- <entry>
- objectProps
- </entry>
- <entry>
- broker, object
- </entry>
- <entry>
- the properties of an object are published
- </entry>
- </row>
- <row>
- <entry>
- objectStats
- </entry>
- <entry>
- broker, object
- </entry>
- <entry>
- the statistics of an object are published
- </entry>
- </row>
- <row>
- <entry>
- event
- </entry>
- <entry>
- broker, event
- </entry>
- <entry>
- an event is published
- </entry>
- </row>
- <row>
- <entry>
- heartbeat
- </entry>
- <entry>
- agent, timestamp
- </entry>
- <entry>
- a heartbeat is published by an agent
- </entry>
- </row>
- <row>
- <entry>
- brokerInfo
- </entry>
- <entry>
- broker
- </entry>
- <entry>
- information about a connected broker is available to be
- queried
- </entry>
- </row>
- <row>
- <entry>
- methodResponse
- </entry>
- <entry>
- broker, seq, response
- </entry>
- <entry>
- the result of an asynchronous method call is received
- </entry>
- </row>
- </tbody>
- </tgroup></table><para>
- Supplied with the API is a class called <emphasis>DebugConsole</emphasis>.
- This is a test <emphasis>Console</emphasis> instance that overrides all of
- the methods such that arriving asynchronous data is printed to
- the screen. This can be used to see all of the arriving
- asynchronous data.
- </para>
- <!--h2--></section>
-
- <section role="h2" id="QMFPythonConsoleTutorial-ReceivingEvents"><title>
- Receiving
- Events
- </title>
-
- <para>
- We'll start the example from the beginning to illustrate the
- reception and handling of events. In this example, we will create
- a <emphasis>Console</emphasis> class that handles broker-connect,
- broker-disconnect, and event messages. We will also allow the
- session manager to manage the broker connection for us.
- </para><para>
- Begin by importing the necessary classes:
- </para>
- <programlisting>
-&gt;&gt;&gt; from qmf.console import Session, Console
-</programlisting>
- <para>
- Now, create a subclass of <emphasis>Console</emphasis> that handles the three
- message types:
- </para>
- <programlisting>
-&gt;&gt;&gt; class EventConsole(Console):
-... def brokerConnected(self, broker):
-... print "brokerConnected:", broker
-... def brokerDisconnected(self, broker):
-... print "brokerDisconnected:", broker
-... def event(self, broker, event):
-... print "event:", event
-...
-&gt;&gt;&gt;
-</programlisting>
- <para>
- Make an instance of the new class:
- </para>
- <programlisting>
-&gt;&gt;&gt; myConsole = EventConsole()
-</programlisting>
- <para>
- Create a <emphasis>Session</emphasis> class using the console instance. In
- addition, we shall request that the session manager do the
- connection management for us. Notice also that we are requesting
- that the session manager not receive objects or heartbeats. Since
- this example is concerned only with events, we can optimize the
- use of the messaging bus by telling the session manager not to
- subscribe for object updates or heartbeats.
- </para>
- <programlisting>
-&gt;&gt;&gt; sess = Session(myConsole, manageConnections=True, rcvObjects=False, rcvHeartbeats=False)
-&gt;&gt;&gt; broker = sess.addBroker()
-&gt;&gt;&gt;
-</programlisting>
- <para>
- Once the broker is added, we will begin to receive asynchronous
- events (assuming there is a functioning broker available to
- connect to).
- </para>
- <programlisting>
-brokerConnected: Broker connected at: localhost:5672
-event: Thu Jan 29 19:53:19 2009 INFO org.apache.qpid.broker:bind broker=localhost:5672 ...
-</programlisting>
-<!--h2--></section>
-
- <section role="h2" id="QMFPythonConsoleTutorial-ReceivingObjects"><title>
- Receiving
- Objects
- </title>
-
- <para>
- To illustrate asynchronous handling of objects, a small console
- program is supplied. The entire program is shown below for
- convenience. We will then go through it part-by-part to explain
- its design.
- </para><para>
- This console program receives object updates and displays a set
- of statistics as they change. It focuses on broker queue objects.
- </para>
- <programlisting>
-# Import needed classes
-from qmf.console import Session, Console
-from time import sleep
-
-# Declare a dictionary to map object-ids to queue names
-queueMap = {}
-
-# Customize the Console class to receive object updates.
-class MyConsole(Console):
-
- # Handle property updates
- def objectProps(self, broker, record):
-
- # Verify that we have received a queue object. Exit otherwise.
- classKey = record.getClassKey()
- if classKey.getClassName() != "queue":
- return
-
- # If this object has not been seen before, create a new mapping from objectID to name
- oid = record.getObjectId()
- if oid not in queueMap:
- queueMap[oid] = record.name
-
- # Handle statistic updates
- def objectStats(self, broker, record):
-
- # Ignore updates for objects that are not in the map
- oid = record.getObjectId()
- if oid not in queueMap:
- return
-
- # Print the queue name and some statistics
- print "%s: enqueues=%d dequeues=%d" % (queueMap[oid], record.msgTotalEnqueues, record.msgTotalDequeues)
-
- # if the delete-time is non-zero, this object has been deleted. Remove it from the map.
- if record.getTimestamps()[2] &gt; 0:
- queueMap.pop(oid)
-
-# Create an instance of the QMF session manager. Set userBindings to True to allow
-# this program to choose which objects classes it is interested in.
-sess = Session(MyConsole(), manageConnections=True, rcvEvents=False, userBindings=True)
-
-# Register to receive updates for broker:queue objects.
-sess.bindClass("org.apache.qpid.broker", "queue")
-broker = sess.addBroker()
-
-# Suspend processing while the asynchronous operations proceed.
-try:
- while True:
- sleep(1)
-except:
- pass
-
-# Disconnect the broker before exiting.
-sess.delBroker(broker)
-</programlisting>
- <para>
- Before going through the code in detail, it is important to
- understand the differences between synchronous object access and
- asynchronous object access. When objects are obtained
- synchronously (using the <emphasis>getObjects</emphasis> function), the
- resulting proxy contains all of the object's attributes, both
- properties and statistics. When object data is published
- asynchronously, the properties and statistics are sent separately
- and only when the session first connects or when the content
- changes.
- </para><para>
- The script wishes to print the queue name with the updated
- statistics, but the queue name is only present with the
- properties. For this reason, the program needs to keep some state
- to correlate property updates with their corresponding statistic
- updates. This can be done using the <emphasis>ObjectId</emphasis> that
- uniquely identifies the object.
- </para>
- <programlisting>
- # If this object has not been seen before, create a new mapping from objectID to name
- oid = record.getObjectId()
- if oid not in queueMap:
- queueMap[oid] = record.name
-</programlisting>
- <para>
- The above code fragment gets the object ID from the proxy and
- checks to see if it is in the map (i.e. has been seen before). If
- it is not in the map, a new map entry is inserted mapping the
- object ID to the queue's name.
- </para>
- <programlisting>
- # if the delete-time is non-zero, this object has been deleted. Remove it from the map.
- if record.getTimestamps()[2] &gt; 0:
- queueMap.pop(oid)
-</programlisting>
- <para>
- This code fragment detects the deletion of a managed object.
- After reporting the statistics, it checks the timestamps of the
- proxy. <emphasis>getTimestamps</emphasis> returns a list of timestamps in the
- order:
- </para><itemizedlist>
- <listitem><para>
- <emphasis>Current</emphasis> - The timestamp of the sending of this update.
- </para></listitem>
- <listitem><para>
- <emphasis>Create</emphasis> - The time of the object's creation
- </para></listitem>
- <listitem><para>
- <emphasis>Delete</emphasis> - The time of the object's deletion (or zero if
- not deleted)
- </para></listitem>
- </itemizedlist><para>
- This code structure is useful for getting information about
- very-short-lived objects. It is possible that an object will be
- created, used, and deleted within an update interval. In this
- case, the property update will arrive first, followed by the
- statistic update. Both will indicate that the object has been
- deleted but a full accounting of the object's existence and final
- state is reported.
- </para>
- <programlisting>
-# Create an instance of the QMF session manager. Set userBindings to True to allow
-# this program to choose which objects classes it is interested in.
-sess = Session(MyConsole(), manageConnections=True, rcvEvents=False, userBindings=True)
-
-# Register to receive updates for broker:queue objects.
-sess.bindClass("org.apache.qpid.broker", "queue")
-</programlisting>
- <para>
- The above code is illustrative of the way a console application
- can tune its use of the QMF bus. Note that <emphasis>rcvEvents</emphasis> is
- set to False. This prevents the reception of events. Note also
- the use of <emphasis>userBindings=True</emphasis> and the call to
- <emphasis>sess.bindClass</emphasis>. If <emphasis>userBindings</emphasis> is set to False
- (its default), the session will receive object updates for all
- classes of object. In the case above, the application is only
- interested in broker:queue objects and reduces its bus bandwidth
- usage by requesting updates to only that class.
- <emphasis>bindClass</emphasis> may be called as many times as desired to add
- classes to the list of subscribed classes.
- </para>
-<!--h2--></section>
-
- <section role="h2" id="QMFPythonConsoleTutorial-AsynchronousMethodCallsandMethodTimeouts"><title>
- Asynchronous Method Calls and Method Timeouts
- </title>
-
- <para>
- Method calls can also be invoked asynchronously. This is useful
- if a large number of calls needs to be made in a short time
- because the console application will not need to wait for the
- complete round-trip delay for each call.
- </para><para>
- Method calls are synchronous by default. They can be made
- asynchronous by adding the keyword-argument _<emphasis>async=True</emphasis>
- to the method call.
- </para><para>
- In a synchronous method call, the return value is the method
- result. When a method is called asynchronously, the return value
- is a sequence number that can be used to correlate the eventual
- result to the request. This sequence number is passed as an
- argument to the <emphasis>methodResponse</emphasis> function in the
- <emphasis>Console</emphasis> interface.
- </para><para>
- It is important to realize that the <emphasis>methodResponse</emphasis>
- function may be invoked before the asynchronous call returns.
- Make sure your code is written to handle this possibility.
- </para>
- <!--h2--></section>
- <!--h1--></section>
-
- <section role="h1" id="QMFPythonConsoleTutorial-DiscoveringwhatKindsofObjectsareAvailable"><title>
- Discovering what Kinds of Objects are Available
- </title>
- <para/>
- <!--h1--></section>
-
-
-</section>