[
https://issues.apache.org/jira/browse/QPID-2411?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Andrew English updated QPID-2411:
---------------------------------
Attachment: qmf-cpp-console-tutorial.html
Attach tutorial as file.
> Created Documentation for Writing a CPP QMF console application
> ---------------------------------------------------------------
>
> Key: QPID-2411
> URL: https://issues.apache.org/jira/browse/QPID-2411
> Project: Qpid
> Issue Type: Improvement
> Components: Documentation
> Reporter: Andrew English
> Priority: Minor
> Attachments: qmf-cpp-console-tutorial.html
>
>
> I have pasted in my initial draft of the documentation for creating a QMF
> console application in C++. If this is still needed, I will complete the
> sections on calling methods and asynchronous notifications.
> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
> "http://www.w3.org/TR/html4/loose.dtd">
> <html><head>
>
> <link type="text/css" rel="stylesheet"
> href="qmf-python-console-tutorial_files/space.css">
> <style type="text/css">
> .footer {
> background-image:
> url('http://cwiki.apache.org/confluence/images/border/border_bottom.gif');
> background-repeat: repeat-x;
> background-position: left top;
> padding-top: 4px;
> color: #666;
> clear: both;
> }
> .left {
> padding-top: 5px;
> float : left;
> width : 15em;
> }
> .pagecontent {
> float: left;
> width: 70%;
> }
> </style>
> <script type="text/javascript" language="javascript">
> var hide = null;
> var show = null;
> var children = null;
> function init() {
> /* Search form initialization */
> var form = document.forms['search'];
> if (form != null) {
> form.elements['domains'].value = location.hostname;
> form.elements['sitesearch'].value = location.hostname;
> }
> /* Children initialization */
> hide = document.getElementById('hide');
> show = document.getElementById('show');
> children = document.all != null ?
> document.all['children'] :
> document.getElementById('children');
> if (children != null) {
> children.style.display = 'none';
> show.style.display = 'inline';
> hide.style.display = 'none';
> }
> }
> function showChildren() {
> children.style.display = 'block';
> show.style.display = 'none';
> hide.style.display = 'inline';
> }
> function hideChildren() {
> children.style.display = 'none';
> show.style.display = 'inline';
> hide.style.display = 'none';
> }
> </script>
> <title>Apache Qpid: Open Source AMQP Messaging - QMF Cpp Console
> Tutorial</title>
> <meta http-equiv="Content-Type" content="text/html;
> charset=UTF-8"></head><body
> onload="init()">
> <table width="100%" border="0" cellpadding="2" cellspacing="0">
> <tbody><tr class="topBar">
> <td class="topBarDiv" valign="middle" align="left"
> nowrap="nowrap">
> <a href="http://qpid.apache.org/index.html"
> title="Apache Qpid">Apache Qpid</a> > <a
> href="http://qpid.apache.org/index.html"
> title="Index">Index</a> > <a
> href="http://qpid.apache.org/developer-pages.html" title="Developer
> Pages">Developer Pages</a> > <a
> href="http://qpid.apache.org/qpid-management-framework.html" title="Qpid
> Management Framework">Qpid Management Framework</a> > <a
> href="" title="QMF Cpp Console Tutorial">QMF Cpp Console Tutorial</a>
> </td>
> <td valign="middle" align="right" nowrap="nowrap">
> <form name="search" action="http://www.google.com/search"
> method="get">
> <input name="ie" value="UTF-8" type="hidden">
> <input name="oe" value="UTF-8" type="hidden">
> <input name="domains" value="qpid.apache.org" type="hidden">
> <input name="sitesearch" value="qpid.apache.org"
> type="hidden">
> <input name="q" maxlength="255" type="text">
> <input name="btnG" value="Google Search" type="submit">
> </form>
> </td>
> </tr>
> </tbody></table>
> <div id="PageContent">
> <div class="pageheader" style="padding: 6px 0px 0px;">
> <div>
> <table width="90%" border="0">
> <tbody><tr>
> <td align="left">
> <a href="http://qpid.apache.org/">
> <img src="qmf-python-console-tutorial_files/qpid-logo.png" width="225"
> border="0" height="69"></a>
> </td>
> <td>
> </td>
> <td align="right"> <a href="http://www.apache.org/">
> <img src="qmf-python-console-tutorial_files/asf-logo.png"
> width="225" border="0" height="69"></a></td>
> </tr>
> </tbody></table>
> </div>
> </div>
> <!--
> <div class="pagesubheading" style="margin: 0px 10px 0px 10px;">
> Added by <a href="/confluence/display/~tross">Ted
> Ross</a>, last edited by <a href="/confluence/display/~tross">Ted Ross</a> on
> Mar 03, 2009
> (<a class="noprint"
> href="/confluence/pages/diffpages.action?pageId=108629&originalId=111632">view
> change</a>)
>
> </div>
> -->
> <div class="left">
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> <div class="panel" style="border: 1px solid rgb(32, 32,
> 128);"><div class="panelContent" style="">
> <h3><a name="Navigation-ApacheQpid"></a>Apache Qpid</h3>
> <p> <a href="http://qpid.apache.org/index.html" title="Index">Home</a><br>
> <a href="http://qpid.apache.org/download.html"
> title="Download">Download</a><br>
> <a href="http://qpid.apache.org/getting-started.html" title="Getting
> Started">Getting Started</a> <br>
> <a href="http://qpid.apache.org/documentation.html"
> title="Documentation">Documentation</a><br>
> <a href="http://qpid.apache.org/mailing-lists.html" title="Mailing
> Lists">Mailing Lists</a><br>
> <a href="http://issues.apache.org/jira/browse/qpid" rel="nofollow">Issue
> Reporting</a><br>
> <a href="http://qpid.apache.org/faq.html" title="FAQ">FAQ/How to</a></p>
> <h3><a name="Navigation-Resources"></a>Resources</h3>
> <p> <a href="http://qpid.apache.org/getting-involved.html"
> title="Getting Involved">Getting Involved</a><br>
> <a href="http://qpid.apache.org/qpid-integrations.html" title="Qpid
> Integrations">Qpid Integrated with..</a><br>
> <a href="http://qpid.apache.org/source-repository.html" title="Source
> Repository">Source Repository</a><br>
> <a href="http://qpid.apache.org/building.html" title="Building">Building
> Qpid</a><br>
> <a href="http://qpid.apache.org/developer-pages.html" title="Developer
> Pages">Developer Pages</a><br>
> <a href="http://qpid.apache.org/qpid-management-framework.html"
> title="Qpid Management Framework">QMF</a></p>
> <h3><a name="Navigation-AboutQpid"></a>About Qpid</h3>
> <p> <a href="http://qpid.apache.org/people.html" title="People">People</a><br>
> <a href="http://qpid.apache.org/license.html" title="License">License</a><br>
> <a href="http://qpid.apache.org/project-status.html" title="Project
> Status">Project Status</a><br>
> <a href="http://qpid.apache.org/acknowledgments.html"
> title="Acknowledgments">Acknowledgments</a></p>
> <h3><a name="Navigation-AboutAMQP"></a>About AMQP</h3>
> <p> <a
> href="http://qpid.apache.org/amqp-advanced-message-queueing-protocol.html"
> title="AMQP (Advanced Message Queueing Protocol)">What is AMQP ?</a><br>
> <a
> href="http://qpid.apache.org/amqp-advanced-message-queueing-protocol.html"
> title="AMQP (Advanced Message Queueing Protocol)">AMQP Specification
> Download</a></p>
> <p><img src="qmf-python-console-tutorial_files/AMQP_logo_71px-small.jpg"
> align="absmiddle" border="0"></p>
> </div></div>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> </div>
> <div class="pagecontent">
> <div class="wiki-content">
> <div>
> <ul>
> <li><a
> href="#QMFCPPConsoleTutorial-PrerequisiteInstallQpidMessaging">Prerequisite
> - Install Qpid Messaging</a></li>
> <li><a
> href="#QMFCPPConsoleTutorial-SynchronousConsoleOperations">Synchronous
> Console Operations</a></li>
> <ul>
> <li><a
> href="#QMFCPPConsoleTutorial-CreatingaQMFConsoleSessionandAttachingtoaBroker">Creating
> a QMF Console Session and Attaching to a Broker</a></li>
> <li><a href="#QMFCPPConsoleTutorial-AccessingManagedObjects">Accessing
> Managed Objects</a></li>
> <ul>
> <li><a
> href="#QMFCPPConsoleTutorial-ViewingPropertiesandStatisticsofanObject">Viewing
> Properties and Statistics of an Object</a></li>
> <li><a href="#QMFCPPConsoleTutorial-InvokingMethodsonanObject">Invoking
> Methods on an Object</a></li>
> </ul>
> </ul>
> <li><a
> href="#QMFPythonConsoleTutorial-AsynchronousConsoleOperations">Asynchronous
> Console Operations</a></li>
> <ul>
> <li><a
> href="#QMFPythonConsoleTutorial-CreatingaConsoleClasstoReceiveAsynchronousData">Creating
> a Console Class to Receive Asynchronous Data</a></li>
> <li><a href="#QMFPythonConsoleTutorial-ReceivingEvents">Receiving
> Events</a></li>
> <li><a href="#QMFPythonConsoleTutorial-ReceivingObjects">Receiving
> Objects</a></li>
> <li><a
> href="#QMFPythonConsoleTutorial-AsynchronousMethodCallsandMethodTimeouts">Asynchronous
> Method Calls and Method Timeouts</a></li>
> </ul>
> <li><a
> href="#QMFPythonConsoleTutorial-DiscoveringwhatKindsofObjectsareAvailable">Discovering
> what Kinds of Objects are Available</a></li>
> </ul></div>
> <h1><a
> name="QMFPythonConsoleTutorial-PrerequisiteInstallQpidMessaging"></a>Prerequisite
> - Install Qpid Messaging</h1>
> <p>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 <a href="http://qpid.apache.org/download.html"
> title="Download">Download</a> for information as to where to get Qpid
> Messaging.</p>
> <p>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 C++-language client library includes the source
> for the
> QMF console libraries needed for this tutorial.</p>
> <p>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.</p>
> <p>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.</p>
> <h1><a
> name="QMFCPPConsoleTutorial-SynchronousConsoleOperations"></a>Synchronous
> Console Operations</h1>
> <p>The C++ 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 C++ 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.</p>
> <h2><a
> name="QMFCPPConsoleTutorial-CreatingaQMFConsoleSessionandAttachingtoaBroker"></a>Creating
> a QMF Console Session and Attaching to a Broker</h2>
> <p>For the purposes of this tutorial, code examples will be shown in snippets
> revelant to the current task.</p>
> <p>We will begin by including the required libraries. If the QMF libraries
> are installed in the lib directory, they
> can be referenced when building and linking the application:</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>
> g++ -c -I/usr/include/qpid-boost qmfagent.cpp -o qmfagent.o
> g++ -lqpidclient -lqmfconsole ./qmfagent.o -o qmfagent
> </pre>
> </div></div>
> In the source, they should be included as follows:
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>#include <qpid/console/SessionManager.h>
>
> namespace qmf = qpid::console;
> </pre>
> </div></div>
> <p>We must now create a <em>Session</em> object to manage this QMF
> console session.</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>qmf::SessionManager sessMgr;
> </pre>
> </div></div>
> <p>If no arguments are supplied to the creation of <em>Session</em>, it
> defaults to synchronous-only operation. It also defaults to
> user-management of connections. More on this in a moment.</p>
> <p>We will now establish a connection to the messaging broker. If the
> broker daemon is running on the local host, simply use the following:</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>qmf::Broker* broker = sessMgr.addBroker();
> </pre>
> </div></div>
> <p>If the messaging broker is on a remote host, supply the URL to the
> broker in the <em>addBroker</em> function call. Here's how to connect
> to a local broker using the URL.</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>qmf::Broker* broker = sessMgr.addBroker("amqp://localhost");
> </pre>
> </div></div>
> <p>A <em>ConnectionSettings</em> object can also be passed to the
> <em>addBroker</em> function call.</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>qmf_::SessionManager sessMgr;
> qc::ConnectionSettings settings;
> settings.host = host;
> settings.port = port;
> qmf::Broker* broker = sessMgr.addBroker(settings);
> </pre>
> </div></div>
> <p>The call to <em>addBroker</em> is synchronous and will return only
> after the connection has been successfully established or has failed.
> If a failure occurs, <em>addBroker</em> will raise an exception.</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>try
> {
> qmf::Broker* broker = sessMgr.addBroker("amqp://localhost:1000");
> }
> catch(const std::exception& error)
> {
> std::cout << "Failed to connect: " << error.what() <<
> std::endl;
> }
> </pre>
> </div></div>
> <p>This operation fails because there is no Qpid Messaging broker
> listening on port 1000 (the default port for qpidd is 5672).</p>
> <p>If preferred, the QMF session can manage the connection for you. In
> this case, <em>addBroker</em> 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.</p>
> <h2><a name="QMFCPPConsoleTutorial-AccessingManagedObjects"></a>Accessing
> Managed Objects</h2>
> <p>The C++ console API provides access to remotely managed objects
> via a <em>proxy</em> 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.</p>
> <p>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.</p>
> <p>Proxy objects are obtained by calling the <em>Session.getObjects</em>
> function.</p>
> <p>To illustrate, we'll get a list of objects representing queues in the
> message broker itself.</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>qmf::Object::Vector objects;
> sessMgr.getObjects(objects, "queue");
> </pre>
> </div></div>
> <p>We can also specify a specific broker when querying.</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>qmf::Broker* broker = sessMgr.addBroker("amqp://localhost:5672");
> qmf::Object::Vector objects;
> sessMgr.getObjects(objects, "queue", broker);
> </pre>
> </div></div>
> <p><em>queues</em> 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.</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>for(unsigned int i = 0; i < objects.size(); i++)
> {
> std::string queueName = objects[i].attrString("name");
> std::cout << "name: " << queueName << std::endl;
>
> qmf::Object obj = objects[i];
> std::cout << "tostring: " << obj << std::endl;
> }
> name: qmfc-a3159ef6-17c5-461f-a27d-7c79fcc132fc
> tostring: org.apache.qpid.broker:queue[0-21-1-0-179]
> 0-0-1-0-1152921504606846979:qmfc-a3159ef6-17c5-461f-a27d-7c79fcc132fc
> </pre>
> </div></div>
> <h3><a
> name="QMFPythonConsoleTutorial-ViewingPropertiesandStatisticsofanObject"></a>Viewing
> Attributes of an Object</h3>
> <p>Let us now focus our attention on one of the queue objects.</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>qmf::Object obj = objects[i];
> </pre>
> </div></div>
> <p>The attributes of an object are stored in a map.</p>
> <p>We can iterate through the attributes of an object:</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>qmf::Object::AttributeMap attributes = obj.getAttributes();
> for(qmf::Object::AttributeMap::const_iterator vIter = attributes.begin();
> vIter != attributes.end(); vIter++)
> {
> std::cout << "Attribute: " << vIter->first << "
> Value: " << vIter->second->str() << std::endl;
> }
> Attribute: arguments Value: {}
> Attribute: autoDelete Value: T
> Attribute: bindingCount Value: 4
> Attribute: bindingCountHigh Value: 4
> Attribute: bindingCountLow Value: 4
> Attribute: byteDepth Value: 912
> Attribute: bytePersistDequeues Value: 0
> Attribute: bytePersistEnqueues Value: 0
> Attribute: byteTotalDequeues Value: 30371
> Attribute: byteTotalEnqueues Value: 31283
> Attribute: byteTxnDequeues Value: 0
> Attribute: byteTxnEnqueues Value: 0
> Attribute: consumerCount Value: 1
> Attribute: consumerCountHigh Value: 1
> Attribute: consumerCountLow Value: 1
> Attribute: durable Value: F
> Attribute: exclusive Value: T
> Attribute: messageLatencyAverage Value: 0
> Attribute: messageLatencyMax Value: 0
> Attribute: messageLatencyMin Value: 0
> Attribute: messageLatencySamples Value: 0
> Attribute: msgDepth Value: 3
> Attribute: msgPersistDequeues Value: 0
> Attribute: msgPersistEnqueues Value: 0
> Attribute: msgTotalDequeues Value: 72
> Attribute: msgTotalEnqueues Value: 75
> Attribute: msgTxnDequeues Value: 0
> Attribute: msgTxnEnqueues Value: 0
> Attribute: name Value: qmfc-bfd3ec18-8222-488f-8c3d-221029145106
> Attribute: unackedMessages Value: 0
> Attribute: unackedMessagesHigh Value: 0
> Attribute: unackedMessagesLow Value: 0
> Attribute: vhostRef Value: 0-0-1-0-1152921504606846979
> </pre>
> </div></div>
> <p>A more convenient way to access attributes is by using the attribute
> of the proxy object directly:</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>std::string name;
> name = obj.attrString("name");
> std::cout << "Name: " << name << std::endl;
> bool autoDelete;
> autoDelete = obj.attrBool("autoDelete");
> std::cout << "autoDelete: " << autoDelete << std::endl;
> Name: qmfc-e9d8f830-ac50-4377-b38c-7b0ffa1d86d2
> autoDelete: 1
> </pre>
> </div></div>
> <p>Statistics are accessed in the same way:</p>
> <div class="preformatted panel" style="border-width: 1px;"><div
> class="preformattedContent panelContent">
> <pre>int msgDepth;
> msgDepth = obj.attrInt("msgDepth");
> std::cout << "msgDepth: " << msgDepth << std::endl;
> msgDepth: 0
> </pre>
> </div></div>
> <p>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 <em>byteTotalEnqueues</em> statistic will show the same
> number as it did the first time. To get updated data on a proxy object,
> query the <em>SessionManager</em> again.</p>
> </div>
> <!--
> -->
> </div>
> <div class="footer">
> Apache Qpid, Enterprise AMQP Messaging
>
> © 2004-2008 The Apache Software Foundation.
>
> (<a
> href="http://cwiki.apache.org/confluence/pages/editpage.action?pageId=108629">edit
> this page</a>)
> </div>
> </div></body></html>
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project: http://qpid.apache.org
Use/Interact: mailto:[email protected]