// $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 // // ===================================================================== #include #include #include #include #include #include #include #include #include #include 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 amount of time. // @@ Assigning 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 's associated with the call // corresponding to aiocb_ptr. int error_code = aio_error (aiocb_ptr); if (error_code == -1) { perror ("Error:Invalid control block was sent to for compleion querying\n"); return -1; } if (error_code != 0) { // Error occurred in the call. Return the errno // corresponding to that 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 \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; }