(file) Return to MessageQueueService.html CVS log (file) (dir) Up to [Pegasus] / pegasus / doc

Diff for /pegasus/doc/MessageQueueService.html between version 1.4 and 1.5

version 1.4, 2002/03/13 17:33:36 version 1.5, 2005/05/12 13:40:18
Line 206 
Line 206 
       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">         <div class="exampleOuter"><div class="exampleInner">
       <pre>        <pre>      Service A--Message----1----> (block on semaphore)
       Service A--Message----1----> (block on semaphore)  
                                   |                                   |
                                   |                                   |
                                   Meta Dispatcher|                                   Meta Dispatcher|
Line 271 
Line 270 
  
         <ol>         <ol>
         <li><b>Define the Service Class</b></li>         <li><b>Define the Service Class</b></li>
 <pre>  <pre>// Define our service class
 // Define our service class  
  
 class MessageQueueClient : public MessageQueueService class MessageQueueClient : public MessageQueueService
 { {
Line 317 
Line 315 
  
 </pre> </pre>
       <li><b>Construct the Service</b></li>       <li><b>Construct the Service</b></li>
 <pre>  <pre>// Create our Service
 // Create our Service  
    MessageQueueClient *q_client =    MessageQueueClient *q_client =
           new MessageQueueClient("test client");           new MessageQueueClient("test client");
  
 </pre> </pre>
       <li><b>Register the Service</b></li>       <li><b>Register the Service</b></li>
 <pre>  <pre>// Register our service with the Meta Dispatcher
 // Register our service with the Meta Dispatcher  
    q_client-&gt;register_service("test client",    q_client-&gt;register_service("test client",
                                q_client-&gt;_client_capabilities,                                q_client-&gt;_client_capabilities,
                                q_client-&gt;_client_mask);                                q_client-&gt;_client_mask);
Line 349 
Line 345 
         program:         program:
  
 <pre> <pre>
   
    Array&lt;Uint32&gt;; services;    Array&lt;Uint32&gt;; services;
  
    while( services.size() == 0 )    while( services.size() == 0 )
Line 380 
Line 375 
 <ol> <ol>
 <li><b>Define the Request and Response Message Pair by Inheriting from AsyncMessage.</b></li> <li><b>Define the Request and Response Message Pair by Inheriting from AsyncMessage.</b></li>
 <pre> <pre>
   
 class test_request : public AsyncRequest class test_request : public AsyncRequest
 { {
  
Line 455 
Line 449 
       process the reply.       process the reply.
  
 <pre> <pre>
   
 void MessageQueueClient::send_test_request(char *greeting, Uint32 qid) void MessageQueueClient::send_test_request(char *greeting, Uint32 qid)
 { {
  
 </pre> </pre>
 <li><b>Construct the Request</b></li> <li><b>Construct the Request</b></li>
  
 <pre>  <pre>   test_request *req =
    test_request *req =  
       new test_request(Base::get_next_xid(),       new test_request(Base::get_next_xid(),
                        0,                        0,
                        qid,        // destination queue ID                        qid,        // destination queue ID
Line 474 
Line 466 
  
 <li><b>Send the message using <code>MessageQueueService::SendWait</code></b></li> <li><b>Send the message using <code>MessageQueueService::SendWait</code></b></li>
  
 <pre>  <pre>   AsyncMessage *response = SendWait(req);
    AsyncMessage *response = SendWait(req);  
  
 </pre> </pre>
  
 <li><b>Process the Response.</b></i> <li><b>Process the Response.</b></i>
 <pre>  <pre>   if( response != 0  )
    if( response != 0  )  
    {    {
       msg_count++;       msg_count++;
       delete response;       delete response;
Line 517 
Line 507 
         before inserting the request on the Service's queue.         before inserting the request on the Service's queue.
  
 <pre> <pre>
   
 Boolean MessageQueueServer::messageOK(const Message *msg) Boolean MessageQueueServer::messageOK(const Message *msg)
 { {
    if(msg->getMask() & message_mask::ha_async)    if(msg->getMask() & message_mask::ha_async)
Line 550 
Line 539 
         the message.         the message.
  
 <pre> <pre>
   
 void MessageQueueServer::_handle_incoming_operation(AsyncOpNode *op) void MessageQueueServer::_handle_incoming_operation(AsyncOpNode *op)
 { {
    if ( operation != 0 )    if ( operation != 0 )
Line 576 
Line 564 
         this method. <b>If the Service does not handle the Request it         this method. <b>If the Service does not handle the Request it
           must pass the Request to the Base class by calling <code>Base::_handle_async_request(req)</code></b>           must pass the Request to the Base class by calling <code>Base::_handle_async_request(req)</code></b>
  
 <pre>  <pre>void MessageQueueServer::_handle_async_request(AsyncRequest *req)
 void MessageQueueServer::_handle_async_request(AsyncRequest *req)  
 { {
    if (req->getType() == 0x04100000 )    if (req->getType() == 0x04100000 )
    {    {
Line 603 
Line 590 
           program.           program.
  
 <pre> <pre>
   
    if( msg-&gt;getType() == 0x04100000 )    if( msg-&gt;getType() == 0x04100000 )
    {    {
  
Line 611 
Line 597 
           <ol>           <ol>
             <li><b>Construct the Reply</b></li>             <li><b>Construct the Reply</b></li>
 <pre> <pre>
   
       test_response *resp =       test_response *resp =
          new test_response(msg-&gt;getKey(),          new test_response(msg-&gt;getKey(),
                            msg-&gt;getRouting(),                            msg-&gt;getRouting(),
Line 625 
Line 610 
             <li><b>Complete the Reply</b> by calling the following             <li><b>Complete the Reply</b> by calling the following
             helper routine in the Base class</li>             helper routine in the Base class</li>
  
 <pre>  <pre>      _completeAsyncResponse(msg, resp, ASYNC_OPSTATE_COMPLETE, 0);
       _completeAsyncResponse(msg, resp, ASYNC_OPSTATE_COMPLETE, 0);  
  
    }    }
 </pre> </pre>
Line 663 
Line 647 
           </p>           </p>
  
 <pre> <pre>
   
    cout &lt;&lt; " sending LEGACY to test server" &lt;&lt; endl;    cout &lt;&lt; " sending LEGACY to test server" &lt;&lt; endl;
  
    Message *legacy = new Message(0x11100011,    Message *legacy = new Message(0x11100011,
Line 697 
Line 680 
           </p>           </p>
  
 <pre> <pre>
   
 void MessageQueueService::handle_AsyncLegacyOperationStart( void MessageQueueService::handle_AsyncLegacyOperationStart(
                                                AsyncLegacyOperationStart *req)                                                AsyncLegacyOperationStart *req)
 { {
Line 738 
Line 720 
  
 <li><b>Implement the virtual <code>_handle_async_request</code> method.</b></li> <li><b>Implement the virtual <code>_handle_async_request</code> method.</b></li>
 <pre> <pre>
   
 void MessageQueueServer::_handle_async_request(AsyncRequest *req) void MessageQueueServer::_handle_async_request(AsyncRequest *req)
 { {
    if (req->getType() == 0x04100000 )    if (req->getType() == 0x04100000 )
Line 753 
Line 734 
    }    }
 </pre> </pre>
 <li><b>Implement a dispatcher for <code>ASYNC_LEGACY_OP_START</code></b></li> <li><b>Implement a dispatcher for <code>ASYNC_LEGACY_OP_START</code></b></li>
 <pre>  <pre>   else if ( req->getType() == async_messages::ASYNC_LEGACY_OP_START )
    else if ( req->getType() == async_messages::ASYNC_LEGACY_OP_START )  
    {    {
       req->op->processing();       req->op->processing();
       handle_LegacyOpStart(static_cast<AsyncLegacyOperationStart *>(req));       handle_LegacyOpStart(static_cast<AsyncLegacyOperationStart *>(req));
Line 767 
Line 747 
 </pre> </pre>
 <li><b>Implement a dispatcher for <code>ASYNC_LEGACY_OP_START</code></b></li> <li><b>Implement a dispatcher for <code>ASYNC_LEGACY_OP_START</code></b></li>
 <pre> <pre>
   
 void MessageQueueServer::handle_LegacyOpStart(AsyncLegacyOperationStart *req) void MessageQueueServer::handle_LegacyOpStart(AsyncLegacyOperationStart *req)
 { {
  
Line 812 
Line 791 
               </p>               </p>
 <br> <br>
               <div class="exampleOuter"><div class="exampleInner">               <div class="exampleOuter"><div class="exampleInner">
       <pre>        <pre>      Service A--Message----1---->
       Service A--Message----1---->  
                                |                                |
         . <-----------(return)-+----->-(loop)--->-+         . <-----------(return)-+----->-(loop)--->-+
         .                      |  Meta Dispatcher |         .                      |  Meta Dispatcher |
Line 849 
Line 827 
  
               <div class="exampleOuter"><div class="exampleInner">               <div class="exampleOuter"><div class="exampleInner">
 <pre> <pre>
   
 Boolean <b><font color=#000000>SendAsync</font></b><font color=#990000>(</font>AsyncOpNode <font color=#990000>*</font>op<font color=#990000>,</font> 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>                   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>                   <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>
Line 953 
Line 930 
                 callback function.                 callback function.
               </p>               </p>
               <div class="exampleOuter"><div class="exampleInner">               <div class="exampleOuter"><div class="exampleInner">
                   <pre>                    <pre><b><font color=#0000FF>virtual</font></b> <font color=#009900>void</font> <b><font color=#000000>_handle_async_request</font></b><font color=#990000>(</font>AsyncRequest <font color=#990000>*</font>req<font color=#990000>)</font><font color=#990000>;</font>
 <b><font color=#0000FF>virtual</font></b> <font color=#009900>void</font> <b><font color=#000000>_handle_async_request</font></b><font color=#990000>(</font>AsyncRequest <font color=#990000>*</font>req<font color=#990000>)</font><font color=#990000>;</font>  
                   </pre>                   </pre>
                   <div class="note">                   <div class="note">
                     <var>AsyncRequest *req (In)</var> is the incoming                     <var>AsyncRequest *req (In)</var> is the incoming
Line 1002 
Line 978 
 <div class="exampleOuter"><div class = "exampleInner"> <div class="exampleOuter"><div class = "exampleInner">
  
                   <pre>                   <pre>
   
 <b><font color=#0000FF>static</font></b> <font color=#009900>void</font> <b><font color=#000000>async_callback_function</font></b><font color=#990000>(</font>AsyncOpNode <font color=#990000>*</font>op<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> <b><font color=#0000FF>static</font></b> <font color=#009900>void</font> <b><font color=#000000>async_callback_function</font></b><font color=#990000>(</font>AsyncOpNode <font color=#990000>*</font>op<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>
  
                   </pre>                   </pre>
Line 1029 
Line 1004 
                     message to the <var>op</var> and set the                     message to the <var>op</var> and set the
                     <code>ASYNC_OPSTATE_COMPLETE</code> bit. <br><br>                     <code>ASYNC_OPSTATE_COMPLETE</code> bit. <br><br>
                     <pre>                     <pre>
   
 void my_class::async_callback_function(AsyncOpNode *op, void my_class::async_callback_function(AsyncOpNode *op,
                                        MessageQueue *q,                                        MessageQueue *q,
                                        void *parm)                                        void *parm)
Line 1053 
Line 1027 
  
               <h3>Strategies for Handling Non-Blocking Responses</h3>               <h3>Strategies for Handling Non-Blocking Responses</h3>
               <p>               <p>
                 All of the legacy message handling code in Pegasus is                  All of the legacy message handling code in Pegasus is syncrhonous, meaning that a service can send a request
                 syncrhonous, meaning that a service can send a request  
                 and receive the response in two adjacent lines of                 and receive the response in two adjacent lines of
                 code. Non-blocking messages are different because the                 code. Non-blocking messages are different because the
                 timing and existence of a response message is                 timing and existence of a response message is
                 undetermined.                  undetermined. </p>
               </p>  
               <p>               <p>
                 There are couple of possible strategies for handing                 There are couple of possible strategies for handing
                 non-blocking response messages.                  non-blocking response messages. <ol>
   
                 <ol>  
                   <li>Seperate the request creation and sending code                   <li>Seperate the request creation and sending code
                   from the response handling code into distinct methods.</li>                   from the response handling code into distinct methods.</li>
                 <li>Handle request creation and sending and response                 <li>Handle request creation and sending and response
Line 1078 
Line 1048 
                   <ol>                   <ol>
                     <li>Write the request generation method.                     <li>Write the request generation method.
                   <pre>                   <pre>
   
  void my_class::generate_request(Uint32 destination)  void my_class::generate_request(Uint32 destination)
 { {
    AsyncOpNode *op = get_op();    AsyncOpNode *op = get_op();
Line 1092 
Line 1061 
                       </li>                       </li>
                     <li> Write the request handling method.                     <li> Write the request handling method.
                       <pre>                       <pre>
   
 void my_class::handle_response(AsyncOpNode *op) void my_class::handle_response(AsyncOpNode *op)
 { {
    my_response *res = op-&gt;get_response();    my_response *res = op-&gt;get_response();
Line 1109 
Line 1077 
                     <li> Have your callback method call your response                     <li> Have your callback method call your response
                       method.                       method.
                       <pre>                       <pre>
   
 void my_class:my_callback(AsyncOpNode *op, MessageQueue *queue, void *parm) void my_class:my_callback(AsyncOpNode *op, MessageQueue *queue, void *parm)
 { {
    my_class *myself = static_cast&lt;queue&gt;    my_class *myself = static_cast&lt;queue&gt;
Line 1128 
Line 1095 
               <p>               <p>
                 This strategy requires two separate code blocks within                 This strategy requires two separate code blocks within
                 the request/response method, and conditional execution                 the request/response method, and conditional execution
                 depending on the status of the operation.                  depending on the status of the operation. </p>
               </p>  
               <p>               <p>
                 I think the advantage of this strategy is that it                 I think the advantage of this strategy is that it
                 matches more closely the current<br>                 matches more closely the current<br>
                 <code>handleEnqueue(Message *msg)</code> code                 <code>handleEnqueue(Message *msg)</code> code
                 convention that is in Pegasus.                  convention that is in Pegasus. </p>
               </p>  
  
               <div class="exampleOuter">               <div class="exampleOuter">
                 <div class="exampleInner">                 <div class="exampleInner">
                   <ol>                   <ol>
                     <li>Write the request generation block.                     <li>Write the request generation block.
                   <pre>                   <pre>
   
  void my_class::handle_operation(AsyncOpNode *op)  void my_class::handle_operation(AsyncOpNode *op)
 { {
    if(op == NULL)    if(op == NULL)
Line 1164 
Line 1128 
                       </li>                       </li>
                     <li> Write the request handling block.                     <li> Write the request handling block.
                       <pre>                       <pre>
   
  void my_class::handle_operation(AsyncOpNode *op)  void my_class::handle_operation(AsyncOpNode *op)
 { {
    if(op == NULL)    if(op == NULL)
Line 1194 
Line 1157 
                     <li> Have your callback method call your handler                     <li> Have your callback method call your handler
                       method.                       method.
                       <pre>                       <pre>
   
 void my_class:my_callback(AsyncOpNode *op, MessageQueue *queue, void *parm) void my_class:my_callback(AsyncOpNode *op, MessageQueue *queue, void *parm)
 { {
    my_class *myself = static_cast&lt;queue&gt;    my_class *myself = static_cast&lt;queue&gt;
Line 1214 
Line 1176 
  
 <h3>cimom (Meta Dispatcher)</h3> <h3>cimom (Meta Dispatcher)</h3>
  
 <pre>  <pre><tt>
 <tt>  
 <i><font color=#9A1900>//%///-*-c++-*-/////////////////////////////////////////////////////////////////</font></i> <i><font color=#9A1900>//%///-*-c++-*-/////////////////////////////////////////////////////////////////</font></i>
 <i><font color=#9A1900>//</font></i> <i><font color=#9A1900>//</font></i>
 <i><font color=#9A1900>// Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM,</font></i> <i><font color=#9A1900>// Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM,</font></i>
Line 1395 
Line 1356 
  
 <h3>MessageQueueService</h3> <h3>MessageQueueService</h3>
  
 <pre>  <pre><tt>
 <tt>  
 <i><font color=#9A1900>//%////-*-c++-*-////////////////////////////////////////////////////////////////</font></i> <i><font color=#9A1900>//%////-*-c++-*-////////////////////////////////////////////////////////////////</font></i>
 <i><font color=#9A1900>//</font></i> <i><font color=#9A1900>//</font></i>
 <i><font color=#9A1900>// Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM</font></i> <i><font color=#9A1900>// Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM</font></i>
Line 1550 
Line 1510 
  
 <h3>Asynchronous Messages</h3> <h3>Asynchronous Messages</h3>
  
 <pre>  <pre><tt>
 <tt>  <font color="#9A1900">//%2005////////////////////////////////////////////////////////////////////////
 <i><font color=#9A1900>//%///-*-c++-*-/////////////////////////////////////////////////////////////////</font></i>  //
 <i><font color=#9A1900>//</font></i>  // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
 <i><font color=#9A1900>// Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM,</font></i>  // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
 <i><font color=#9A1900>// The Open Group, Tivoli Systems</font></i>  // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
 <i><font color=#9A1900>//</font></i>  // IBM Corp.; EMC Corporation, The Open Group.
 <i><font color=#9A1900>// Permission is hereby granted, free of charge, to any person obtaining a copy</font></i>  // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
 <i><font color=#9A1900>// of this software and associated documentation files (the "Software"), to</font></i>  // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
 <i><font color=#9A1900>// deal in the Software without restriction, including without limitation the</font></i>  // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 <i><font color=#9A1900>// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or</font></i>  // EMC Corporation; VERITAS Software Corporation; The Open Group.
 <i><font color=#9A1900>// sell copies of the Software, and to permit persons to whom the Software is</font></i>  //
 <i><font color=#9A1900>// furnished to do so, subject to the following conditions:</font></i>  // Permission is hereby granted, free of charge, to any person obtaining a copy
 <i><font color=#9A1900>//</font></i>  // of this software and associated documentation files (the &quot;Software&quot;), to
 <i><font color=#9A1900>// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN</font></i>  // deal in the Software without restriction, including without limitation the
 <i><font color=#9A1900>// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED</font></i>  // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 <i><font color=#9A1900>// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT</font></i>  // sell copies of the Software, and to permit persons to whom the Software is
 <i><font color=#9A1900>// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR</font></i>  // furnished to do so, subject to the following conditions:
 <i><font color=#9A1900>// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT</font></i>  //
 <i><font color=#9A1900>// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN</font></i>  // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 <i><font color=#9A1900>// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION</font></i>  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 <i><font color=#9A1900>// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</font></i>  // &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 <i><font color=#9A1900>//</font></i>  // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 <i><font color=#9A1900>//==============================================================================</font></i>  // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 <i><font color=#9A1900>//</font></i>  // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   //
   //==============================================================================
   </font><i><font color=#9A1900>//</font></i>
 <i><font color=#9A1900>// Author: Mike Day (mdday@us.ibm.com)</font></i> <i><font color=#9A1900>// Author: Mike Day (mdday@us.ibm.com)</font></i>
 <i><font color=#9A1900>//</font></i> <i><font color=#9A1900>//</font></i>
 <i><font color=#9A1900>// Modified By:</font></i> <i><font color=#9A1900>// Modified By:</font></i>
Line 2082 
Line 2047 
  
 <h3>AsyncOpNode</h3> <h3>AsyncOpNode</h3>
  
 <pre>  <pre><tt>
 <tt>  
 <i><font color=#9A1900>//%///////////-*-c++-*-//////////////////////////////////////////////////////</font></i> <i><font color=#9A1900>//%///////////-*-c++-*-//////////////////////////////////////////////////////</font></i>
 <i><font color=#9A1900>//</font></i> <i><font color=#9A1900>//</font></i>
 <i><font color=#9A1900>// Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM</font></i> <i><font color=#9A1900>// Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM</font></i>
Line 2598 
Line 2562 
 <!-- hhmts start --> <!-- hhmts start -->
 Last modified: Wed Mar 13 12:26:56 EST 2002 Last modified: Wed Mar 13 12:26:56 EST 2002
 <!-- hhmts end --> <!-- hhmts end -->
   </body>    </body></html>
 </html>  
   
   


Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2