Changes to attempt to silence bcc64x
[ACE_TAO.git] / TAO / docs / rtcorba / features.html
blobc1a16aa8f28740258d723ad9c00adc8d318b5f1c
1 <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
5 <meta name="GENERATOR" content="Mozilla/4.77 [en] (Windows NT 5.0; U) [Netscape]">
6 <title>TAO Real-Time CORBA Features Documentation</title>
7 <!-- -->
8 </head>
9 <body>
11 <center>
12 <h3>
13 Features Documentation</h3></center>
14 This page is not a tutorial on Real-Time CORBA, but is rather a supplement
15 to the specification, covering all implementation-specific details. Sample
16 code exercising RTCORBA features can be found in
17 <tt>$TAO/tests/RTCORBA/</tt>.
18 We hope to have tutorial-style examples available in the near future.
19 <h3>
20 <a NAME="enabling"></a>Enabling Real-Time CORBA features</h3>
21 In order to use features from the Real-Time CORBA 1.0 specification in
22 TAO, a RT-CORBA client application must link with the RTCORBA library;
23 a RT-CORBA server application must link with the RTCORBA library and the
24 RTPortableServer libraries. Since some features in RT-CORBA depend on the
25 messaging specification, all code must be compiled with <tt>TAO_HAS_CORBA_MESSAGING</tt>
26 set to
27 <tt>1</tt>. This macros are defined in
28 <tt>$TAO/tao/orbconf.h</tt>
29 <p>By default, both Real-Time CORBA and Messaging are enabled in TAO unless
30 Minimum CORBA support is turned on, <i>i.e.</i>,
31 <tt>TAO_HAS_MINIMUM_CORBA</tt>
32 is set to <tt>1</tt>.
33 <h3>
34 <a NAME="mappings"></a>Priority Mappings</h3>
35 TAO provides three Priority Mappings: Direct, Linear, and Continuous. If
36 no mapping is specified, Direct Priority Mappings will be used. Note that
37 Continuous was previously referred to as Direct.
38 <dl>
39 <dt>
40 <b>Direct</b></dt>
42 <dd>
43 Maps CORBA priorities directly to native priorities.</dd>
45 <dt>
46 <b>Linear</b></dt>
48 <dd>
49 Maps each individual native priority to a contiguous range of CORBA priorities,
50 so that the complete CORBA priority range is used up for the mapping. See
51 <tt>$TAO_ROOT/tao/RTCORBA/Linear_Priority_Mapping.cpp
52 </tt>for
53 more details.</dd>
55 <dt>
56 <b>Continuous</b></dt>
58 <dd>
59 Maps the first <i>n</i> CORBA priorities to the range of native priorities,
60 where <i>n</i> is the number of native priorities. The lowest native priority
61 is mapped to CORBA priority 0, next higher native priority is mapped to
62 CORBA priority 1, and so on. Since in all the operating systems where TAO
63 is supported the native priority set contains less than 32767 priorities,
64 part of the CORBA priority range is left unused. Consider NT Direct priority
65 mapping as an example. NT native priorities -15 -2 -1 0 1 2 15 are mapped
66 to CORBA priorities 0 1 2 3 4 5 6, respectively, and the rest of the CORBA
67 priority range is not used.</dd>
68 </dl>
69 Priority mappings implement the rules for mapping CORBA priority range
70 (from 0 to 32767) into the native OS priority range and vice versa. However,
71 in some operating systems, the the native OS priority range depends on
72 the scheduling policy being used. That's why when specifying a priority
73 mapping, scheduling policy must be specified as well. Below, we describe
74 how to configure TAO to use a particular priority mapping and scheduling
75 policy. Note, in some operating systems super user privileges are required
76 for use of some of the scheduling policies.
77 <p>By default TAO uses Direct priority mapping and
78 <tt>SCHED_OTHER</tt>
79 scheduling policy. There are two ways for an application to override these
80 settings:
81 <ol>
82 <li>
83 <tt>svc.conf</tt> file can be used to select a mapping and a scheduling
84 policy the ORB will use. (This method does not allow the specification
85 of user-defined mappings.) Config file should contain the following options:</li>
87 <br>&nbsp;
88 <p>&nbsp;
89 <br>&nbsp;
90 <br>&nbsp;
91 <p><tt>static RT_ORB_Loader "-ORBPriorityMapping
92 <i>mapping_type</i> -ORBSchedPolicy
93 <i>sched_policy</i>"</tt>
94 <p>where valid values for <i>mapping_type</i> are <tt>continuous</tt>, <tt>linear</tt> and <tt>direct,</tt>
95 and<i> </i>valid values for <i>sched_policy</i> are <tt>SCHED_OTHER</tt>,
96 <tt>SCHED_FIFO</tt>
97 and <tt>SCHED_RR</tt>.
98 <li>
99 <i>TAO::PriorityMappingManager</i> can be used to 1) override the default
100 priority mapping and scheduling policy with another ORB-defined mapping/scheduling
101 policy combination, 2) install a user-defined priority mapping, 3) obtain
102 a reference to the priority mapping object used by the ORB. Code excerpts
103 below demonstrate how to perform each of these tasks.</li>
105 <br>&nbsp;
106 <p>&nbsp;
107 <br>&nbsp;
108 <br>&nbsp;
109 <p>Obtaining Priority Mapping Manager:
110 <br><tt>object = orb->resolve_initial_references ("PriorityMappingManager");</tt>
111 <br><tt>TAO::PriorityMappingManager_var mapping_manager =</tt>
112 <br><tt>TAO::PriorityMappingManager::_narrow (object.in ());</tt>
113 <p>Overriding priority mapping/policy in effect with another ORB-defined
114 mapping/policy combination:
115 <br><tt>#include "tao/RTCORBA/Continuous_Priority_Mapping.h"</tt>
116 <br><tt>#include "tao/RTCORBA/Linear_Priority_Mapping.h"</tt>
117 <br><tt>#include "tao/RTCORBA/Direct_Priority_Mapping.h"</tt>
118 <br><tt>...</tt>
119 <p><tt>RTCORBA::PriorityMapping *pm =</tt>
120 <br><tt>new TAO_Continuous_Priority_Mapping (policy);</tt>
121 <br>or
122 <br><tt>new TAO_Linear_Priority_Mapping (policy);</tt>
123 <br>or
124 <br><tt>new TAO_Direct_Priority_Mapping (policy);</tt>
125 <br><tt>mapping_manager->mapping (pm);</tt>
126 <br><tt>...</tt>
127 <br>where policy is <tt>SCHED_OTHER, SCHED_FIFO</tt> or
128 <tt>SCHED_RR.</tt>
129 Priority Mapping Manager takes the ownership of the priority mapping object.
130 <p>Overriding the default with user-defined priority mapping:
131 <br><tt>My_Mapping *foo = new My_Mapping;</tt>
132 <br><tt>mapping_manager->mapping (foo);</tt>
133 <br>where <i>My_Mapping</i> must inherit from <i>RTCORBA::PriorityMapping</i>
134 (a typedef for <i>TAO_Priority_Mapping</i> class) located in
135 <tt>$TAO/tao/Priority_Mapping.h</tt>
136 <p>Obtaining a pointer to the priority mapping object being used by the
137 ORB:
138 <br><tt>RTCORBA::PriorityMapping *pm =</tt>
139 <br><tt>mapping_manager->mapping ();</tt>
140 <br>Mapping manager retains the ownership of the priority mapping object.</ol>
142 <h3>
143 <a NAME="defaults"></a>ORB Default Policies</h3>
144 Real-Time CORBA 1.0 does not specify ORB defaults for the policies it defines,
145 leaving it up to implementations. Below is a summary TAO defaults.
146 <br>&nbsp;
147 <table BORDER CELLPADDING=7 WIDTH="100%" >
148 <tr>
149 <td ALIGN=CENTER WIDTH="31%"><b>Policy</b></td>
151 <td ALIGN=CENTER WIDTH="69%"><b>Default</b></td>
152 </tr>
154 <tr>
155 <td WIDTH="31%"><i>ServerProtocolPolicy</i></td>
157 <td WIDTH="69%">All protocols that are loaded by the ORB by default (e.g.,
158 IIOP) and any explicitly specified by the user (e.g., SHMIOP), in the order
159 they were loaded, with their default properties. See <a href="#protocols">Protocol
160 Policies</a> section for more details.</td>
161 </tr>
163 <tr>
164 <td WIDTH="31%"><i>ClientProtocolPolicy</i></td>
166 <td WIDTH="69%">None</td>
167 </tr>
169 <tr>
170 <td WIDTH="31%"><i>ThreadpoolPolicy</i></td>
172 <td WIDTH="69%">None. If no ThreadpoolPolicy policy is specified during
173 POA creation, the default thread-pool will be used for that POA.</td>
174 </tr>
176 <tr>
177 <td WIDTH="31%"><i>PriorityModelPolicy</i></td>
179 <td WIDTH="69%">None</td>
180 </tr>
182 <tr>
183 <td WIDTH="31%"><i>PriorityBandedConnectionPolicy</i></td>
185 <td WIDTH="69%">None</td>
186 </tr>
188 <tr>
189 <td WIDTH="31%"><i>PrivateConnectionPolicy</i></td>
191 <td WIDTH="69%">None</td>
192 </tr>
194 <tr>
195 <td WIDTH="31%">Priority Mapping</td>
197 <td WIDTH="69%">Direct mapping with <tt>SCHED_OTHER</tt> scheduling policy.
198 See <a href="#mappings">Priority Mappings</a> section for more details.</td>
199 </tr>
200 </table>
202 <h3>
203 <a NAME="threadpools"></a>Threadpools</h3>
205 <ul>
206 <li>
207 ThreadPools are now fully supported. Endpoint priorities are no longer
208 supported.</li>
209 <li>
210 By default dynamic RTCorba threads live forever after they are created.
211 When using the <code>RTORBDynamicThreadIdleTimeout</code> from the
212 <code>RT_ORB_Loader</code> it
213 can be specified that the dynamic threads should end after a given
214 idle time. Timeout must be specified in microseconds, 0 means the threads
215 will stay alive forever. With <code>RTORBDynamicThreadRunTime</code> you
216 specify the amount of time after a dynamic thread ends itself.
217 </ul>
219 <h3>
220 <a NAME="valid_configurations"></a>Priority Policies</h3>
221 The table below lists all possible configurations of policies involving
222 priorities, and summarizes the semantics of each configuration.
223 <br>&nbsp;
224 <table BORDER CELLPADDING=4 WIDTH="100%" >
225 <tr>
226 <td ALIGN=CENTER WIDTH="33%"><b>Configuration</b></td>
228 <td ALIGN=CENTER WIDTH="33%"><b>Valid values</b></td>
230 <td ALIGN=CENTER WIDTH="34%"><b>Semantics</b></td>
231 </tr>
233 <tr>
234 <td WIDTH="33%">Threadpool with lanes,
235 <br>no <i>PriorityModelPolicy</i>,
236 <br>no <i>PriorityBandedConnectionPolicy</i></td>
238 <td WIDTH="33%">Invalid.</td>
240 <td WIDTH="34%">None.</td>
241 </tr>
243 <tr>
244 <td WIDTH="33%">Threadpool with lanes +
245 <br><tt>SERVER_DECLARED</tt> model,
246 <br>no <i>PriorityBandedConnectionPolicy</i></td>
248 <td WIDTH="33%"><i>Server_priority</i> attribute of the <i>PriorityModelPolicy</i>
249 must be equal to the priority of one of the threadpool lanes. (Same goes
250 for priorities of all the objects registered with the target POA).</td>
252 <td WIDTH="34%">All processing is done at the servant's priority.</td>
253 </tr>
255 <tr>
256 <td WIDTH="33%">Threadpool with lanes +
257 <br><tt>CLIENT_PROPAGATED</tt> model,
258 <br>no <i>PriorityBandedConnectionPolicy</i></td>
260 <td WIDTH="33%">Priority of the invoking client thread must be equal to
261 the priority of one of the threadpool lanes.</td>
263 <td WIDTH="34%">All processing is done at the client-propagated priority.</td>
264 </tr>
266 <tr>
267 <td WIDTH="33%">Threadpool with lanes +
268 <br><i>PriorityBandedConnectionPolicy</i>,
269 <br>no <i>PriorityModelPolicy</i></td>
271 <td WIDTH="33%">Invalid.</td>
273 <td WIDTH="34%">None.</td>
274 </tr>
276 <tr>
277 <td WIDTH="33%">Threadpool with lanes +
278 <br><tt>SERVER_DECLARED</tt> model +
279 <br><i>PriorityBandedConnectionPolicy</i></td>
281 <td WIDTH="33%"><i>Server_priority</i> attribute of the <i>PriorityModelPolicy</i>
282 must be equal to the priority of one of the threadpool lanes. (Same goes
283 for priorities of all the objects registered with the target POA). In addition,
284 each of the priority bands must cover at least one of the threadpool lane
285 priorities.</td>
287 <td WIDTH="34%">All processing is done at the servant's priority.</td>
288 </tr>
290 <tr>
291 <td WIDTH="33%">Threadpool with lanes +
292 <br><tt>CLIENT_PROPAGATED</tt> model +
293 <br><i>PriorityBandedConnectionPolicy</i></td>
295 <td WIDTH="33%">Priority of the invoking client thread must fall into one
296 of the priority bands. In addition, each of the priority bands must cover
297 at least one of the threadpool lane priorities.</td>
299 <td WIDTH="34%">All processing is done at the threadpool lane priority
300 which matches the priority band used by the client.</td>
301 </tr>
303 <tr>
304 <td WIDTH="33%">Threadpool without lanes,
305 <br>no <i>PriorityModelPolicy</i>,
306 <br>no <i>PriorityBandedConnectionPolicy</i></td>
308 <td WIDTH="33%">All valid CORBA priorities.</td>
310 <td WIDTH="34%">All processing is done at the threadpool's default priority.</td>
311 </tr>
313 <tr>
314 <td WIDTH="33%">Threadpool without lanes +
315 <br><tt>SERVER_DECLARED</tt> model,
316 <br>no <i>PriorityBandedConnectionPolicy</i></td>
318 <td WIDTH="33%">All valid CORBA priorities.</td>
320 <td WIDTH="34%">Request I/O and demultiplexing processing is done at the
321 threadpool's default priority. Application level processing is done at
322 the servant's priority.</td>
323 </tr>
325 <tr>
326 <td WIDTH="33%">Threadpool without lanes + <tt>CLIENT_PROPAGATED</tt> model,
327 <br>no <i>PriorityBandedConnectionPolicy</i></td>
329 <td WIDTH="33%">All valid CORBA priorities.</td>
331 <td WIDTH="34%">Request I/O and demultiplexing processing is done at the
332 threadpool's default priority. Application level processing is done at
333 the client-propagated priority.</td>
334 </tr>
336 <tr>
337 <td WIDTH="33%">Threadpool without lanes +
338 <br><i>PriorityBandedConnectionPolicy</i>,
339 <br>no <i>PriorityModelPolicy</i></td>
341 <td WIDTH="33%">Invalid.</td>
343 <td WIDTH="34%">None.</td>
344 </tr>
346 <tr>
347 <td WIDTH="33%">Threadpool without lanes +
348 <br><tt>SERVER_DECLARED</tt> model +
349 <br><i>PriorityBandedConnectionPolicy</i></td>
351 <td WIDTH="33%"><i>Server_priority</i> attribute of the <i>PriorityModelPolicy</i>
352 must fall into one of the priority bands. (Same goes for priorities of
353 all the objects registered with the target POA).</td>
355 <td WIDTH="34%">Request I/O and demultiplexing processing is done at the
356 threadpool's default priority. Application level processing is done at
357 the servant's priority. In this case, <i>PriorityBandedConnectionPolicy</i>
358 is used to restrict the allowed priority values for the servant.</td>
359 </tr>
361 <tr>
362 <td WIDTH="33%">Threadpool without lanes +
363 <br><tt>CLIENT_PROPAGATED</tt> model +
364 <br><i>PriorityBandedConnectionPolicy</i></td>
366 <td WIDTH="33%">Priority of the invoking client thread must fall into one
367 of the priority bands.</td>
369 <td WIDTH="34%">Request I/O and demultiplexing processing is done at the
370 threadpool's default priority. Application level processing is done at
371 the client-propagated priority. In this case, <i>PriorityBandedConnectionPolicy</i>
372 is used to restrict the allowed priority values for the client.</td>
373 </tr>
374 </table>
376 <h3>
377 <a NAME="explicit_bind"></a>Explicit Binding</h3>
378 <tt>Object::_validate_connection ()</tt> method establishes a connection,
379 if one doesn't already exist, and verifies policy overrides for the <i>invoking
380 thread/ its priority/ target object</i> combination. To establish all connections
381 ahead of time, application must call <tt>_validate_connection ()</tt> for
382 <b>all</b><i>thread/
383 priority/ object</i> combinations that will be used.
384 <h3>
385 <a NAME="protocols"></a>Protocol Policies</h3>
386 In addition to <i>TCPProtocolProperties</i> defined by the Real-Time CORBA
387 specification, TAO provides configurable properties for each protocol it
388 supports. Below is a summary of all protocol properties available in TAO.
389 <ul>
390 <li>
391 <b>IIOP</b></li>
393 <br>Protocol <i>ProfileId</i>: 0
394 <br>Transport properties interface name: <i>RTCORBA::TCPProtocolProperties</i>
395 (standard)
396 <br>Implementation class name: <i>TAO_TCP_Properties</i>
397 <table BORDER CELLPADDING=4 HEIGHT="150" >
398 <tr>
399 <td ALIGN=CENTER HEIGHT="19"><b>Protocol Properties Attribute</b></td>
401 <td ALIGN=CENTER HEIGHT="19"><b>Default Value</b></td>
402 </tr>
404 <tr>
405 <td HEIGHT="19">long <i>send_buffer_size</i></td>
407 <td ALIGN=LEFT HEIGHT="19"><tt>ACE_DEFAULT_MAX_SOCKET_BUFSIZ</tt></td>
408 </tr>
410 <tr>
411 <td HEIGHT="19">long <i>recv_buffer_size</i></td>
413 <td ALIGN=LEFT HEIGHT="19"><tt>ACE_DEFAULT_MAX_SOCKET_BUFSIZ</tt></td>
414 </tr>
416 <tr>
417 <td HEIGHT="19">boolean <i>keep_alive</i> (not yet supported)</td>
419 <td ALIGN=LEFT HEIGHT="19"><tt>1</tt></td>
420 </tr>
422 <tr>
423 <td HEIGHT="19">boolean <i>dont_route</i> (not yet supported)</td>
425 <td ALIGN=LEFT HEIGHT="19"><tt>0</tt></td>
426 </tr>
428 <tr>
429 <td HEIGHT="19">boolean <i>no_delay</i></td>
431 <td ALIGN=LEFT HEIGHT="19"><tt>1</tt></td>
432 </tr>
433 </table>
435 <li>
436 <b>UIOP</b></li>
438 <br>Protocol <i>ProfileId</i>: 0x54414f00U
439 <br>Transport properties interface name: <i>RTCORBA::UnixDomainProtocolProperties</i>
440 (TAO-specific)
441 <br>Implementation class name: <i>TAO_Unix_Domain_Properties</i>
442 <table BORDER CELLPADDING=4 >
443 <tr>
444 <td ALIGN=CENTER><b>Protocol Properties Attribute</b></td>
446 <td ALIGN=CENTER><b>Default Value</b></td>
447 </tr>
449 <tr>
450 <td>long <i>send_buffer_size</i></td>
452 <td><tt>ACE_DEFAULT_MAX_SOCKET_BUFSIZ</tt></td>
453 </tr>
455 <tr>
456 <td>long <i>recv_buffer_size</i></td>
458 <td><tt>ACE_DEFAULT_MAX_SOCKET_BUFSIZ</tt></td>
459 </tr>
460 </table>
462 <li>
463 <b>SHMIOP</b></li>
465 <br>Protocol <i>ProfileId</i>: 0x54414f02U
466 <br>Transport properties interface name: <i>RTCORBA::SharedMemoryProtocolProperties</i>
467 (TAO-specific)
468 <br>Implementation class name: <i>TAO_SMEM_Properties</i>
469 <table BORDER CELLPADDING=4 >
470 <tr>
471 <td ALIGN=CENTER><b>Protocol Properties Attribute</b></td>
473 <td ALIGN=CENTER><b>Default Value</b></td>
474 </tr>
476 <tr>
477 <td>long <i>preallocate_buffer_size</i></td>
479 <td>not yet supported</td>
480 </tr>
482 <tr>
483 <td>string <i>mmap_filename</i></td>
485 <td>not yet supported</td>
486 </tr>
488 <tr>
489 <td>string <i>mmap_lockname</i></td>
491 <td>not yet supported</td>
492 </tr>
493 </table>
494 </ul>
495 Real-Time CORBA 1.0 does not define how protocol properties are created.
496 <i>TAO_Protocol_Factory</i>
497 class can be used to create default <i>ProtocolProperties</i> for a particular
498 protocol given its <i>ProfileId</i>:
499 <p><tt>class TAO_Protocol_Properties_Factory</tt>
500 <br><tt>{</tt>
501 <br><tt>public:</tt>
502 <p><tt>static RTCORBA::ProtocolProperties*</tt>
503 <br><tt>create_transport_protocol_property (IOP::ProfileId id);</tt>
504 <p><tt>static RTCORBA::ProtocolProperties*</tt>
505 <br><tt>create_orb_protocol_property (IOP::ProfileId id);</tt>
506 <br><tt>};</tt>
507 <p>Alternatively, concrete <i>ProtocolProperties</i> implementation classes
508 can be instantiated directly as needed.
509 <p>The table below summarizes how protocol policies overrides affect protocol
510 selection and configuration in TAO.
511 <br>&nbsp;
512 <table BORDER CELLPADDING=4 >
513 <tr>
514 <td ALIGN=CENTER><b>Policy</b></td>
516 <td ALIGN=CENTER><b>ORB default</b></td>
518 <td ALIGN=CENTER><b>Override levels that have impact on protocol selection</b></td>
520 <td ALIGN=CENTER><b>Override levels that have impact on protocol configuration</b></td>
521 </tr>
523 <tr>
524 <td><i>ServerProtocolPolicy</i></td>
526 <td>All protocols loaded into the ORB, in the order they were loaded.</td>
528 <td>ORB
529 <br>POA</td>
531 <td>ORB
532 <br>(If no protocol properties are specified at the ORB level, default
533 protocol configurations are used.)</td>
534 </tr>
536 <tr>
537 <td><i>ClientProtocolPolicy</i></td>
539 <td>None</td>
541 <td>ORB
542 <br>Current
543 <br>Object</td>
545 <td>ORB
546 <br>(If no protocol properties are specified at the ORB level, default
547 protocol configurations are used.)</td>
548 </tr>
549 </table>
551 <p>NOTE: <tt>-ORBSndSock</tt> and <tt>-ORBRcvSock</tt> ORB options have
552 no effect when RTCORBA is enabled.
553 <p>Protocol policies do not depend on any other Real-Time CORBA features
554 and can be used alone. In fact, we plan to make protocol policies available
555 outside RTCORBA, and better integrate them with the Pluggable Protocols
556 framework in the near future.
557 <br>
558 <hr>
559 <h3>
560 <a NAME="diffserv"></a>Diffserv Support</h3>
562 <p>Though the RT-CORBA specification details the real-time ORB, thread
563 priorities, and application scheduling requirements, it is less
564 explicit about the communication transport and the underlying
565 network priorities. Our research involved using Differentiated Services
566 technology to prioritize the RT-CORBA traffic in the network. This
567 effort required two essential enhancements to the TAO ORB. First, we
568 provided an efficient and flexible way of setting the DSCP codepoints
569 in the data packets, which is done by extending the ORB protocol
570 properties. DSCP codepoints can dynamically change, based on many
571 factors like QoS feedback received from external QoS monitoring
572 resources or even a change in the application policy. Second, we
573 provide a mechanism to map the RT-CORBA priorities to the Diff-Serv
574 network priorities. The detials of the implementation follows.
575 <dl>
576 <dt>
577 <b>Modifications to RTCORBA.pidl</b></dt>
579 <br>&nbsp;
580 <ul>
581 <li>
582 <b>TCP Protocol Properties extension</b></li>
584 <br>&nbsp;
585 <dd>
586 The TCP protocol properties interface was extended to add a flag, enable_network_priority.
587 When this flag is set to 1 the RTCORBA priority is mapped to network priority
588 (diffserv codepoint - DSCP) and this priority is set on the GIOP requests
589 and replies. When the flag is not set no network priorities are set on
590 the GIOP requests and replies and are hence best effort.</dd>
591 &nbsp;
592 <p><tt>local interface TCPProtocolProperties : ProtocolProperties</tt>
593 <br><tt>{</tt>
594 <br><tt>attribute long send_buffer_size;</tt>
595 <br><tt>attribute long recv_buffer_size;</tt>
596 <br><tt>attribute boolean keep_alive;</tt>
597 <br><tt>attribute boolean dont_route;</tt>
598 <br><tt>attribute boolean no_delay;</tt>
599 <br><tt>attribute boolean enable_network_priority;</tt>
600 <br><tt>};</tt>
601 <br>&nbsp;
602 <li>
603 <b>Network Priority Mapping Interfaces</b></li>
605 <dd>
606 <p>Support was added for mapping RTCORBA priority to Network Priority. It
607 is similar to the RTCORBA to native thread priority mapping.</dd>
609 <p><tt>typedef long NetworkPriority;</tt>
610 <br><tt>native NetworkPriorityMapping;</tt></ul><br>
612 <dt>
613 <b>Usage</b></dt>
615 <br>&nbsp;
616 <ul>
617 <li>
618 <b>Client - Setting DSCP on the GIOP Requests</b></li>
620 <br><br>
621 <dd>
622 1. <i>Create TCP protocol properties</i> - The enable_network_priority
623 flag implies the setting/unsetting of the network priority.</dd>
625 <p><tt>RTCORBA::TCPProtocolProperties_var tcp_properties =</tt>
626 <br><tt>&nbsp;&nbsp;&nbsp; rt_orb->create_tcp_protocol_properties (send_buffer_size,</tt>
627 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
628 recv_buffer_size,</tt>
629 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
630 1, //keep alive</tt>
631 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
632 0, //don't route</tt>
633 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
634 1, //no delay</tt>
635 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
636 enable_network_priority);</tt>
637 <p>2. <i>Create TCP Protocol Properties Policy</i>
638 <p><tt>RTCORBA::ProtocolList protocols;</tt>
639 <br><tt>protocols.length (1);</tt>
640 <br><tt>protocols[0].protocol_type = 0; //IIOP</tt>
641 <br><tt>protocols[0].transport_protocol_properties =</tt>
642 <br><tt>&nbsp;&nbsp;&nbsp; RTCORBA::ProtocolProperties::_duplicate (tcp_properties.in
643 ());</tt>
644 <br><tt>protocols[0].orb_protocol_properties =</tt>
645 <br><tt>&nbsp;&nbsp;&nbsp; RTCORBA::ProtocolProperties::_nil ();</tt>
646 <p><tt>CORBA::PolicyList policy_list;</tt>
647 <br><tt>policy_list.length (1);</tt>
648 <br><tt>policy_list[0] =</tt>
649 <br><tt>&nbsp;&nbsp;&nbsp; rt_orb->create_client_protocol_policy (protocols);</tt>
650 <p>3.<i> Set TCP Protocol Properties Policy</i>
651 <p><b>ORB Level</b> - This implies that the tcp protocol properties set
652 will apply to every invocation made with this ORB.
653 <p><tt>CORBA::Object_var object =</tt>
654 <br><tt>orb->resolve_initial_references ("ORBPolicyManager");</tt>
655 <br><tt>CORBA::PolicyManager_var policy_manager =</tt>
656 <br><tt>&nbsp;&nbsp;&nbsp; CORBA::PolicyManager::_narrow (object.in ());</tt>
657 <br><tt>policy_manager->set_policy_overrides (policy_list,</tt>
658 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
659 CORBA::SET_OVERRIDE);</tt>
660 <p><b>THREAD Level</b> - This implies that the tcp protocol properties
661 set will apply to all the invocations made in the corresponding thread
662 only. All other invocations will have the TCP protocol properties set at
663 the ORB level.
664 <p>orb->orb_core ()->policy_current ().set_policy_overrides (policy_list,
665 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
666 CORBA::SET_OVERRIDE);
667 <p><b>OBJECT Level</b> - This implies that the tcp protocol properties
668 set will apply to the invocations made on the corresponding object only.
669 <p><tt>CORBA::Object_var object = server->_set_policy_overrides (policy_list,</tt>
670 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
671 CORBA::SET_OVERRIDE);</tt>
672 <p><tt>server = Test::_narrow (object.in ()); //server is the CORBA Object</tt>
673 <p>The above steps can be applied repeatedly to create and set TCP protocol
674 properties on the client to enable/disable network priority on the GIOP
675 requests. Since the TCP protocol properties are updated per invocation
676 the most recently set policy will apply.
677 <br>&nbsp;
678 <li>
679 <b>Server - Setting DSCP on the GIOP Replies</b></li>
681 <br>&nbsp;
682 <dd>
683 1. <i>Create the TCP protocol properties</i> - The enable_network_priority
684 flag implies the setting/unsetting of the network priority.</dd>
686 <p><tt>RTCORBA::TCPProtocolProperties_var tcp_properties =</tt>
687 <br><tt>&nbsp;&nbsp;&nbsp; rt_orb->create_tcp_protocol_properties (send_buffer_size,</tt>
688 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
689 recv_buffer_size,</tt>
690 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
691 1, //keep alive</tt>
692 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
693 0, //don't route</tt>
694 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
695 1, //no delay</tt>
696 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
697 enable_network_priority);</tt>
698 <p>2. <i>Create TCP Protocol Properties Policy</i>
699 <p><tt>RTCORBA::ProtocolList protocols;</tt>
700 <br><tt>protocols.length (1);</tt>
701 <br><tt>protocols[0].protocol_type = 0; //IIOP</tt>
702 <br><tt>protocols[0].transport_protocol_properties =</tt>
703 <br><tt>&nbsp;&nbsp;&nbsp; RTCORBA::ProtocolProperties::_duplicate (tcp_properties.in
704 ());</tt>
705 <br><tt>protocols[0].orb_protocol_properties =</tt>
706 <br><tt>&nbsp;&nbsp;&nbsp; RTCORBA::ProtocolProperties::_nil ();</tt>
707 <br>&nbsp;
708 <p><tt>CORBA::PolicyList policy_list;</tt>
709 <br><tt>policy_list.length (1);</tt>
710 <br><tt>policy_list[0] =</tt>
711 <br><tt>&nbsp;&nbsp;&nbsp; rt_orb->create_server_protocol_policy (protocols);</tt>
712 <p>3. <i>Create POA with Diffserv enabled</i>
713 <p><tt>CORBA::PolicyList poa_policy_list;</tt>
714 <br><tt>poa_policy_list.length (1);</tt>
715 <br><tt>poa_policy_list [0] =</tt>
716 <br><tt>&nbsp;&nbsp;&nbsp; rt_orb->create_server_protocol_policy (protocols);</tt>
717 <p><tt>PortableServer::POA_var poa_with_ds =</tt>
718 <br><tt>root_poa->create_POA ("POA_WITH_DS",</tt>
719 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
720 poa_manager.in (),</tt>
721 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
722 poa_policy_list );</tt>
723 <p>All the servants that want network priority set on their replies should
724 register with this POA.
725 <p>NOTE - The POA policy can be set only once. This implies that all replies
726 sent from the POA that has the network priority set will have the DSCP
727 set on them. In order to unset the network priority one has to use a different
728 POA without the network priority set on it.
729 <br>&nbsp;</ul>
731 <dt>
732 <b>Network Priority Mapping</b></dt>
734 <br>&nbsp;
735 <ul>
736 <li>
737 <b>NetworkPriorityMapping interface</b></li>
739 <br>&nbsp;
740 <dd>
741 The RTCORBA to network priority mapping framework is similar to the RTCORBA
742 to native thread priority mapping framework. As mentioned in section 2.1.2
743 this is implemented by providing the native interface NetworkPriorityMapping.
744 The native interface is implemented in the RTCORBAC.h as:
746 <p><tt>typedef TAO_Network_Priority_Mapping
747 NetworkPriorityMapping;</tt></dd>
749 <p><tt>Where TAO_Network_Priority_Mapping is defined as:</tt>
750 <p><tt>class TAO_Network_Priority_Mapping</tt>
751 <br><tt>{</tt>
752 <br><tt>public:</tt>
753 <br><tt>&nbsp;&nbsp;&nbsp; virtual CORBA::Boolean to_network (RTCORBA::Priority
754 corba_priority,</tt>
755 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
756 RTCORBA::NetworkPriority &amp;network_priority) = 0;</tt>
757 <br><tt>&nbsp;&nbsp;&nbsp; virtual CORBA::Boolean to_CORBA (RTCORBA::NetworkPriority
758 network_priority,</tt>
759 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
760 RTCORBA::Priority &amp;corba_priority) = 0;</tt>
761 <br><tt>};</tt>
762 <p>The methods to_network (…) and to_corba (…) can be implemented differently
763 for different mapping algorithms that can be defined by the application.
764 <br>&nbsp;
765 <li>
766 <b>Default Network Priority Mappings</b></li>
768 <br>&nbsp;
769 <dd>
770 TAO implements the default Linear Mapping from RTCORBA to Diffserv Codepoint
771 mapping. Further mappings may be added to TAO. The application can choose
772 these TAO supported mappings through the Service Configurator (svc.conf)
773 files with the following entry:</dd>
775 <p>static RT_ORB_Loader "-ORBSchedPolicy SCHED_FIFO -ORBScopePolicy PROCESS
776 -ORBPriorityMapping direct <i>-RTORBNetworkPriorityMapping Linear</i>"
777 <br>&nbsp;
778 <li>
779 <b>Network Priority Mapping Manager</b></li>
781 <br>&nbsp;
782 <dd>
783 A NetworkPriorityMappingManager is defined in TAO to manage the Network
784 Priority Mapping.</dd>
786 <p><tt>typedef TAO_Network_Priority_Mapping_Manager NetworkPriorityMappingManager;</tt>
787 <p><tt>Where TAO_Network_Priority_Mapping_Manager is:</tt>
788 <p><tt>class TAO_RTCORBA_Export TAO_Network_Priority_Mapping_Manager :</tt>
789 <br><tt>{</tt>
790 <br><tt>public:</tt>
791 <br><tt>&nbsp;&nbsp;&nbsp; TAO_Network_Priority_Mapping_Manager (RTCORBA::NetworkPriorityMapping
792 * mapping);</tt>
793 <br><tt>&nbsp;&nbsp;&nbsp; void mapping (RTCORBA::NetworkPriorityMapping
794 * mapping);</tt>
795 <br><tt>&nbsp;&nbsp;&nbsp; RTCORBA::NetworkPriority_Mapping *mapping (void);</tt><tt></tt>
796 <p><tt>private:</tt>
797 <br><tt>&nbsp;&nbsp;&nbsp; TAO_Network_Priority_Mapping *mapping_;</tt>
798 <br><tt>};</tt>
799 <p>The application developer can add his custom network priority mappings
800 as described in section 2.3.3 using the NetworkPriorityMappingManager.
801 <br>&nbsp;
802 <li>
803 <b>Custom Network Priority Mapping</b></li>
805 <br>&nbsp;
806 <dd>
807 In order to implement a custom network priority mapping the application
808 developer should implement the methods of the TAO_Network_Priority_Mapping
809 class. E.g:</dd>
811 <p><tt>class TAO_Custom_Network_Priority_Mapping :</tt>
812 <br><tt>public TAO_Network_Priority_Mapping</tt>
813 <br><tt>{</tt>
814 <br><tt>&nbsp;&nbsp;&nbsp; virtual CORBA::Boolean to_network (RTCORBA::Priority
815 corba_priority,</tt>
816 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
817 RTCORBA::NetworkPriority &amp;network_priority);</tt>
818 <br><tt>&nbsp;&nbsp;&nbsp; virtual CORBA::Boolean to_CORBA (RTCORBA::NetworkPriority
819 network_priority,</tt>
820 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
821 RTCORBA::Priority &amp;corba_priority);</tt>
822 <br><tt>};</tt>
823 <p>This custom Network Priority Mapping can then be loaded into the Network
824 Priority Mapping Manager as follows:
825 <p><tt># Resolve the Network priority Mapping Manager</tt>
826 <br><tt>CORBA::Object_var object = orb->resolve_initial_references ("NetworkPriorityMappingManager");</tt>
827 <br><tt>RTCORBA::NetworkPriorityMappingManager_var mapping_manager = RTCORBA::NetworkPriorityMappingManager::_narrow
828 (object.in ());</tt>
829 <p><tt># Initialize the custom priority mapping</tt>
830 <br><tt>TAO_Custom_Network_Priority_Mapping *cnpm = 0;</tt>
831 <br><tt>ACE_NEW (cnpm,</tt>
832 <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TAO_Custom_Network_Priority_Mapping);</tt>
833 <p><tt>#Load the custom network priority mapping object in the network
834 priority</tt>
835 <br><tt>#mapping manager. The user can thus add his own priority mapping.</tt>
836 <br><tt>mapping_manager->mapping (cnpm);</tt>
837 <p>This ensures that the Custom Network Priority Mapping will be used to
838 map the RTCORBA priority to the network priority.
839 </ul>
840 <br>
841 </dl>
843 </body>
844 </html>