diff options
Diffstat (limited to 'ACE/examples/Reactor/Proactor/test_aiosig.cpp')
-rw-r--r-- | ACE/examples/Reactor/Proactor/test_aiosig.cpp | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/ACE/examples/Reactor/Proactor/test_aiosig.cpp b/ACE/examples/Reactor/Proactor/test_aiosig.cpp new file mode 100644 index 00000000000..1746a10a49c --- /dev/null +++ b/ACE/examples/Reactor/Proactor/test_aiosig.cpp @@ -0,0 +1,294 @@ +// $Id$ +// ============================================================================ +// +// = FILENAME +// test_aiosig.cpp +// +// = DESCRITPTION +// Check out test_aiosig_ace.cpp, the ACE'ified version of this +// program. This program may not be uptodate. +// +// = COMPILATION +// CC -g -o test_aiosig -lrt 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_handler (void); +int setup_signal_handler (int signal_number); + +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 (pthread_sigmask (SIG_BLOCK, &completion_signal, 0) == -1) + { + perror ("Error:Couldnt maks the RT completion signals\n"); + return -1; + } + + return setup_signal_handler (SIGRTMIN); +} + +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 +setup_signal_handler (int signal_number) +{ + // 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 = null_handler; // Null 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; +} + +void +null_handler (int /* signal_number */, + siginfo_t * /* info */, + void * /* context */) +{ +} + +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; +} |