1 //=============================================================================
5 * Naming Service listing utility
7 * @author Thomas Lockhart, NASA/JPL <Thomas.Lockhart@jpl.nasa.gov>
9 * Enhanced 21 Jun, 2006 Simon Massey <sma@prismtech.com>
11 //=============================================================================
13 #include "ace/SString.h"
14 #include "orbsvcs/CosNamingC.h"
15 #include "orbsvcs/Time_Utilities.h"
16 #include "tao/Endpoint.h"
17 #include "tao/Profile.h"
19 #include "tao/ORB_Constants.h"
20 #include "tao/AnyTypeCode/Any.h"
21 #include "tao/Messaging/Messaging.h"
22 #include "tao/Strategies/advanced_resource.h"
23 #include "tao/PolicyC.h"
24 #include "ace/Time_Value.h"
25 #include "ace/Log_Msg.h"
26 #include "ace/OS_NS_stdio.h"
27 #include "ace/Argv_Type_Converter.h"
28 #include "ace/OS_NS_ctype.h"
30 //============================================================================
35 showIOR
= false, // Default decodes endpoints
36 showCtxIOR
= false, // Default no displaying naming context ior
37 noLoops
= false; // Default draw loopback arrows
39 *myTree
= "|", // Default string to draw tree "tram-lines"
40 *myNode
= "+"; // Default string to draw tree node end-points
41 size_t sizeMyTree
; // Initialised by main to strlen (myTree)
42 size_t sizeMyNode
; // Initialised by main to strlen (myNode)
43 size_t maxDepth
= 0; // Limit to display depth (default unlimited)
45 rtt
= ACE_Time_Value::zero
; // relative roundtrip timeout for ctx
47 const CORBA::ULong MAX_COUNT_DEFAULT
= 100;
48 CORBA::ULong max_count
= MAX_COUNT_DEFAULT
;
50 void list_context (const CosNaming::NamingContext_ptr
,
52 CORBA::ULong max_count
);
54 CORBA::Object_ptr
set_rtt(CORBA::Object_ptr obj
);
56 //==========================================================================
57 class NestedNamingContexts
60 static void add (const CosNaming::NamingContext_ptr nc
)
62 (void) new NestedNamingContexts( nc
); // This is not a leak (see constructor)
70 static size_t hasBeenSeen (const CosNaming::NamingContext_ptr nc
)
73 for (const NestedNamingContexts
*pMyNode
= pBottom
;
75 ++level
, pMyNode
= pMyNode
->pNext
)
77 if (pMyNode
->pnc
->_is_equivalent (nc
))
78 return level
; // Loops backwards this number of levels
81 return 0; // Not seen before
85 static const NestedNamingContexts
86 *pBottom
; // Our current lowest level
87 const CosNaming::NamingContext_ptr
88 pnc
; // This level's Naming Context
89 const NestedNamingContexts
90 *const pNext
; // Next highest level
92 NestedNamingContexts (const CosNaming::NamingContext_ptr nc
)
93 :pnc(nc
), pNext(pBottom
) // Adds the old list to this!
95 this->pBottom
= this; // Doesn't leak this (it's the new start)
98 ~NestedNamingContexts ()
100 this->pBottom
= this->pNext
; // this node removed from list.
104 NestedNamingContexts (const NestedNamingContexts
&);
105 NestedNamingContexts
&operator= (const NestedNamingContexts
&);
107 const NestedNamingContexts
*NestedNamingContexts::pBottom
= 0;
109 //==========================================================================
111 get_tag_name (CORBA::ULong tag
, ACE_CString
& tag_string
)
113 if (tag
== IOP::TAG_INTERNET_IOP
)
115 else if (tag
== TAO_TAG_UIOP_PROFILE
)
117 else if (tag
== TAO_TAG_SHMEM_PROFILE
)
118 tag_string
= "SHMEM";
119 else if (tag
== TAO_TAG_DIOP_PROFILE
)
121 else if (tag
== TAO_TAG_COIOP_PROFILE
)
122 tag_string
= "COIOP";
123 else if (tag
== TAO_TAG_SCIOP_PROFILE
)
124 tag_string
= "SCIOP";
127 char buffer
[32]= {'\0'};
128 ACE_OS::sprintf( buffer
, "%08x (%u)", tag
, tag
);
129 (tag_string
= "Unknown tag: ") += buffer
;
133 //==========================================================================
135 display_endpoint_info (CORBA::Object_ptr obj
, const size_t level
)
137 TAO_Stub
*stub
= obj
->_stubobj ();
140 ACE_DEBUG ((LM_DEBUG
, " {Invalid Stub}\n"));
144 TAO_Profile
* profile
= stub
->profile_in_use ();
147 ACE_DEBUG ((LM_DEBUG
, " {Invalid Profile}\n"));
151 TAO_Endpoint
* endpoint
= profile
->endpoint ();
154 ACE_DEBUG ((LM_DEBUG
, " {Invalid Endpoint}\n"));
159 CORBA::ULong
const tag
= endpoint
->tag ();
160 ACE_CString tag_name
;
161 get_tag_name (tag
, tag_name
);
163 ACE_DEBUG ((LM_DEBUG
, "\n"));
165 for (count
= 0; count
< level
; ++count
)
166 ACE_DEBUG ((LM_DEBUG
, "%C ", myTree
));
167 for (count
= 0; count
< sizeMyNode
; ++count
)
168 ACE_DEBUG ((LM_DEBUG
, " "));
169 ACE_DEBUG ((LM_DEBUG
, " Protocol: %C\n",
173 for (count
= 0; count
< level
; ++count
)
174 ACE_DEBUG ((LM_DEBUG
, "%C ", myTree
));
175 for (count
= 0; count
< sizeMyNode
; ++count
)
176 ACE_DEBUG ((LM_DEBUG
, " "));
177 char buf
[256]= {'\0'};
178 if (endpoint
->addr_to_string (buf
, sizeof(buf
)-1u) < 0)
179 ACE_OS::strcpy( buf
, "{Endpoint too long}" );
180 ACE_DEBUG ((LM_DEBUG
, " Endpoint: %C\n", buf
));
183 //==========================================================================
184 // Display NS entries from a finite list.
186 show_chunk (const CosNaming::NamingContext_ptr nc
,
187 const CosNaming::BindingList
&bl
,
190 for (CORBA::ULong i
= 0;
195 for (count
= 0; count
< level
-1; ++count
)
196 ACE_DEBUG ((LM_DEBUG
, "%C ", myTree
));
197 ACE_DEBUG ((LM_DEBUG
, "%C %C", myNode
,
198 bl
[i
].binding_name
[0].id
.in ()));
200 if (bl
[i
].binding_name
[0].kind
[0])
201 ACE_DEBUG ((LM_DEBUG
,
203 bl
[i
].binding_name
[0].kind
.in ()));
205 CosNaming::Name Name
;
208 CORBA::string_dup (bl
[i
].binding_name
[0].id
);
210 CORBA::string_dup (bl
[i
].binding_name
[0].kind
);
212 CORBA::Object_var obj
= nc
->resolve (Name
);
214 // If this is a context node, follow it down to the next level...
215 if (bl
[i
].binding_type
== CosNaming::ncontext
)
217 ACE_DEBUG ((LM_DEBUG
, ": Naming context"));
219 obj
= set_rtt(obj
.in ());
221 CosNaming::NamingContext_var xc
;
224 xc
= CosNaming::NamingContext::_narrow (obj
.in ());
226 catch (const CORBA::OBJECT_NOT_EXIST
&)
229 ACE_DEBUG ((LM_DEBUG
, " {Destroyed}"));
231 catch (const CORBA::TRANSIENT
&)
234 ACE_DEBUG ((LM_DEBUG
, " {Transient context IOR}"));
236 catch (const CORBA::TIMEOUT
&)
239 ACE_DEBUG ((LM_DEBUG
, " {Operation on conext IOR timed out}"));
242 if (const size_t backwards
= NestedNamingContexts::hasBeenSeen (xc
.in ()))
244 ACE_DEBUG ((LM_DEBUG
, " (Binding Loop)\n"));
248 for (count
= 0; count
< (level
- backwards
); ++count
)
249 ACE_DEBUG ((LM_DEBUG
, "%C ", myTree
));
250 ACE_DEBUG ((LM_DEBUG
, "^"));
252 while (++count
< level
)
253 for (chars
= 0; chars
<= sizeMyTree
; ++chars
)
254 ACE_DEBUG ((LM_DEBUG
, "-"));
255 for (chars
= 0; chars
< sizeMyNode
; ++chars
)
256 ACE_DEBUG ((LM_DEBUG
, "-"));
257 ACE_DEBUG ((LM_DEBUG
, "^\n"));
264 CORBA::String_var str
=
265 orb
->object_to_string (obj
.in ());
266 ACE_DEBUG ((LM_DEBUG
, ": %C", str
.in ()));
269 if (maxDepth
!= level
)
271 ACE_DEBUG ((LM_DEBUG
, "\n"));
274 list_context (xc
.in (), level
+ 1, max_count
);
278 ACE_DEBUG ((LM_DEBUG
, " {Max depth reached}\n"));
281 // Mark this node as a reference
284 ACE_DEBUG ((LM_DEBUG
, ": Object Reference"));
285 if (CORBA::is_nil (obj
.in ()))
286 ACE_DEBUG ((LM_DEBUG
, " {Null}"));
290 CORBA::String_var str
=
291 orb
->object_to_string (obj
.in ());
292 ACE_DEBUG ((LM_DEBUG
, ": %C\n", str
.in ()));
294 else if (CORBA::is_nil (obj
.in ()))
295 ACE_DEBUG ((LM_DEBUG
, "\n"));
297 display_endpoint_info (obj
.in(), level
);
302 //==========================================================================
304 list_context (const CosNaming::NamingContext_ptr nc
,
306 CORBA::ULong max_count
)
308 CosNaming::BindingIterator_var it
;
309 CosNaming::BindingList_var bl
;
311 NestedNamingContexts::add (nc
);
312 nc
->list (max_count
, bl
, it
);
314 show_chunk (nc
, bl
.in (), level
);
316 if (!CORBA::is_nil (it
.in ()))
322 more
= it
->next_n (max_count
, bl
);
323 show_chunk (nc
, bl
.in (), level
);
329 NestedNamingContexts::remove ();
332 //==========================================================================
334 set_rtt(CORBA::Object_ptr obj
)
336 if (rtt
!= ACE_Time_Value::zero
)
338 #if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0
339 TimeBase::TimeT roundTripTimeoutVal
;
340 ORBSVCS_Time::Time_Value_to_TimeT(roundTripTimeoutVal
, rtt
);
342 CORBA::Any anyObjectVal
;
343 anyObjectVal
<<= roundTripTimeoutVal
;
344 CORBA::PolicyList
polList (1);
347 polList
[0] = orb
->create_policy(Messaging::RELATIVE_RT_TIMEOUT_POLICY_TYPE
,
350 CORBA::Object_var obj2
= obj
->_set_policy_overrides(polList
, CORBA::SET_OVERRIDE
);
351 polList
[0]->destroy();
354 ACE_DEBUG ((LM_DEBUG
, "RTT not supported in TAO build.\n"));
357 return CORBA::Object::_duplicate(obj
);
359 } // end of local unnamed namespace
361 //============================================================================
363 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
370 orb
= CORBA::ORB_init (argc
, argv
);
372 // Scan through the command line options
376 ACE_TCHAR kindsep
= ACE_TEXT('.');
377 ACE_TCHAR ctxsep
[] = ACE_TEXT("/");
379 const ACE_TCHAR
*const pname
= argv
[0];
380 const ACE_TCHAR
*nameService
= 0;
387 if (0 == ACE_OS::strcmp (*argv
, ACE_TEXT ("--ns")))
391 ACE_DEBUG ((LM_DEBUG
,
392 "Error: --ns requires an argument\n"));
400 ACE_DEBUG ((LM_DEBUG
,
401 "Error: more than one --ns.\n"));
406 ACE_DEBUG ((LM_DEBUG
,
407 "Error: --nsior and --ns "
408 "are both specified\n"));
415 else if (0 == ACE_OS::strcmp (*argv
, ACE_TEXT ("--nsior")))
417 if (showIOR
|| showCtxIOR
|| noLoops
418 || nameService
|| name
|| maxDepth
)
420 ACE_DEBUG ((LM_DEBUG
,
421 "Error: --nsior given "
422 "with other options\n"));
428 else if (0 == ACE_OS::strcmp(*argv
, ACE_TEXT ("--ior")))
432 ACE_DEBUG ((LM_DEBUG
,
433 "Error: --nsior and --ior are "
434 "both specified\n"));
440 else if (0 == ACE_OS::strcmp (*argv
, ACE_TEXT ("--ctxior")))
444 ACE_DEBUG ((LM_DEBUG
,
445 "Error: --nsior and --ctxior are "
446 "both specified\n"));
452 else if (0 == ACE_OS::strcmp (*argv
, ACE_TEXT ("--tree")))
456 ACE_DEBUG ((LM_DEBUG
,
457 "Error: --tree requires an argument\n"));
465 ACE_DEBUG ((LM_DEBUG
,
466 "Error: --nsior and --tree are "
467 "both specified\n"));
471 myTree
= ACE_TEXT_ALWAYS_CHAR (*argv
);
474 else if (0 == ACE_OS::strcmp (*argv
, ACE_TEXT ("--node")))
478 ACE_DEBUG ((LM_DEBUG
,
479 "Error: --node requires an argument\n"));
487 ACE_DEBUG ((LM_DEBUG
,
488 "Error: --nsior and --node are "
489 "both specified\n"));
493 myNode
= ACE_TEXT_ALWAYS_CHAR (*argv
);
496 else if (0 == ACE_OS::strcmp(*argv
, ACE_TEXT ("--noloops")))
500 ACE_DEBUG ((LM_DEBUG
,
501 "Error: --nsior and --noloops are "
502 "both specified\n"));
508 else if (0 == ACE_OS::strcmp (*argv
, ACE_TEXT ("--name")))
512 ACE_DEBUG ((LM_DEBUG
,
513 "Error: more than one --name\n"));
518 ACE_DEBUG ((LM_DEBUG
,
519 "Error: --name requires an argument\n"));
527 ACE_DEBUG ((LM_DEBUG
,
528 "Error: --nsior and --name are "
529 "both specified\n"));
536 else if (0 == ACE_OS::strcmp (*argv
, ACE_TEXT ("--ctxsep")))
540 ACE_DEBUG ((LM_DEBUG
,
541 "Error: --ctxsep requires a character\n"));
544 else if (1 != ACE_OS::strlen(*(++argv
)))
546 ACE_DEBUG ((LM_DEBUG
,
547 "Error: --ctxsep takes a single character (not %s)\n", *argv
));
552 ACE_DEBUG ((LM_DEBUG
,
553 "Error: --nsior and --ctxsep are "
554 "both specified\n"));
558 ctxsep
[0] = (*argv
)[0];
560 else if (0 == ACE_OS::strcmp (*argv
, ACE_TEXT ("--kindsep")))
564 ACE_DEBUG ((LM_DEBUG
,
565 "Error: --kindsep requires a character\n"));
568 else if (1 != ACE_OS::strlen(*(++argv
)))
570 ACE_DEBUG ((LM_DEBUG
,
571 ACE_TEXT ("Error: --kindsep takes a single ")
572 ACE_TEXT ("character (not %s)\n"), *argv
));
577 ACE_DEBUG ((LM_DEBUG
,
578 ACE_TEXT ("Error: --nsior and --kindsep are ")
579 ACE_TEXT ("both specified\n")));
583 kindsep
= (*argv
)[0];
585 else if (0 == ACE_OS::strcmp(*argv
, ACE_TEXT ("--max")))
589 ACE_DEBUG ((LM_DEBUG
,
590 "Error: --max given more than once\n"));
593 else if (!--argc
|| !ACE_OS::ace_isdigit (ACE_TEXT_ALWAYS_CHAR (*(++argv
))[0]))
595 ACE_DEBUG ((LM_DEBUG
,
596 ACE_TEXT ("Error: --max requires a number\n")));
601 ACE_DEBUG ((LM_DEBUG
,
602 ACE_TEXT ("Error: --nsior and --max are ")
603 ACE_TEXT ("both specified\n")));
607 maxDepth
= ACE_OS::atoi (*argv
);
609 else if (0 == ACE_OS::strcmp(*argv
, ACE_TEXT ("--rtt")))
611 if (rtt
!= ACE_Time_Value::zero
)
613 ACE_DEBUG ((LM_DEBUG
,
614 ACE_TEXT ("Error: --rtt given more than once\n")));
617 else if (!--argc
|| !ACE_OS::ace_isdigit (ACE_TEXT_ALWAYS_CHAR (*(++argv
))[0]))
619 ACE_DEBUG ((LM_DEBUG
,
620 ACE_TEXT ("Error: --rtt requires a number\n")));
624 rtt
.set (ACE_OS::atoi (*argv
), 0);
626 else if (0 == ACE_OS::strcmp(*argv
, ACE_TEXT ("--count")))
628 if (max_count
!= MAX_COUNT_DEFAULT
)
630 ACE_DEBUG ((LM_DEBUG
,
631 ACE_TEXT ("Error: --count given more than once\n")));
634 else if (!--argc
|| !ACE_OS::ace_isdigit (ACE_TEXT_ALWAYS_CHAR (*(++argv
))[0]))
636 ACE_DEBUG ((LM_DEBUG
,
637 ACE_TEXT ("Error: --count requires a number\n")));
642 CORBA::ULong count
= ACE_OS::strtoul (ACE_TEXT_ALWAYS_CHAR (*argv
), 0, 10);
649 ACE_DEBUG ((LM_DEBUG
,
650 ACE_TEXT ("Error: --count requires a number")
651 ACE_TEXT (" greater than 0\n")));
658 ACE_DEBUG ((LM_DEBUG
,
659 ACE_TEXT ("Unknown option %s\n"),
668 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("\n%s options:\n")
669 ACE_TEXT (" --nsior {Display the naming service IOR and exit}\n")
671 ACE_TEXT (" --ns <ior> {Defaults to standard NameService}\n")
672 ACE_TEXT (" --ior {Display ior for end points}\n")
673 ACE_TEXT (" --ctxior {Display ior for naming contexts}\n")
674 ACE_TEXT (" --tree \"xx\" {Defaults to | for drawing tramlines}\n")
675 ACE_TEXT (" --node \"xx\" {Defaults to + for drawing nodes}\n")
676 ACE_TEXT (" --noloops {Inhibit drawing of naming context loops}\n")
677 ACE_TEXT (" --name <name> {Lists sub-set, defaults to root}\n")
678 ACE_TEXT (" --ctxsep <character> {<name> Context separation character, default /}\n")
679 ACE_TEXT (" --kindsep <character> {<name> ID/Kind separation character, default .}\n")
680 ACE_TEXT (" --max <number> {If given, limits displayed sub-context depth}\n")
681 ACE_TEXT (" --rtt <seconds> {If given, sets the relative round trip timeout policy}\n")
682 ACE_TEXT (" --count <number> {If given, sets the maximum ")
683 ACE_TEXT ("number of entries per request from the NameService}\n"),
689 // Initialise the lengths of the myTree and myNode draw strings.
690 sizeMyTree
= ACE_OS::strlen (myTree
);
691 sizeMyNode
= ACE_OS::strlen (myNode
);
693 // Contact the name service
694 CORBA::Object_var obj
;
696 obj
= orb
->string_to_object (nameService
);
698 obj
= orb
->resolve_initial_references ("NameService");
700 obj
= set_rtt(obj
.in ());
702 CosNaming::NamingContext_var root_nc
=
703 CosNaming::NamingContext::_narrow (obj
.in ());
704 if (CORBA::is_nil (root_nc
.in ()))
706 ACE_DEBUG ((LM_DEBUG
,
707 "Error: nil root naming context\n"));
713 // Assemble the name from the user string given
714 CosNaming::Name
the_name (0);
716 while (0 != (cp
= ACE_OS::strtok (name
, ctxsep
)))
718 const int index
= the_name
.length();
719 the_name
.length (index
+1);
720 ACE_TCHAR
*kind
= const_cast<ACE_TCHAR
*> (ACE_OS::strchr (cp
, kindsep
));
724 the_name
[index
].kind
= CORBA::string_dup (ACE_TEXT_ALWAYS_CHAR(++kind
));
726 the_name
[index
].id
= CORBA::string_dup (ACE_TEXT_ALWAYS_CHAR(cp
));
727 name
= 0; // way strtok works
730 // Now find this sub-context and replace the root with it.
731 obj
= root_nc
->resolve( the_name
);
733 CosNaming::NamingContext::_narrow (obj
.in ());
734 if (CORBA::is_nil (root_nc
.in ()))
736 ACE_DEBUG ((LM_DEBUG
,
737 "Error: Can't find naming context\n %s\n", name
));
743 CORBA::String_var str
=
744 orb
->object_to_string (root_nc
.in ());
748 ACE_DEBUG ((LM_DEBUG
,
749 "The NameService is located via:\n%C\n", str
.in ()));
753 ACE_DEBUG ((LM_DEBUG
,
754 "Naming Service: %C\n---------------\n",
755 ((showCtxIOR
)? str
.in () : "")));
756 list_context (root_nc
.in (), 1, max_count
);
759 catch (const CORBA::Exception
& ex
)
761 ex
._tao_print_exception ("Exception in nslist");
769 catch (const CORBA::Exception
& ex
)
771 ACE_DEBUG ((LM_DEBUG
, "\nError:\n"));
772 ex
._tao_print_exception ("Exception in while shutting down");