version 1.1, 2002/02/05 23:14:54
|
version 1.3, 2002/03/12 22:57:40
|
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
|
<html lang="en"><head> |
|
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>XML Pointer Language (XPointer) Version 1.0</title><style type="text/css"> |
|
|
|
body { |
|
margin: 2em 1em 2em; |
|
font-family: sans-serif; |
|
color: black; |
|
background: white; |
|
background-position: top left; |
|
background-attachment: fixed; |
|
background-repeat: no-repeat; |
|
} |
|
:link { color: #00C; background: transparent } |
|
:visited { color: #609; background: transparent } |
|
:active { color: #C00; background: transparent } |
|
|
|
th, td { /* ns 4 */ |
|
font-family: sans-serif; |
|
} |
|
|
|
h1, h2, h3, h4, h5, h6 { text-align: left } |
|
/* background should be transparent, but WebTV has a bug */ |
|
h1, h2, h3 { color: #005A9C; background: white } |
|
h1 { font: 170% sans-serif } |
|
h2 { font: 140% sans-serif } |
|
h3 { font: 120% sans-serif } |
|
h4 { font: bold 100% sans-serif } |
|
h5 { font: italic 100% sans-serif } |
|
h6 { font: small-caps 100% sans-serif } |
|
|
|
.hide { display: none } |
|
|
|
div.head { margin-bottom: 1em } |
|
div.head h1 { margin-top: 2em; clear: both } |
|
div.head table { margin-left: 2em; margin-top: 2em } |
|
div.head img { color: white; border: none } /* remove border from top image */ |
|
|
|
p.copyright { font-size: small } |
|
p.copyright small { font-size: small } |
|
|
|
pre { margin-left: 2em } |
|
/* |
|
p { |
|
margin-top: 0.6em; |
|
margin-bottom: 0.6em; |
|
} |
|
*/ |
|
dt, dd { margin-top: 0; margin-bottom: 0 } /* opera 3.50 */ |
|
dt { font-weight: bold } |
|
|
|
pre, code { font-family: monospace } /* navigator 4 requires this */ |
|
|
|
ul.toc { |
|
list-style: disc; /* Mac NS has problem with 'none' */ |
|
list-style: none; |
|
} |
|
|
|
code { font-family: monospace; } |
|
|
|
div.constraint, |
|
div.issue, |
|
div.note, |
|
div.notice { margin-left: 2em; } |
|
|
|
li p { margin-top: 0.3em; |
|
margin-bottom: 0.3em; } |
|
|
|
div.exampleInner pre { margin-left: 1em; |
|
margin-top: 0em; margin-bottom: 0em} |
|
div.exampleOuter {border: 4px double gray; |
|
margin: 0em; padding: 0em} |
|
div.exampleInner { background-color: #d5dee3; |
|
border-top-width: 4px; |
|
border-top-style: double; |
|
border-top-color: #d3d3d3; |
|
border-bottom-width: 4px; |
|
border-bottom-style: double; |
|
border-bottom-color: #d3d3d3; |
|
padding: 4px; margin: 0em } |
|
div.exampleWrapper { margin: 4px } |
|
div.exampleHeader { font-weight: bold; |
|
margin: 4px} |
|
|
|
table { background-color: #d5dee3; |
|
width: 85% ; |
|
border-style: double; |
|
border-width: 4px; |
|
border-color: #d3d3d3; |
|
} |
|
</style> |
|
|
<html> | <html> |
<head> | <head> |
<title>Pegasus Meta Dispatcher</title> | <title>Pegasus Meta Dispatcher</title> |
</head> | </head> |
| |
<body> | <body> |
|
|
|
<p class="copyright">this is copyright text</p> |
|
|
|
<div class="constraint">this is a constraint</div> |
|
|
|
<div class="exampleInner"><code>this is an inner example</code></div> |
<h1>Pegasus Meta Dispatcher</h1> | <h1>Pegasus Meta Dispatcher</h1> |
<p> | <p> |
The Pegasus Meta Dispatcher is a set of classes that extend the | The Pegasus Meta Dispatcher is a set of classes that extend the |
|
|
asynchronous, and multithreaded. The primary classes consist of the | asynchronous, and multithreaded. The primary classes consist of the |
folowing: | folowing: |
</p> | </p> |
<table border="1" bgcolor="#cdcdc1" cellpadding="3" width="80%"> |
<table> |
<tr align="left"><th>Class</th><th>Derived from</th><th>Source file</th></tr> | <tr align="left"><th>Class</th><th>Derived from</th><th>Source file</th></tr> |
<tr><td>cimom</td><td>MessageQueue</td><td>Pegasus/Common/Cimom.h</td></tr> |
<tr><td><div class="exampleInner">cimom</div></td><td>MessageQueue</td><td>Pegasus/Common/Cimom.h</td></tr> |
<tr><td>MessageQueueService</td><td>MessageQueue</td><td>Pegasus/Common/MessageQueueServices.h</td></tr> | <tr><td>MessageQueueService</td><td>MessageQueue</td><td>Pegasus/Common/MessageQueueServices.h</td></tr> |
<tr><td>CimomMessage</td><td>Message</td><td>Pegasus/Common/CimomMessage.h</td></tr> | <tr><td>CimomMessage</td><td>Message</td><td>Pegasus/Common/CimomMessage.h</td></tr> |
<tr><td>AsyncOpNode</td><td>n/a</td><td>Pegasus/Common/AsyncOpNode.h</td></tr> | <tr><td>AsyncOpNode</td><td>n/a</td><td>Pegasus/Common/AsyncOpNode.h</td></tr> |
<tr><td>AsyncDQueue</td><td>unlocked_dq</td><td>Pegasus/Common/DQueue.h</td></tr> | <tr><td>AsyncDQueue</td><td>unlocked_dq</td><td>Pegasus/Common/DQueue.h</td></tr> |
<tr><td>IPC classes</td><td>n/a</td><td>Pegasus/Common/IPC.h</td></tr> | <tr><td>IPC classes</td><td>n/a</td><td>Pegasus/Common/IPC.h</td></tr> |
<tr><td>Threading classes</td><td>n/a</td><td>Pegasus/Common/Thread.h</td></tr> | <tr><td>Threading classes</td><td>n/a</td><td>Pegasus/Common/Thread.h</td></tr> |
|
|
</table> | </table> |
|
|
<br> | <br> |
<br> | <br> |
| |
|
|
The Meta Dispatcher therefore acts as a central message | The Meta Dispatcher therefore acts as a central message |
hub. Services communicate with each other <i>via</i> the Meta | hub. Services communicate with each other <i>via</i> the Meta |
Dispatcher. | Dispatcher. |
|
<div class="exampleOuter"><div class="exampleInner"> |
<pre> | <pre> |
Service A--Message----1----> (block on semaphore) | Service A--Message----1----> (block on semaphore) |
| | | |
|
|
| |
</pre> | </pre> |
| |
|
</div></div> |
The numbered steps above are as follows: | The numbered steps above are as follows: |
<ol> | <ol> |
<li><b>Service A</b> creates a new <code>AsyncMessage</code> and | <li><b>Service A</b> creates a new <code>AsyncMessage</code> and |
|
|
| |
<pre> | <pre> |
| |
Array<Uint32> services; |
Array<Uint32>; services; |
| |
while( services.size() == 0 ) | while( services.size() == 0 ) |
{ | { |
q_client->find_services(String("test server"), 0, 0, &services); |
q_client->find_services(String("test server"), 0, 0, &services); |
pegasus_yield(); | pegasus_yield(); |
} | } |
| |
cout << "found server at " << services[0] << endl; |
cout << "found server at " << services[0] << endl; |
| |
| |
</pre> | </pre> |
|
|
<pre> | <pre> |
_completeAsyncResponse(msg, resp, ASYNC_OPSTATE_COMPLETE, 0); | _completeAsyncResponse(msg, resp, ASYNC_OPSTATE_COMPLETE, 0); |
| |
|
|
} | } |
</pre> | </pre> |
| |
</ol> | </ol> |
</p> | </p> |
| |
|
<h2>Handling CIMMessage and Other Pre-existing Message Classes</h2> |
|
<p> |
|
Existing Messages, including all of the <code>CIMMessage</code> |
|
derivitives, are not configured to be asynchronous |
|
request/reply pairs. They are designed to travel through |
|
Pegasus as events that trigger other processing events, |
|
which is the end of their lifetime. This is not an optimal |
|
use model for asynchronous operation because the |
|
originator of the event does not require nor receive any |
|
completion notification. Further, there is not a |
|
one-to-one correspondence of "event messages" to replies. |
|
</p> |
|
|
|
<h3>AsyncLegacyOperationStart Message</h3> |
|
<p> |
|
The AsyncLegacyOperationStart message is an envelope that |
|
allows a <code>MessageQueueService</code>-based service to |
|
send, receive, and process pre-existing "legacy" |
|
messages. |
|
</p> |
|
<p> |
|
The <code>AsyncLegacyOperationStart</code> Message allows |
|
an asynchronous service to create, package, and send a |
|
"legacy" message to another service or, indirectly, |
|
enqueue it to a non-asynchronous message queue. The code |
|
example below shows how this works: |
|
</p> |
|
|
|
<pre> |
|
|
|
cout << " sending LEGACY to test server" << endl; |
|
|
|
Message *legacy = new Message(0x11100011, |
|
Message::getNextKey()); |
|
|
|
AsyncLegacyOperationStart *req = |
|
new AsyncLegacyOperationStart(q_client->get_next_xid(), |
|
0, |
|
services[0], |
|
legacy, |
|
q_client->getQueueId()); |
|
reply = q_client->SendWait(req); |
|
delete req; |
|
delete reply; |
|
|
|
</pre> |
|
<p> |
|
The code sample above shows a <code>Message</code> object |
|
being embedded inside an |
|
<code>AsyncLegacyOperationStart</code> message and sent |
|
using the <code>SendWait</code>API. |
|
</p> |
|
|
|
<h3>Default Handler for Legacy Messages</h3> |
|
<p> |
|
The <code>MessageQueueService</code> class has a default |
|
handler for legacy messages that extracts the |
|
<code>Message</code> out of its asynchronous "envelope" |
|
and dispatches it using the pre-existing synchronous |
|
interface, as shown below. |
|
</p> |
|
|
|
<pre> |
|
|
|
void MessageQueueService::handle_AsyncLegacyOperationStart( |
|
AsyncLegacyOperationStart *req) |
|
{ |
|
// remove the legacy message from the request and enqueue it to its destination |
|
Uint32 result = async_results::CIM_NAK; |
|
|
|
Message *legacy = req->act; |
|
if ( legacy != 0 ) |
|
{ |
|
MessageQueue* queue = MessageQueue::lookup(req->legacy_destination); |
|
if( queue != 0 ) |
|
{ |
|
// Enqueue the response: |
|
queue->enqueue(legacy); |
|
result = async_results::OK; |
|
} |
|
} |
|
_make_response(req, result); |
|
} |
|
|
|
</pre> |
|
|
|
<p> |
|
The default handler shown above extracts the legacy |
|
message and attempts to <code>enqueue</code> that message |
|
syncrhonously using the pre-existing interface. |
|
</p> |
|
|
|
<h3>Example of Custom Handler for Legacy Messages</h3> |
|
<p> |
|
By implementing the virtual |
|
<code>_handle_async_request</code> method, |
|
a service can choose to implement its own handler for |
|
Legacy messages, as the code below shows: |
|
</p> |
|
|
|
<ol> |
|
|
|
<li><b>Implement the virtual <code>_handle_async_request</code> method.</b></li> |
|
<pre> |
|
|
|
void MessageQueueServer::_handle_async_request(AsyncRequest *req) |
|
{ |
|
if (req->getType() == 0x04100000 ) |
|
{ |
|
req->op->processing(); |
|
handle_test_request(req); |
|
} |
|
else if ( req->getType() == async_messages::CIMSERVICE_STOP ) |
|
{ |
|
req->op->processing(); |
|
handle_CimServiceStop(static_cast<CimServiceStop *>(req)); |
|
} |
|
</pre> |
|
<li><b>Implement a dispatcher for <code>ASYNC_LEGACY_OP_START</code></b></li> |
|
<pre> |
|
else if ( req->getType() == async_messages::ASYNC_LEGACY_OP_START ) |
|
{ |
|
req->op->processing(); |
|
handle_LegacyOpStart(static_cast<AsyncLegacyOperationStart *>(req)); |
|
} |
|
|
|
else |
|
Base::_handle_async_request(req); |
|
} |
|
|
|
</pre> |
|
<li><b>Implement a dispatcher for <code>ASYNC_LEGACY_OP_START</code></b></li> |
|
<pre> |
|
|
|
void MessageQueueServer::handle_LegacyOpStart(AsyncLegacyOperationStart *req) |
|
{ |
|
|
|
Message *legacy = req->act; |
|
cout << " ### handling legacy messages " << endl; |
|
|
|
|
|
AsyncReply *resp = |
|
new AsyncReply(async_messages::REPLY, |
|
req->getKey(), |
|
req->getRouting(), |
|
0, |
|
req->op, |
|
async_results::OK, |
|
req->resp, |
|
req->block); |
|
_completeAsyncResponse(req, resp, ASYNC_OPSTATE_COMPLETE, 0 ); |
|
|
|
if (legacy != 0 ) |
|
cout << " legacy msg type: " << legacy->getType() << endl; |
|
|
|
} |
|
|
|
</pre> |
|
|
|
|
|
</ol> |
| |
<hr> | <hr> |
|
|
|
|
|
|
|
<h2>Sending Messages without Blocking (Async with Callback)</h2> |
|
|
|
<p> |
|
Whenever there is a possibility that the processing of |
|
one message may generate a nested message (message |
|
generated within the handler of a message) it is |
|
necessary to send messages without blocking, and to |
|
receive responses via callback routines. The diagram |
|
below shows the (more complicated) flow of |
|
non-blocking messages. |
|
</p> |
|
<br> |
|
<div class="exampleOuter"><div class="exampleInner"> |
|
<pre> |
|
Service A--Message----1----> |
|
| |
|
. <-----------(return)-+----->-(loop)--->-+ |
|
. | Meta Dispatcher | |
|
. +----<-----<---<---+ |
|
. Message---2-->Service B |
|
. | |
|
. <--Response--3------+ |
|
. | |
|
. +--<--<-----<-----+--(return)----> |
|
. | Meta Dispatcher | |
|
Service A <--Callback--4---+--->-(loop)-->---+ |
|
| ^ |
|
+-------+ |
|
</pre> |
|
</div></div> |
|
|
|
<h3>Test Program</h3> |
|
|
|
<p> |
|
There is a test program that sends and receives |
|
non-blocking messages in |
|
<code>$(PEGASUS_ROOT)/src/Pegasus/Common/tests/async_callback/</code> |
|
</p> |
|
|
|
<h3>SendAsync method</h3> |
|
|
|
<p> |
|
The <code>MessageQueueService</code> class sends |
|
non-blocking messages using the <code>SendAsync</code> |
|
method from <code>MessageQueueService.h</code>. |
|
</p> |
|
<pre> |
|
Boolean <b><font color=#000000>SendAsync</font></b><font color=#990000>(</font>AsyncOpNode <font color=#990000>*</font>op<font color=#990000>,</font> |
|
Uint32 destination<font color=#990000>,</font> |
|
<font color=#009900>void</font> <font color=#990000>(</font><font color=#990000>*</font>callback<font color=#990000>)</font><font color=#990000>(</font>AsyncOpNode <font color=#990000>*</font><font color=#990000>,</font> MessageQueue <font color=#990000>*</font><font color=#990000>,</font> <font color=#009900>void</font> <font color=#990000>*</font><font color=#990000>)</font><font color=#990000>,</font> |
|
MessageQueue <font color=#990000>*</font>callback_q<font color=#990000>,</font> |
|
<font color=#009900>void</font> <font |
|
color=#990000>*</font>callback_ptr<font color=#990000>)</font><font color=#990000>;</font> |
|
</pre> |
|
|
<h2>Class Definitions</h2> | <h2>Class Definitions</h2> |
| |
<h3>cimom (Meta Dispatcher)</h3> | <h3>cimom (Meta Dispatcher)</h3> |
|
|
<address><a href="mailto:mdday@us.ibm.com">Michael Day</a></address> | <address><a href="mailto:mdday@us.ibm.com">Michael Day</a></address> |
<!-- Created: Tue Feb 5 13:21:55 EST 2002 --> | <!-- Created: Tue Feb 5 13:21:55 EST 2002 --> |
<!-- hhmts start --> | <!-- hhmts start --> |
Last modified: Tue Feb 5 18:09:50 EST 2002 |
Last modified: Tue Mar 12 17:48:45 EST 2002 |
<!-- hhmts end --> | <!-- hhmts end --> |
</body> | </body> |
</html> | </html> |