int main(int argc, char *argv[]) { char *buf; int done[NUMOPS]; int fd[NUMOPS]; int i; int numbytes, numfiles; if (argc < 2) { fprintf(stderr, "Usage: %s filename1 filename2 ...\n", argv[0]); return 1; } else if (argc > NUMOPS + 1) { fprintf(stderr, "%s: only supports %d simultaneous operations\n", argv[0], NUMOPS); return 1; } numfiles = argc - 1; for (i = 0; i < numfiles; i++) { /* set up the I/O operations */ done[i] = 0; if ((fd[i] = open(argv[i+1], O_RDONLY)) == -1) { fprintf(stderr, "Failed to open %s:%s\n", argv[i+1], strerror(errno)); return 1; } if (initaio(fd[i], i) == -1) { fprintf(stderr, "Failed to setup I/O op %d:%s\n", i, strerror(errno)); return 1; } if (readstart(i) == -1) { fprintf(stderr, "Failed to start read %d:%s\n", i, strerror(errno)); return 1; } } for ( ; ; ) { /* loop and poll */ dowork(); for (i = 0; i < numfiles; i++) { if (done[i]) continue; numbytes = readcheck(i, &buf); if ((numbytes == -1) && (errno == EINPROGRESS)) continue; if (numbytes <= 0) { if (numbytes == 0) fprintf(stderr, "End of file on %d\n", i); else fprintf(stderr, "Failed to read %d:%s\n", i, strerror(errno)); done[i] = 1; continue; } processbuffer(i, buf, numbytes); reinit(i); if (readstart(i) == -1) { fprintf(stderr, "Failed to start read %d:%s\n", i, strerror(errno)); done[i] = 1; } } } }
int initread(int fdread, int fdwrite, int signo, char *buf, int bufsize) { int error; sigset_t oldset, fullset; if ((sigfillset(&fullset) == -1) || (sigprocmask(SIG_SETMASK, &fullset, &oldset) == -1)) { seterror(errno); return -1; } aiocb.aio_fildes = fdread; /* set up structure */ aiocb.aio_offset = 0; aiocb.aio_buf = (void *)buf; aiocb.aio_nbytes = bufsize; aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; aiocb.aio_sigevent.sigev_signo = signo; aiocb.aio_sigevent.sigev_value.sival_ptr = &aiocb; fdout = fdwrite; doneflag = 0; globalerror = 0; totalbytes = 0; error = readstart(); /* start first read */ if (sigprocmask(SIG_SETMASK, &oldset, NULL) == -1) { seterror(errno); return -1; } return error; }
/* ARGSUSED */ static void aiohandler(int signo, siginfo_t *info, void *context) { int myerrno, mystatus, serrno; serrno = errno; myerrno = aio_error(&aiocb_read); if (myerrno == EINPROGRESS) { errno = serrno; return; } if (myerrno) { seterror(myerrno); errno = serrno; return; } mystatus = aio_return(&aiocb_read); totalbytes += mystatus; aiocb_read.aio_offset += mystatus; aiocb_write.aio_nbytes = mystatus; if (mystatus == 0) doneflag = 1; else if (aio_write(&aiocb_write) == -1) seterror(errno); else if (readstart() == -1) seterror(errno); errno = serrno; }