Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / TAO / orbsvcs / tests / FT_Naming / Replication / client.cpp
blob0807eb0c6c58a116440617af223524c9e838be6b
1 // ============================================================================
2 //
3 // = DESCRIPTION
4 // This class implements a CORBA client for a redundant CosNaming
5 // Service using stubs generated by the TAO ORB IDL compiler.
6 //
7 // = AUTHORS
8 // Rich Seibel <seibel_r@ociweb.com>
9 // ============================================================================
11 #include "test_objectS.h"
12 #include "orbsvcs/CosNamingC.h"
13 #include "orbsvcs/Naming/Naming_Server.h"
14 #include "tao/debug.h"
15 #include "ace/Get_Opt.h"
16 #include "ace/OS_NS_stdio.h"
17 #include "ace/High_Res_Timer.h"
19 #if defined (_MSC_VER)
20 # pragma warning (disable : 4250)
21 #endif /* _MSC_VER */
23 class My_Test_Object :
24 public virtual POA_Test_Object
26 public:
27 My_Test_Object (CORBA::Short id = 0);
28 // Constructor.
30 ~My_Test_Object ();
31 // Destructor.
33 // = Interface implementation accessor methods.
35 void id (CORBA::Short id);
36 // Sets id.
38 CORBA::Short id ();
39 // Gets id.
41 private:
42 short id_;
45 My_Test_Object::My_Test_Object (CORBA::Short id)
46 : id_ (id)
50 My_Test_Object::~My_Test_Object ()
54 CORBA::Short
55 My_Test_Object::id ()
57 return id_;
60 void
61 My_Test_Object::id (CORBA::Short id)
63 id_ = id;
67 // This function runs the test.
69 int
70 ACE_TMAIN(int argc, ACE_TCHAR *argv[])
72 int c_breadth = 4;
73 int c_depth = 4;
74 int o_breadth = 4;
75 ACE_TCHAR *ns1ref = 0;
76 ACE_TCHAR *ns2ref = 0;
77 int test_runs = 100;
79 ACE_Get_Opt get_opts (argc, argv, ACE_TEXT ("b:d:o:p:q:t:"));
80 int c;
81 int i;
83 while ((c = get_opts ()) != -1)
84 switch (c)
86 case 'b':
87 i = ACE_OS::atoi(get_opts.opt_arg ());
88 if (i<2)
90 ACE_ERROR((LM_ERROR,
91 ACE_TEXT ("Invalid breadth, must be 2 or more\n")));
92 ACE_OS::exit(1);
94 c_breadth = i;
95 break;
96 case 'd':
97 i = ACE_OS::atoi(get_opts.opt_arg ());
98 if (i<2)
100 ACE_ERROR ((LM_ERROR,
101 ACE_TEXT ("Invalid depth, must be 2 or more\n")));
102 ACE_OS::exit (1);
104 c_depth = i;
105 break;
106 case 'o':
107 i = ACE_OS::atoi(get_opts.opt_arg ());
108 if (i<2)
110 ACE_ERROR ((LM_ERROR,
111 ACE_TEXT ("Invalid breadth, must be 2 or more\n")));
112 ACE_OS::exit (1);
114 o_breadth = i;
115 break;
116 case 'p':
117 ns1ref = get_opts.opt_arg ();
118 break;
119 case 't':
120 i = ACE_OS::atoi (get_opts.opt_arg ());
121 if (i<1)
123 ACE_ERROR ((LM_ERROR,
124 ACE_TEXT ("Invalid number of test runs. ")
125 ACE_TEXT ("Must be 1 or more\n")));
126 ACE_OS::exit (1);
128 test_runs = i;
129 break;
130 case 'q':
131 ns2ref = get_opts.opt_arg ();
132 break;
133 default:
134 ACE_ERROR_RETURN ((LM_ERROR,
135 ACE_TEXT ("Argument %c \n usage: %s")
136 ACE_TEXT (" [-b <breadth of context tree>]")
137 ACE_TEXT (" [-d <depth of context tree>]")
138 ACE_TEXT (" [-o <breadth of object tree>]")
139 ACE_TEXT (" [-t <number of performance test runs>]")
140 ACE_TEXT (" -p <ior of first name server>")
141 ACE_TEXT (" -q <ior of second name server>")
142 ACE_TEXT ("\n")),
143 -1);
146 CosNaming::NamingContext_var root_context_1;
147 CosNaming::NamingContext_var root_context_2;
151 // Initialize orb
152 CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
154 // ior's are specified for the name servers through a commandline
155 // option or a file.
157 // Resolve the first name server
159 CORBA::Object_var ns1obj = orb->string_to_object (
160 ACE_TEXT_ALWAYS_CHAR (ns1ref));
162 if (CORBA::is_nil (ns1obj.in ()))
163 ACE_ERROR_RETURN ((LM_ERROR,
164 ACE_TEXT ("invalid ior <%s>\n"),
165 ns1ref),
166 -1);
167 root_context_1 = CosNaming::NamingContext::_narrow (ns1obj.in ());
169 // Resolve the second name server
171 CORBA::Object_var ns2obj = orb->string_to_object (
172 ACE_TEXT_ALWAYS_CHAR (ns2ref));
174 if (CORBA::is_nil (ns2obj.in ()))
175 ACE_ERROR_RETURN ((LM_ERROR,
176 ACE_TEXT ("invalid ior <%s>\n"),
177 ns2ref),
178 -1);
179 root_context_2 = CosNaming::NamingContext::_narrow (ns2obj.in ());
181 catch (const CORBA::Exception& ex)
183 ex._tao_print_exception (ACE_TEXT ("Unable to resolve name servers"));
184 return -1;
187 // Create a bunch of objects in one context
188 // Note: strings to the naming service must be char, not wchar
191 // Bind one context level under root.
192 CosNaming::Name level1;
193 level1.length (1);
194 level1[0].id = CORBA::string_dup ("level1_context");
195 CosNaming::NamingContext_var level1_context;
196 level1_context = root_context_1->bind_new_context (level1);
198 for (i=0; i<o_breadth; i++)
200 // Instantiate a dummy object and bind it under the new context.
201 My_Test_Object *impl1 = new My_Test_Object (i+1);
202 Test_Object_var obj1 = impl1->_this ();
203 impl1->_remove_ref ();
205 level1.length (2);
206 char wide_name[16];
207 ACE_OS::sprintf(wide_name, "obj_%d", i);
208 level1[1].id = CORBA::string_dup (wide_name);
209 root_context_1->bind (level1, obj1.in ());
211 // See if the newly bound object is available in the
212 // replica
213 try {
214 CORBA::Object_var obj1_on_replica =
215 root_context_2->resolve (level1);
217 catch (const CosNaming::NamingContext::NotFound&)
219 ACE_ERROR ((LM_ERROR,
220 ACE_TEXT("Did not resolve object from replica on first.\n")));
222 // Try again...
223 try {
224 CORBA::Object_var obj1_on_replica =
225 root_context_2->resolve (level1);
226 // We did find the object on the replica, but only after a wait.
227 // This would be caused by a race condition to access the variable.
228 ACE_ERROR ((LM_ERROR,
229 ACE_TEXT("Object appeared after a short wait.\n")));
231 catch (const CosNaming::NamingContext::NotFound& second_ex)
233 second_ex._tao_print_exception ("It really is not there. Failing...\n");
234 return -1;
239 catch (const CORBA::Exception& ex)
241 ex._tao_print_exception (ACE_TEXT ("Unable to create a lot of objects"));
242 return -1;
245 // Create a deep context tree
248 CosNaming::NamingContext_var next_context = root_context_1;
249 for (i=0; i<c_depth; i++)
251 // Bind level1 context under root.
252 CosNaming::Name deep;
253 deep.length (1);
254 char deep_name[16];
255 ACE_OS::sprintf(deep_name, "deep_%d", i);
256 deep[0].id = CORBA::string_dup (deep_name);
257 CosNaming::NamingContext_var deep_context;
258 deep_context = next_context->bind_new_context (deep);
259 next_context = deep_context;
262 catch (const CORBA::Exception& ex)
264 ex._tao_print_exception (ACE_TEXT ("Unable to create deep context"));
265 return -1;
268 // Create a wide context tree
271 for (i=0; i<c_breadth; i++)
273 // Bind all level of context under root.
274 CosNaming::Name wide;
275 wide.length (1);
276 char wide_name[16];
277 ACE_OS::sprintf(wide_name, "wide_%d", i);
278 wide[0].id = CORBA::string_dup (wide_name);
279 CosNaming::NamingContext_var wide_context;
280 wide_context = root_context_1->bind_new_context (wide);
282 try {
283 // Check if the new context is available in the replica
284 CORBA::Object_var obj1_on_replica =
285 root_context_2->resolve (wide);
286 // Make sure it is a context
287 CosNaming::NamingContext_var nc =
288 CosNaming::NamingContext::_narrow (obj1_on_replica.in ());
290 catch (const CosNaming::NamingContext::NotFound&)
292 ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Unable to resolve wide context object from replica.\n")));
294 // Try again to see if it just was a race condition
295 try {
296 CORBA::Object_var obj1_on_replica =
297 root_context_2->resolve (wide);
298 // We did find the object on the replica, but only after a wait.
299 // This would be caused by a race condition to access the variable.
300 ACE_DEBUG ((LM_DEBUG,
301 ACE_TEXT("Object appeared after a short wait.\n")));
303 catch (const CosNaming::NamingContext::NotFound& second_ex)
305 second_ex._tao_print_exception (ACE_TEXT ("It really is not there. Failing...\n"));
306 return -1;
311 catch (const CORBA::Exception& ex)
313 ex._tao_print_exception (ACE_TEXT ("Unable to create wide context"));
314 return -1;
317 // Delete three selected things, one from each tree
318 try {
319 // Remove the second to last object from the Naming Context
320 CosNaming::Name wide1;
321 wide1.length (2);
322 wide1[0].id = CORBA::string_dup ("level1_context");
323 char wide_name[16];
324 ACE_OS::sprintf(wide_name, "obj_%d", o_breadth-2);
325 wide1[1].id = CORBA::string_dup (wide_name);
326 root_context_1->unbind (wide1);
328 bool retried = false;
329 // Make sure it is gone from the replica
330 try {
331 CORBA::Object_var obj1_on_replica =
332 root_context_2->resolve (wide1);
334 // An exception should be thrown by the above or
335 // there is an error. This means the replica did
336 // not register the loss of the context.
337 ACE_ERROR ((LM_ERROR,
338 "Unbound deep context not removed from replica. Trying again...\n"));
339 retried = true; // Mark this so it can be reported in catch block.
340 obj1_on_replica =
341 root_context_2->resolve (wide1);
342 ACE_ERROR_RETURN ((LM_ERROR,
343 "Unbound context not removed from on retry\n"),
344 -1);
346 catch (const CosNaming::NamingContext::NotFound&)
348 // Not on replica --- as it should be.
349 if (retried) // Was found on the retry
350 ACE_ERROR ((LM_ERROR,
351 "Was removed after short wait.\n"));
354 // Remove the second to last context from the wide root Naming Context
355 CosNaming::Name wide2;
356 wide2.length (1);
357 ACE_OS::sprintf(wide_name, "wide_%d", c_breadth-2);
358 wide2[0].id = CORBA::string_dup (wide_name);
359 CORBA::Object_var result_obj_ref = root_context_1->resolve (wide2);
360 CosNaming::NamingContext_var result_object =
361 CosNaming::NamingContext::_narrow (result_obj_ref.in ());
362 if (CORBA::is_nil (result_object.in ()))
363 ACE_ERROR_RETURN ((LM_ERROR,
364 ACE_TEXT ("Problems with resolving wide context ")
365 ACE_TEXT ("- nil object ref.\n")),
366 -1);
367 result_object->destroy();
368 root_context_1->unbind (wide2);
370 // Remove the last context from the deep Naming Context
371 CosNaming::Name deep;
372 deep.length (c_depth);
373 char deep_name[16];
374 for (i=0; i<c_depth; i++)
376 ACE_OS::sprintf(deep_name, "deep_%d", i);
377 deep[i].id = CORBA::string_dup (deep_name);
379 result_obj_ref = root_context_1->resolve (deep);
380 result_object =
381 CosNaming::NamingContext::_narrow (result_obj_ref.in ());
382 if (CORBA::is_nil (result_object.in ()))
383 ACE_ERROR_RETURN ((LM_ERROR,
384 ACE_TEXT ("Problems with resolving deep context ")
385 ACE_TEXT ("- nil object ref.\n")),
386 -1);
387 result_object->destroy();
388 root_context_1->unbind (deep);
390 retried = false;
391 // Make sure it is gone from the replica
392 try {
393 CORBA::Object_var obj1_on_replica =
394 root_context_2->resolve (deep);
396 // An exception should be thrown by the above or
397 // there is an error. This means the replica did
398 // not register the loss of the context.
399 ACE_ERROR ((LM_ERROR,
400 "Unbound deep context not removed from replica. Trying again...\n"));
401 retried = true; // Mark this so it can be reported in catch block.
402 obj1_on_replica =
403 root_context_2->resolve (deep);
404 ACE_ERROR_RETURN ((LM_ERROR,
405 "Unbound context not removed from on retry\n"),
406 -1);
408 catch (const CosNaming::NamingContext::NotFound&)
410 // Not on replica --- as it should be.
411 if (retried) // Was found on the retry
412 ACE_ERROR ((LM_ERROR,
413 ACE_TEXT("Was removed after short wait.\n")));
416 catch (const CORBA::Exception& ex)
418 ex._tao_print_exception (ACE_TEXT ("Unable to delete objects"));
419 return -1;
422 // Now use the other name server to access 3 objects next to the
423 // deleted objects and the 3 deleted objects
426 // Access the last object from the Naming Context
427 CosNaming::Name wide;
428 wide.length (2);
429 wide[0].id = CORBA::string_dup ("level1_context");
430 char wide_name[16];
431 ACE_OS::sprintf(wide_name, "obj_%d", o_breadth-1);
432 wide[1].id = CORBA::string_dup (wide_name);
433 CORBA::Object_var result_obj_ref = root_context_2->resolve (wide);
434 Test_Object_var result_object = Test_Object::_narrow (result_obj_ref.in ());
435 if (CORBA::is_nil (result_object.in ()))
436 ACE_ERROR_RETURN ((LM_ERROR,
437 ACE_TEXT ("Problems with resolving object from ")
438 ACE_TEXT ("redundant server - nil object ref.\n")),
439 -1);
441 catch (const CORBA::Exception& ex)
443 ex._tao_print_exception (ACE_TEXT ("Unable to resolve object from redundant server"));
444 return -1;
449 // Access the deleted second to last object from the Naming Context
450 CosNaming::Name wide;
451 wide.length (2);
452 wide[0].id = CORBA::string_dup ("level1_context");
453 char wide_name[16];
454 ACE_OS::sprintf(wide_name, "obj_%d", o_breadth-2);
455 wide[1].id = CORBA::string_dup (wide_name);
456 CORBA::Object_var result_obj_ref = root_context_2->resolve (wide);
457 ACE_ERROR_RETURN ((LM_ERROR,
458 ACE_TEXT ("Problems with resolving object from ")
459 ACE_TEXT ("redundant server - deleted object found.\n")),
460 -1);
462 catch (const CosNaming::NamingContext::NotFound& ex)
464 // expect exception since the context was deleted.
465 // Make sure the right exception reason is provided.
466 if (ex.why != CosNaming::NamingContext::missing_node)
467 ACE_ERROR_RETURN ((LM_ERROR,
468 ACE_TEXT ("Wrong exception returned during resolve.\n")),
469 -1);
471 catch (const CORBA::Exception& ex)
473 ex._tao_print_exception (ACE_TEXT ("Wrong exception type returned from resolve.\n"));
474 return -1;
478 // Access the last context from the wide Naming Context
479 CosNaming::Name wide;
480 wide.length (1);
481 char wide_name[16];
482 ACE_OS::sprintf(wide_name, "wide_%d", c_breadth-1);
483 wide[0].id = CORBA::string_dup (wide_name);
484 CORBA::Object_var result_obj_ref = root_context_2->resolve (wide);
485 CosNaming::NamingContext_var result_object =
486 CosNaming::NamingContext::_narrow (result_obj_ref.in ());
487 if (CORBA::is_nil (result_object.in ()))
488 ACE_ERROR_RETURN ((LM_ERROR,
489 ACE_TEXT ("Problems with resolving wide context from ")
490 ACE_TEXT ("redundant server - nil object ref.\n")),
491 -1);
493 catch (const CosNaming::NamingContext::NotFound&)
495 // Expected exception
497 catch (const CORBA::Exception& ex)
499 ex._tao_print_exception (ACE_TEXT ("Unexpected Exception received.\n"));
500 return -1;
505 // Access the deleted second to last object from the Naming Context
506 CosNaming::Name wide;
507 wide.length (2);
508 char wide_name[16];
509 ACE_OS::sprintf(wide_name, "wide_%d", c_breadth-2);
510 wide[0].id = CORBA::string_dup (wide_name);
511 CORBA::Object_var result_obj_ref = root_context_2->resolve (wide);
512 ACE_ERROR_RETURN ((LM_ERROR,
513 ACE_TEXT ("Problems with resolving wide context from ")
514 ACE_TEXT ("redundant server - deleted object found.\n")),
515 -1);
517 catch (const CosNaming::NamingContext::NotFound&)
519 // Expected exception
521 catch (const CORBA::Exception& ex)
523 ex._tao_print_exception (ACE_TEXT ("Unexpected Exception received.\n"));
524 return -1;
529 // Access the deleted last context from the deep Naming Context
530 CosNaming::Name deep;
531 deep.length (c_depth);
532 char deep_name[16];
533 for (i=0; i<c_depth; i++)
535 ACE_OS::sprintf(deep_name, "deep_%d", i);
536 deep[i].id = CORBA::string_dup (deep_name);
538 CORBA::Object_var result_obj_ref = root_context_1->resolve (deep);
539 ACE_ERROR_RETURN ((LM_ERROR,
540 ACE_TEXT ("Problems with resolving deep context from ")
541 ACE_TEXT ("redundant server - deleted object found.\n")),
542 -1);
544 catch (const CosNaming::NamingContext::NotFound&)
546 // Expected exception
548 catch (const CORBA::Exception& ex)
550 ex._tao_print_exception (
551 ACE_TEXT ("Unexpected Exception received resolving ")
552 ACE_TEXT ("deep cxt from redundant server.\n"));
553 return -1;
558 // Access the second to last object from the Naming Context
559 CosNaming::Name deep;
560 deep.length (c_depth-1);
561 char deep_name[16];
562 for (i=0; i<c_depth-1; i++)
564 ACE_OS::sprintf(deep_name, "deep_%d", i);
565 deep[i].id = CORBA::string_dup (deep_name);
567 CORBA::Object_var result_obj_ref = root_context_1->resolve (deep);
568 CosNaming::NamingContext_var result_object =
569 CosNaming::NamingContext::_narrow (result_obj_ref.in ());
570 if (CORBA::is_nil (result_object.in ()))
571 ACE_ERROR_RETURN ((LM_ERROR,
572 ACE_TEXT ("Problems with resolving deep context from ")
573 ACE_TEXT ("redundant server - nil object ref.\n")),
574 -1);
576 catch (const CORBA::Exception& ex)
578 ex._tao_print_exception (
579 ACE_TEXT ("Unable to resolve deep context from redundant server"));
580 return -1;
583 // TODO: Cleanup namespace
586 // TODO: Create object groups and bind them. Check the replica.
588 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Redundancy test OK.\n")
589 ACE_TEXT ("Starting performance tests.\n")));
591 // Test performance of binding a bunch of objects in one context
594 // Bind one context level under root.
595 CosNaming::Name level1;
596 level1.length (1);
597 level1[0].id = CORBA::string_dup ("perf_context");
598 CosNaming::NamingContext_var perf_context;
599 perf_context = root_context_1->bind_new_context (level1);
601 // Instantiate a dummy object and bind it under the new context.
602 My_Test_Object *impl1 = new My_Test_Object (i+1);
603 Test_Object_var obj1 = impl1->_this ();
604 impl1->_remove_ref ();
606 ACE_High_Res_Timer::global_scale_factor_type gsf =
607 ACE_High_Res_Timer::global_scale_factor ();
609 ACE_hrtime_t start = ACE_OS::gethrtime ();
611 // Test how long it takes to bind
612 for (i=0; i<test_runs; i++)
614 level1.length (1);
615 char wide_name[16];
616 ACE_OS::sprintf(wide_name, "obj_%d", i);
617 level1[0].id = CORBA::string_dup (wide_name);
618 perf_context->bind (level1, obj1.in ());
621 ACE_hrtime_t elapsed_time = ACE_OS::gethrtime () - start;
622 // convert to microseconds
623 ACE_UINT32 usecs = ACE_UINT32(elapsed_time / gsf);
624 double secs = usecs / 1000000.0;
626 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Bound %i objects in %.2f secs\n"),
627 test_runs, secs));
629 // Test how long it takes to resolve
630 start = ACE_OS::gethrtime ();
631 for (i=0; i<test_runs; i++)
633 level1.length (1);
634 char wide_name[16];
635 ACE_OS::sprintf(wide_name, "obj_%d", i);
636 level1[0].id = CORBA::string_dup (wide_name);
637 CORBA::Object_var result_obj_ref = perf_context->resolve (level1);
640 elapsed_time = ACE_OS::gethrtime () - start;
641 // convert to microseconds
642 usecs = ACE_UINT32(elapsed_time / gsf);
643 secs = ((ACE_INT32) usecs) / 1000000.0;
645 ACE_DEBUG ((LM_DEBUG,
646 ACE_TEXT ("Resolved %i objects in %.2f secs\n"),
647 test_runs, secs));
649 // Test how long it takes to unbind
650 start = ACE_OS::gethrtime ();
651 for (i=0; i<test_runs; i++)
653 level1.length (1);
654 char wide_name[16];
655 ACE_OS::sprintf(wide_name, "obj_%d", i);
656 level1[0].id = CORBA::string_dup (wide_name);
657 perf_context->unbind (level1);
660 elapsed_time = ACE_OS::gethrtime () - start;
661 // convert to microseconds
662 usecs = ACE_UINT32(elapsed_time / gsf);
663 secs = ((ACE_INT32) usecs) / 1000000.0;
665 ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Unbound %i objects in %.2f secs\n"),
666 test_runs, secs));
668 catch (const CORBA::Exception& ex)
670 ex._tao_print_exception (ACE_TEXT ("ERROR: Exception during performance test.\n"));
671 return -1;
675 return 0;