diff options
10 files changed, 435 insertions, 0 deletions
diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl new file mode 100644 index 00000000000..28db1a83dad --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl @@ -0,0 +1,18 @@ +/* -*- C++ -*- */ +#if !defined (_ECHO_IDL) +#define _ECHO_IDL + +interface Echo +{ + // = TITLE + // Defines an interface that encapsulates an operation that returns + // a string sequence. + + typedef sequence<string> List; + + List return_list (); + + oneway void shutdown (); +}; + +#endif /* _ECHO_IDL */ diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp new file mode 100644 index 00000000000..d779208205d --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.cpp @@ -0,0 +1,78 @@ +#include "Echo_Client_i.h" +#include "ace/Get_Opt.h" +#include "ace/Read_Buffer.h" +#include "ace/OS_NS_unistd.h" +#include <iostream> +#include <cstring> + +// This is the interface program that accesses the remote object + +// Constructor. +Echo_Client_i::Echo_Client_i (void) +{ + //no-op +} + +//Destructor. +Echo_Client_i::~Echo_Client_i (void) +{ + //no-op +} + +int +Echo_Client_i::run (const char *name, + int argc, + ACE_TCHAR *argv[]) +{ + // Initialize the client. + if (client_.init (name, argc, argv) == -1) + return -1; + + try + { + Echo::List_var list = client_->return_list(); + std::cout << "Received list of length " + << list->length() << std::endl; + if (list->length() != 2) + { + std::cout << "ERROR: Expected length 2, exiting..." << std::endl; + client_->shutdown (); + return -1; + } + const char* value = (*list)[0].in(); + size_t length = std::strlen(value); + std::cout << "First element has length " + << length << std::endl; + for (size_t n = 0; n < length; ++n) + { + if (value[n] != 'A') + { + std::cout << "ERROR: Character at position " << n + << " should be 'A', but is '" + << value[n] << "'" << std::endl; + client_->shutdown (); + return -1; + } + } + value = (*list)[1].in(); + length = std::strlen(value); + std::cout << "Second element has length " + << length << std::endl; + std::cout << "Value: " << value << std::endl; + if (std::strcmp(value, "Hello World") != 0) + { + std::cout << "ERROR: Expected \"Hello World\", exiting..." + << std::endl; + client_->shutdown (); + return -1; + } + client_->shutdown (); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("\n Exception in RMI"); + return -1; + } + + return 0; +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h new file mode 100644 index 00000000000..82d35d53f18 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_Client_i.h @@ -0,0 +1,34 @@ +// -*- C++ -*- + +#ifndef ECHO_CLIENT_I_H +#define ECHO_CLIENT_I_H + +#include "../../../examples/Simple/Simple_util.h" +#include "EchoC.h" + +/** + * @class Echo_Client_i + * + * @brief Echo_Client interface subclass. + * + * This class implements the interface between the interface + * objects and the client . + */ +class Echo_Client_i +{ +public: + /// Constructor + Echo_Client_i (void); + + /// Destructor + ~Echo_Client_i (void); + + /// Execute the methods + int run (const char *, int, ACE_TCHAR **); + +private: + /// Instantiate the client object. + Client<Echo> client_; +}; + +#endif /* TIME_CLIENT_I_H */ diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp new file mode 100644 index 00000000000..058861f7624 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp @@ -0,0 +1,62 @@ +#include <string> +#include "Echo_i.h" + +// Constructor. + +Echo_i::Echo_i (void) +{ +} + +// Destructor. + +Echo_i::~Echo_i (void) +{ +} + +// Set the ORB pointer. + +void +Echo_i::orb (CORBA::ORB_ptr o) +{ + this->orb_ = CORBA::ORB::_duplicate (o); +} + +// Return a list of strings. + +Echo::List * +Echo_i::return_list () +{ + Echo::List_var list; + + { + Echo::List *tmp = 0; + ACE_NEW_RETURN (tmp, + Echo::List (2), + 0); + // Pass ownership to the _var, pitty that ACE_NEW_RETURN cannot + // assign to T_vars directly. + list = tmp; + } + + list->length (2); + + // Just do something to get a 'big' list of strings. + std::string big(4 * 1024 * 1024, 'A'); + std::string small("Hello World"); + list[CORBA::ULong(0)] = CORBA::string_dup(big.c_str()); + list[CORBA::ULong(1)] = CORBA::string_dup(small.c_str()); + + return list._retn (); +} + +// Shutdown the server application. + +void +Echo_i::shutdown (void) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\nThe echo server is shutting down\n"))); + + // Instruct the ORB to shutdown. + this->orb_->shutdown (); +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h new file mode 100644 index 00000000000..7e0822ebe26 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h @@ -0,0 +1,54 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Echo_i.h + * + * This class implements the Echo IDL interface. + * + * @author Kirthika Parameswaran <kirthika@cs.wustl.edu> + */ +//============================================================================= + + +#ifndef ECHO_I_H +#define ECHO_I_H + +#include "EchoS.h" + +/** + * @class Echo_i + * + * @brief Echo Object Implementation + * + * The object implementation performs the following functions: + * -- To return the string which needs to be displayed + * from the server. + * -- shuts down the server + */ +class Echo_i : public POA_Echo +{ +public: + /// Constructor. + Echo_i (void); + + /// Destructor. + virtual ~Echo_i (void); + + /// Return the mesg string back from the server. + virtual Echo::List *return_list (); + + /// Shutdown the server. + virtual void shutdown (); + + /// Set the ORB pointer. + void orb (CORBA::ORB_ptr o); + +private: + /// ORB pointer. + CORBA::ORB_var orb_; + + void operator= (const Echo_i&); +}; + +#endif /* ECHO_I_H */ diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md b/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md new file mode 100644 index 00000000000..235eb9fb32a --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md @@ -0,0 +1,19 @@ +# TAO GIOP Fragmentation Bug +## Reproduces a bug when GIOP fragmentation is used + +The server returns a string sequence with two elements, the first is a +long 4MB string with repeating character 'A', the second element is +the string "Hello World". If one removes the command line parameters +`-ORBMaxMessageSize 1048576` from `run_test.pl` everything +works as expected, but with these settings, which cause GIOP +fragmentation, the client receives an empty string as the second +element of the sequence. + +We discovered problems in a more complicated application when big +sequences are returned, often the client encountering +`CORBA::MARSHAL` or `CORBA::COMM_FAILURE` exceptions. In one +case, it worked if the sequence contained a single element, even if +big, but a small second element caused client exceptions. The complex +application encountered problems with big sequences even without the +`-ORBMaxMessageSize` parameter, but problems start at smaller +sizes if it is used.
\ No newline at end of file diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp new file mode 100644 index 00000000000..d3851527028 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp @@ -0,0 +1,19 @@ +# include "Echo_Client_i.h" + +// The client program for the application. + +int +ACE_TMAIN(int argc, ACE_TCHAR *argv[]) +{ + Echo_Client_i client; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\nEcho client\n\n"))); + + if (client.run ("Echo", + argc, + argv) == -1) + return -1; + else + return 0; +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc b/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc new file mode 100644 index 00000000000..ddd71d26341 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/echo.mpc @@ -0,0 +1,34 @@ +// -*- MPC -*- +project(*idl): taoidldefaults { + IDL_Files { + Echo.idl + } + custom_only = 1 +} + +project(*Server): taoserver, namingexe, iortable, utils, avoids_corba_e_micro { + exename = server + after += *idl + Source_Files { + Echo_i.cpp + ../../../examples/Simple/Simple_util.cpp + server.cpp + EchoS.cpp + EchoC.cpp + } + IDL_Files { + } +} + +project(*Client): taoclient, namingexe, iortable, utils { + exename = client + after += *IDL + Source_Files { + Echo_Client_i.cpp + ../../../examples/Simple/Simple_util.cpp + client.cpp + EchoC.cpp + } + IDL_Files { + } +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl b/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl new file mode 100755 index 00000000000..6d6d869d2a4 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl @@ -0,0 +1,75 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# -*- perl -*- + +use lib "$ENV{ACE_ROOT}/bin"; +use PerlACE::TestTarget; + +$status = 0; +$debug_level = '0'; + +foreach $i (@ARGV) { + if ($i eq '-debug') { + $debug_level = '10'; + } +} + +my $server = PerlACE::TestTarget::create_target (1) || die "Create target 1 failed\n"; +my $client = PerlACE::TestTarget::create_target (2) || die "Create target 2 failed\n"; + +my $iorbase = "server.ior"; +my $server_iorfile = $server->LocalFile ($iorbase); +my $client_iorfile = $client->LocalFile ($iorbase); +$server->DeleteFile($iorbase); +$client->DeleteFile($iorbase); + +$SV = $server->CreateProcess ("server", "-ORBMaxMessageSize 1048576 -ORBdebuglevel $debug_level -ORBLogFile server_log.txt -o $server_iorfile"); +$CL = $client->CreateProcess ("client", "-ORBdebuglevel $debug_level -ORBLogFile client_log.txt -f $client_iorfile -x"); +$server_status = $SV->Spawn (); + +if ($server_status != 0) { + print STDERR "ERROR: server returned $server_status\n"; + exit 1; +} + +if ($server->WaitForFileTimed ($iorbase, + $server->ProcessStartWaitInterval()) == -1) { + print STDERR "ERROR: cannot find file <$server_iorfile>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; +} + +if ($server->GetFile ($iorbase) == -1) { + print STDERR "ERROR: cannot retrieve file <$server_iorfile>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; +} +if ($client->PutFile ($iorbase) == -1) { + print STDERR "ERROR: cannot set file <$client_iorfile>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; +} + +$client_status = $CL->SpawnWaitKill ($client->ProcessStartWaitInterval()); + +if ($client_status != 0) { + print STDERR "ERROR: client returned $client_status\n"; + $status = 1; +} + +$server_status = $SV->WaitKill ($server->ProcessStopWaitInterval()); + +if ($server_status != 0) { + print STDERR "ERROR: server returned $server_status\n"; + $status = 1; +} + +$server->GetStderrLog(); +$client->GetStderrLog(); + +$server->DeleteFile($server_iorfile); +$client->DeleteFile($client_iorfile); + +exit $status; diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp new file mode 100644 index 00000000000..8f504aa3ba2 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp @@ -0,0 +1,42 @@ +#include "../../../examples/Simple/Simple_util.h" +#include "Echo_i.h" + +// This is the main driver program for the time and date server. + +int +ACE_TMAIN(int argc, ACE_TCHAR *argv[]) +{ + Server<Echo_i> server; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\n\tEcho server\n\n"))); + + try + { + if (server.init ("Echo", + argc, + argv) == -1) + return 1; + else + { + server.run (); + } + } + catch (const CORBA::UserException& userex) + { + userex._tao_print_exception ("User Exception"); + return -1; + } + catch (const CORBA::SystemException& sysex) + { + sysex._tao_print_exception ("System Exception"); + return -1; + } + catch (const ::CORBA::Exception &e) + { + e._tao_print_exception ("CORBA exception"); + return 1; + } + + return 0; +} |