diff options
author | alex <alex@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-02-16 06:38:49 +0000 |
---|---|---|
committer | alex <alex@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-02-16 06:38:49 +0000 |
commit | 7211c1e2fcda52e3bce16a29f05cc8f94fbab56c (patch) | |
tree | 6103a5605b624fe5306a57d8c8db1e4888734bc1 /examples | |
parent | c3ea40ae39854fb98b82ab6c9e415010ff09b26d (diff) | |
download | ATCD-7211c1e2fcda52e3bce16a29f05cc8f94fbab56c.tar.gz |
*** empty log message ***
Diffstat (limited to 'examples')
-rw-r--r-- | examples/Reactor/Proactor/README | 146 | ||||
-rw-r--r-- | examples/Reactor/Proactor/test_aiosig.cpp | 294 | ||||
-rw-r--r-- | examples/Reactor/Proactor/test_aiosig_ace.cpp | 273 |
3 files changed, 713 insertions, 0 deletions
diff --git a/examples/Reactor/Proactor/README b/examples/Reactor/Proactor/README new file mode 100644 index 00000000000..fa873589773 --- /dev/null +++ b/examples/Reactor/Proactor/README @@ -0,0 +1,146 @@ +This file describes the behavior of the POSIX <aio_> calls on the +various platforms it is being tested on. + +Test Suits: +========== + +o $ACE_ROOT/tests/Aio_Platform_Test.cpp : Tests basic limits + pertaining to the POSIX features + +o $ACE_ROOT/examples/Reactor/Proactor/test_aiocb.cpp : + This is a C++ program for testing the AIOCB (AIO Control + Blocks) based completion approach which uses <aio_suspend> for + completion querying. + +o $ACE_ROOT/examples/Reactor/Proactor/test_aiosig.cpp : This is a + C++ program for testing the Signal based completion approach + that uses <sigtimedwait> for completion querying. + +o $ACE_ROOT/examples/Reactor/Proactor/test_aiosig_ace.cpp: (Same as + test_aiosig.cpp, but uses ACE_DEBUGs instead of printf's and + ACE_Message_Blocks instead of char*'s. + +o test_proactor.cpp (with ACE_POSIX_AIOCB_Proactor) : Test for + ACE_Proactor which uses AIOCB (AIO Control Blocks) based + completions strategy Proactor. (#define ACE_POSIX_AIOCB_PROACTOR) + +o test_proactor.cpp (with ACE_POSIX_SIG_Proactor) : Test for + ACE_Proactor which uses real time signal based completion + strategy proactor. (#define ACE_POSIX_SIG_PROACTOR) + + + +Behavior of POSIX AIO of various platforms: +========================================== + +Aio_Platform_Test: +================ + + +Sun5.6 CC: +--------- + Status : OK + + Problems: 1.The constant which indicates the maximum + concurrent asynchronous I/Os is -1 at run + time. This should be atleast 1. + +Sun57 CC: +-------- + Status : OK + + Problems: <Same as in sun56 CC> + +Lynx g++: +-------- + Status : OK + + Problems: AIO_LISTIO_MAX, AIO_MAX and SIGQUEUE_MAX are defined + but their values are -1 + +test_aiocb.cpp +============= + +Sun5.6 CC: +--------- + Status : GOOD + + Problems: NONE + +Sun57 CC: +-------- + Status : GOOD + + Problems: NONE + +Lynx g++: +-------- + + + +test_aiosig.cpp: +=============== + +Sun5.6 CC: +--------- + Status : GOOD + + Problems: NONE + +Sun57 CC: +-------- + Status : BAD + + Problems: 1. If 2 <aio_> calls are issed, only one completion + gets through, second one hangs. + +Lynx g++: +-------- + + + +test_aiosig_ace.cpp: +==================== + +Sun5.6 CC: +--------- + Status : BAD + + Problems: 1. <aio_read> and <aio_write> calls return 0 but + sets the<errno> to 48 which is <Operation Not + Supported> + + 2. I issue <aio_read/write> with a RT signal enabled. It + returns but with the a wrong signal code, -2, which is + SI_QUEUE. But we are supposed to get SI_ASYNCIO + + 3*.IMPORTANT: If I issue two <aio_read/write> calls, + they get queued and + they execute correctly. But their completions are not + queued up correctly. + + 4. Calling <sigtimedwait> sometimes print the string + "err = 22". But <sigtimedwait> doesnt return a error and + errno is also not set to any error values. (err == 22, may + be referring to errno 22 which means Invalid Argument) + +Sun57 CC: +-------- + Status : BAD + + Problems: <same as in sun56 CC> + +Lynx g++: +-------- + + Status : OK + + Problems: 1. In between my Proactor test application the + <errno> is getting set to <77>. This means + Unsupported POSIX operation. But none of my + <posix> calls return -1. + + TO-DO : 1. Run <gdb> and watch for <errno> and figure when + it is changing over to 77. + + diff --git a/examples/Reactor/Proactor/test_aiosig.cpp b/examples/Reactor/Proactor/test_aiosig.cpp new file mode 100644 index 00000000000..ff4c257af84 --- /dev/null +++ b/examples/Reactor/Proactor/test_aiosig.cpp @@ -0,0 +1,294 @@ +// $Id$ +// ============================================================================ +// +// = FILENAME +// test_aiosig.cpp +// +// = DESCRITPTION +// This program helps you to test the <aio_*> calls on a +// platform. +// Before running this test, make sure the platform can +// support POSIX <aio_> calls. use $ACE_ROOT/tests for this. +// This is for testing the Signal based completion approach which +// uses <sigtimedwait> for completion querying. +// If this test is successful, ACE_POSIX_SIG_PROACTOR +// can be used on this platform. +// This program is a C-language version of the +// $ACE_ROOT/examples/Reactor/Proactor/test_aiosig_ace.cpp, with +// all the ACE calls removed. +// This test does the following: +// Issue two <aio_read>s. +// Assign SIGRTMIN as the notification signal. +// Mask these signals from delivery. +// Receive this signal by doing <sigtimedwait>. +// Wait for two completions (two signals) +// +// = COMPILATION +// CC -g -o test_aiosig -lposix4 test_aiosig.cpp +// +// = RUN +// ./test_aiosig +// +// = AUTHOR +// Programming for the Real World. Bill O. GallMeister. +// Modified by Alexander Babu Arulanthu <alex@cs.wustl.edu> +// +// ===================================================================== + + +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#include <limits.h> + +#include <aio.h> + +int file_handle = -1; +char mb1 [BUFSIZ + 1]; +char mb2 [BUFSIZ + 1]; +aiocb aiocb1, aiocb2; +sigset_t completion_signal; + +// Function prototypes. +int setup_signal_delivery (void); +int issue_aio_calls (void); +int query_aio_completions (void); +int test_aio_calls (void); + +int +setup_signal_delivery (void) +{ + // Make the sigset_t consisting of the completion signal. + if (sigemptyset (&completion_signal) == -1) + { + perror ("Error:Couldnt init the RT completion signal set\n"); + return -1; + } + + if (sigaddset (&completion_signal, SIGRTMIN) == -1) + { + perror ("Error:Couldnt init the RT completion signal set\n"); + return -1; + } + + // Mask them. + if (sigprocmask (SIG_BLOCK, &completion_signal, 0) == -1) + { + perror ("Error:Couldnt maks the RT completion signals\n"); + return -1; + } + + // Setting up the handler(!) for these signals. + struct sigaction reaction; + sigemptyset (&reaction.sa_mask); // Nothing else to mask. + reaction.sa_flags = SA_SIGINFO; // Realtime flag. +#if defined (SA_SIGACTION) + // Lynx says, it is better to set this bit to be portable. + reaction.sa_flags &= SA_SIGACTION; +#endif /* SA_SIGACTION */ + reaction.sa_sigaction = 0; // No handler. + int sigaction_return = sigaction (SIGRTMIN, + &reaction, + 0); + if (sigaction_return == -1) + { + perror ("Error:Proactor couldnt do sigaction for the RT SIGNAL"); + return -1; + } + + return 0; +} + +int +issue_aio_calls (void) +{ + // Setup AIOCB. + aiocb1.aio_fildes = file_handle; + aiocb1.aio_offset = 0; + aiocb1.aio_buf = mb1; + aiocb1.aio_nbytes = BUFSIZ; + aiocb1.aio_reqprio = 0; + aiocb1.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + aiocb1.aio_sigevent.sigev_signo = SIGRTMIN; + aiocb1.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb1; + + // Fire off the aio write. + if (aio_read (&aiocb1) == -1) + { + // Queueing failed. + perror ("Error:Asynch_Read_Stream: aio_read queueing failed\n"); + return -1; + } + + // Setup AIOCB. + aiocb2.aio_fildes = file_handle; + aiocb2.aio_offset = BUFSIZ + 1; + aiocb2.aio_buf = mb2; + aiocb2.aio_nbytes = BUFSIZ; + aiocb2.aio_reqprio = 0; + aiocb2.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + aiocb2.aio_sigevent.sigev_signo = SIGRTMIN; + aiocb2.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb2; + + // Fire off the aio write. + if (aio_read (&aiocb2) == -1) + { + // Queueing failed. + perror ("Error:Asynch_Read_Stream: aio_read queueing failed\n"); + return -1; + } + return 0; +} + +int +query_aio_completions (void) +{ + int result = 0; + size_t number_of_compleions = 0; + for (number_of_compleions = 0; + number_of_compleions < 2; + number_of_compleions ++) + { + // Wait for <milli_seconds> amount of time. + // @@ Assigning <milli_seconds> to tv_sec. + timespec timeout; + timeout.tv_sec = INT_MAX; + timeout.tv_nsec = 0; + + // To get back the signal info. + siginfo_t sig_info; + + // Await the RT completion signal. + int sig_return = sigtimedwait (&completion_signal, + &sig_info, + &timeout); + + // Error case. + // If failure is coz of timeout, then return *0* but set + // errno appropriately. This is what the WinNT proactor + // does. + if (sig_return == -1) + { + perror ("Error:Error waiting for RT completion signals\n"); + return -1; + } + + // RT completion signals returned. + if (sig_return != SIGRTMIN) + { + printf ("Unexpected signal (%d) has been received while waiting for RT Completion Signals\n", + sig_return); + return -1; + } + + // @@ Debugging. + printf ("Sig number found in the sig_info block : %d\n", + sig_info.si_signo); + + // Is the signo returned consistent? + if (sig_info.si_signo != sig_return) + { + printf ("Inconsistent signal number (%d) in the signal info block\n", + sig_info.si_signo); + return -1; + } + + // @@ Debugging. + printf ("Signal code for this signal delivery : %d\n", + sig_info.si_code); + + // Is the signal code an aio completion one? + if ((sig_info.si_code != SI_ASYNCIO) && + (sig_info.si_code != SI_QUEUE)) + { + printf ("Unexpected signal code (%d) returned on completion querying\n", + sig_info.si_code); + return -1; + } + + // Retrive the aiocb. + aiocb* aiocb_ptr = (aiocb *) sig_info.si_value.sival_ptr; + + // Analyze error and return values. Return values are + // actually <errno>'s associated with the <aio_> call + // corresponding to aiocb_ptr. + int error_code = aio_error (aiocb_ptr); + if (error_code == -1) + { + perror ("Error:Invalid control block was sent to <aio_error> for compleion querying\n"); + return -1; + } + + if (error_code != 0) + { + // Error occurred in the <aio_>call. Return the errno + // corresponding to that <aio_> call. + printf ("Error:An AIO call has failed:Error code = %d\n", + error_code); + return -1; + } + + // No error occured in the AIO operation. + int nbytes = aio_return (aiocb_ptr); + if (nbytes == -1) + { + perror ("Error:Invalid control block was send to <aio_return>\n"); + return -1; + } + + if (number_of_compleions == 0) + // Print the buffer. + printf ("Number of bytes transferred : %d\n The buffer : %s \n", + nbytes, + mb1); + else + // Print the buffer. + printf ("Number of bytes transferred : %d\n The buffer : %s \n", + nbytes, + mb2); + } + return 0; +} + +int +test_aio_calls (void) +{ + // Set up the input file. + // Open file (in SEQUENTIAL_SCAN mode) + file_handle = open ("test_aiosig.cpp", O_RDONLY); + + if (file_handle == -1) + { + perror ("Error:Opening the inputfile"); + return -1; + } + + if (setup_signal_delivery () < 0) + return -1; + + if (issue_aio_calls () < 0) + return -1; + + if (query_aio_completions () < 0) + return -1; + + return 0; +} + +int +main (int, char *[]) +{ + if (test_aio_calls () == 0) + printf ("RT SIG test successful:\n" + "ACE_POSIX_SIG_PROACTOR should work in this platform\n"); + else + printf ("RT SIG test failed:\n" + "ACE_POSIX_SIG_PROACTOR may not work in this platform\n"); + return 0; +} diff --git a/examples/Reactor/Proactor/test_aiosig_ace.cpp b/examples/Reactor/Proactor/test_aiosig_ace.cpp new file mode 100644 index 00000000000..09094727629 --- /dev/null +++ b/examples/Reactor/Proactor/test_aiosig_ace.cpp @@ -0,0 +1,273 @@ +// $Id$ +// ============================================================================ +// +// = FILENAME +// test_aiosig_sig.cpp +// +// = DESCRITPTION +// This program helps you to test the <aio_*> calls on a +// platform. +// Before running this test, make sure the platform can +// support POSIX <aio_> calls. use $ACE_ROOT/tests for this. +// This is for testing the Signal based completion approach which +// uses <sigtimedwait> for completion querying. +// If this test is successful, ACE_POSIX_SIG_PROACTOR +// can be used on this platform. +// This program is a ACE version of the +// $ACE_ROOT/examples/Reactor/Proactor/test_aiosig.cpp, with +// ACE_DEBUGs and Message_Blocks. +// This test does the following: +// Issue two <aio_read>s. +// Assign SIGRTMIN as the notification signal. +// Mask these signals from delivery. +// Receive this signal by doing <sigtimedwait>. +// Wait for two completions (two signals) +// +// = COMPILATION +// make +// +// = RUN +// ./test_aiosig_ace +// +// = AUTHOR +// Programming for the Real World. Bill O. GallMeister. +// Modified by Alexander Babu Arulanthu <alex@cs.wustl.edu> +// +// ===================================================================== + +#include "ace/Message_Block.h" + +static ACE_HANDLE file_handle = ACE_INVALID_HANDLE; +static ACE_Message_Block mb1 (BUFSIZ + 1); +static ACE_Message_Block mb2 (BUFSIZ + 1); +static aiocb aiocb1; +static aiocb aiocb2; +static sigset_t completion_signal; + +// Function prototypes. +static int setup_signal_delivery (void); +static int issue_aio_calls (void); +static int query_aio_completions (void); +static int test_aio_calls (void); + +static int +setup_signal_delivery (void) +{ + // Make the sigset_t consisting of the completion signal. + if (sigemptyset (&completion_signal) < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p:Couldnt init the RT completion signal set\n"), + -1); + + if (sigaddset (&completion_signal, + SIGRTMIN) < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p:Couldnt init the RT completion signal set\n"), + -1); + + // Mask them. + if (sigprocmask (SIG_BLOCK, &completion_signal, 0) < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p:Couldnt maks the RT completion signals\n"), + -1); + + // Setting up the handler(!) for these signals. + struct sigaction reaction; + sigemptyset (&reaction.sa_mask); // Nothing else to mask. + reaction.sa_flags = SA_SIGINFO; // Realtime flag. +#if defined (SA_SIGACTION) + // Lynx says, it is better to set this bit to be portable. + reaction.sa_flags &= SA_SIGACTION; +#endif /* SA_SIGACTION */ + reaction.sa_sigaction = 0; // No handler. + int sigaction_return = sigaction (SIGRTMIN, + &reaction, + 0); + if (sigaction_return == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p:Proactor couldnt do sigaction for the RT SIGNAL"), + -1); + return 0; +} + +static int +issue_aio_calls (void) +{ + // Setup AIOCB. + aiocb1.aio_fildes = file_handle; + aiocb1.aio_offset = 0; + aiocb1.aio_buf = mb1.wr_ptr (); + aiocb1.aio_nbytes = BUFSIZ; + aiocb1.aio_reqprio = 0; + aiocb1.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + aiocb1.aio_sigevent.sigev_signo = SIGRTMIN; + aiocb1.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb1; + + // Fire off the aio write. + if (aio_read (&aiocb1) == -1) + // Queueing failed. + ACE_ERROR_RETURN ((LM_ERROR, + "Erro:%p:Asynch_Read_Stream: aio_read queueing failed\n"), + -1); + + // Setup AIOCB. + aiocb2.aio_fildes = file_handle; + aiocb2.aio_offset = BUFSIZ + 1; + aiocb2.aio_buf = mb2.wr_ptr (); + aiocb2.aio_nbytes = BUFSIZ; + aiocb2.aio_reqprio = 0; + aiocb2.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + aiocb2.aio_sigevent.sigev_signo = SIGRTMIN; + aiocb2.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb2; + + // Fire off the aio write. + if (aio_read (&aiocb2) == -1) + // Queueing failed. + ACE_ERROR_RETURN ((LM_ERROR, + "Erro:%p:Asynch_Read_Stream: aio_read queueing failed\n"), + -1); + + return 0; +} + +static int +query_aio_completions (void) +{ + for (size_t number_of_compleions = 0; + number_of_compleions < 2; + number_of_compleions ++) + { + // Wait for <milli_seconds> amount of time. @@ Assigning + // <milli_seconds> to tv_sec. + timespec timeout; + timeout.tv_sec = ACE_INFINITE; + timeout.tv_nsec = 0; + + // To get back the signal info. + siginfo_t sig_info; + + // Await the RT completion signal. + int sig_return = sigtimedwait (&completion_signal, + &sig_info, + &timeout); + + // Error case. + // If failure is coz of timeout, then return *0* but set + // errno appropriately. This is what the WinNT proactor + // does. + if (sig_return == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "Error:%p:Error waiting for RT completion signals\n"), + 0); + + // RT completion signals returned. + if (sig_return != SIGRTMIN) + ACE_ERROR_RETURN ((LM_ERROR, + "Unexpected signal (%d) has been received while waiting for RT Completion Signals\n", + sig_return), + -1); + + // @@ Debugging. + ACE_DEBUG ((LM_DEBUG, + "Sig number found in the sig_info block : %d\n", + sig_info.si_signo)); + + // Is the signo returned consistent? + if (sig_info.si_signo != sig_return) + ACE_ERROR_RETURN ((LM_ERROR, + "Inconsistent signal number (%d) in the signal info block\n", + sig_info.si_signo), + -1); + + // @@ Debugging. + ACE_DEBUG ((LM_DEBUG, + "Signal code for this signal delivery : %d\n", + sig_info.si_code)); + + // Is the signal code an aio completion one? + if ((sig_info.si_code != SI_ASYNCIO) && + (sig_info.si_code != SI_QUEUE)) + ACE_ERROR_RETURN ((LM_DEBUG, + "Unexpected signal code (%d) returned on completion querying\n", + sig_info.si_code), + -1); + + // Retrive the aiocb. + aiocb* aiocb_ptr = (aiocb *) sig_info.si_value.sival_ptr; + + // Analyze error and return values. Return values are + // actually <errno>'s associated with the <aio_> call + // corresponding to aiocb_ptr. + int error_code = aio_error (aiocb_ptr); + if (error_code == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p:Invalid control block was sent to <aio_error> for compleion querying\n"), + -1); + + if (error_code != 0) + // Error occurred in the <aio_>call. Return the errno + // corresponding to that <aio_> call. + ACE_ERROR_RETURN ((LM_ERROR, + "%p:An AIO call has failed\n"), + error_code); + + // No error occured in the AIO operation. + int nbytes = aio_return (aiocb_ptr); + if (nbytes == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p:Invalid control block was send to <aio_return>\n"), + -1); + if (number_of_compleions == 0) + // Print the buffer. + ACE_DEBUG ((LM_DEBUG, + "\n Number of bytes transferred : %d\n The buffer : %s \n", + nbytes, + mb1.rd_ptr ())); + else + // Print the buffer. + ACE_DEBUG ((LM_DEBUG, + "\n Number of bytes transferred : %d\n The buffer : %s \n", + nbytes, + mb2.rd_ptr ())); + } + + return 0; +} + +static int +test_aio_calls (void) +{ + // Set up the input file. + // Open file (in SEQUENTIAL_SCAN mode) + file_handle = ACE_OS::open ("test_aiosig_ace.cpp", + O_RDONLY); + + if (file_handle == ACE_INVALID_HANDLE) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "ACE_OS::open"), + -1); + + if (setup_signal_delivery () < 0) + return -1; + + if (issue_aio_calls () < 0) + return -1; + + if (query_aio_completions () < 0) + return -1; + + return 0; +} + +int +main (int, char *[]) +{ + if (test_aio_calls () == 0) + printf ("RT SIG test successful:\n" + "ACE_POSIX_SIG_PROACTOR should work in this platform\n"); + else + printf ("RT SIG test failed:\n" + "ACE_POSIX_SIG_PROACTOR may not work in this platform\n"); + return 0; +} |