diff options
| author | root <root> | 2008-05-12 00:31:43 +0000 | 
|---|---|---|
| committer | root <root> | 2008-05-12 00:31:43 +0000 | 
| commit | acf608862a9af73453ba86c7e587f6137208ca33 (patch) | |
| tree | 63c63bd340296b55135a58138c3b38c0f0fac5fc | |
| parent | 501dd04e8b3d25c638e86ac9ba40395deee86d99 (diff) | |
*** empty log message ***rel-3_02
| -rw-r--r-- | demo.c | 223 | ||||
| -rw-r--r-- | eio.c | 562 | ||||
| -rw-r--r-- | eio.h | 50 | ||||
| -rw-r--r-- | libeio.m4 | 3 | 
4 files changed, 389 insertions, 449 deletions
| @@ -0,0 +1,223 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <poll.h> +#include <string.h> +#include <assert.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "eio.h" + +int respipe [2]; + +void +want_poll (void) +{ +  char dummy; +  printf ("want_poll ()\n"); +  write (respipe [1], &dummy, 1); +} + +void +done_poll (void) +{ +  char dummy; +  printf ("done_poll ()\n"); +  read (respipe [0], &dummy, 1); +} + +void +event_loop (void) +{ +  // an event loop. yeah. +  struct pollfd pfd; +  pfd.fd     = respipe [0]; +  pfd.events = POLLIN; + +  printf ("\nentering event loop\n"); +  while (eio_nreqs ()) +    { +      poll (&pfd, 1, -1); +      printf ("eio_poll () = %d\n", eio_poll ()); +    } +  printf ("leaving event loop\n"); +} + +int +res_cb (eio_req *req) +{ +  printf ("res_cb(%d|%s) = %d\n", req->type, req->data ? req->data : "?", EIO_RESULT (req)); + +  if (req->result < 0) +    abort (); + +  return 0; +} + +int +readdir_cb (eio_req *req) +{ +  char *buf = (char *)EIO_BUF (req); + +  printf ("readdir_cb = %d\n", EIO_RESULT (req)); + +  if (EIO_RESULT (req) < 0) +    return 0; + +  while (EIO_RESULT (req)--) +    { +      printf ("readdir = <%s>\n", buf); +      buf += strlen (buf) + 1; +    } + +  return 0; +} + +int +stat_cb (eio_req *req) +{ +  struct stat *buf = EIO_STAT_BUF (req); + +  if (req->type == EIO_FSTAT) +    printf ("fstat_cb = %d\n", EIO_RESULT (req)); +  else +    printf ("stat_cb(%s) = %d\n", EIO_PATH (req), EIO_RESULT (req)); + +  if (!EIO_RESULT (req)) +    printf ("stat size %d perm 0%o\n", buf->st_size, buf->st_mode & 0777); + +  return 0; +} + +int +read_cb (eio_req *req) +{ +  unsigned char *buf = (unsigned char *)EIO_BUF (req); + +  printf ("read_cb = %d (%02x%02x%02x%02x %02x%02x%02x%02x)\n", +          EIO_RESULT (req), +          buf [0], buf [1], buf [2], buf [3], +          buf [4], buf [5], buf [6], buf [7]); + +  return 0; +} + +int last_fd; + +int +open_cb (eio_req *req) +{ +  printf ("open_cb = %d\n", EIO_RESULT (req)); + +  last_fd = EIO_RESULT (req); + +  return 0; +} + +int +main (void) +{ +  printf ("pipe ()\n"); +  if (pipe (respipe)) abort (); + +  printf ("eio_init ()\n"); +  if (eio_init (want_poll, done_poll)) abort (); + +  do +    { +      /* avoid relative paths yourself(!) */ +      eio_mkdir ("eio-test-dir", 0777, res_cb) +        ->data = "mkdir"; +      eio_nop (res_cb) +        ->data = "nop"; +      event_loop (); + +      eio_stat ("eio-test-dir", stat_cb); +      eio_lstat ("eio-test-dir", stat_cb); +      eio_open ("eio-test-dir/eio-test-file", O_RDWR | O_CREAT, 0777, open_cb); +      eio_symlink ("test", "eio-test-dir/eio-symlink", res_cb) +        ->data = "symlink"; +      eio_mknod ("eio-test-dir/eio-fifo", S_IFIFO, 0, res_cb) +        ->data = "mknod"; +      event_loop (); + +      eio_utime ("eio-test-dir", 12345.678, 23456.789, res_cb) +        ->data = "utime"; +      eio_futime (last_fd, 92345.678, 93456.789, res_cb) +        ->data = "futime"; +      eio_chown ("eio-test-dir", getuid (), getgid (), res_cb) +        ->data = "chown"; +      eio_fchown (last_fd, getuid (), getgid (), res_cb) +        ->data = "fchown"; +      eio_fchmod (last_fd, 0123, res_cb) +        ->data = "fchmod"; +      eio_readdir ("eio-test-dir", readdir_cb); +      eio_readdir ("/nonexistant", readdir_cb); +      eio_fstat (last_fd, stat_cb); +      eio_write (last_fd, "test\nfail\n", 10, 4, res_cb) +        ->data = "write"; +      event_loop (); + +      eio_read (last_fd, 0, 8, 0, read_cb); +      eio_readlink ("eio-test-dir/eio-symlink", res_cb) +        ->data = "readlink"; +      event_loop (); + +      eio_dup2 (1, 2, res_cb) // dup stdout to stderr +        ->data = "dup2"; +      eio_chmod ("eio-test-dir", 0765, res_cb) +        ->data = "chmod"; +      eio_ftruncate (last_fd, 9, res_cb) +        ->data = "ftruncate"; +      eio_fdatasync (last_fd, res_cb) +        ->data = "fdatasync"; +      eio_fsync (last_fd, res_cb) +        ->data = "fsync"; +      eio_sync (res_cb) +        ->data = "sync"; +      eio_busy (0.5, res_cb) +        ->data = "busy"; +      event_loop (); + +      eio_sendfile (1, last_fd, 4, 5, res_cb) // write "test\n" to stdout +        ->data = "sendfile"; +      eio_fstat (last_fd, stat_cb); +      event_loop (); + +      eio_truncate ("eio-test-dir/eio-test-file", 6, res_cb) +        ->data = "truncate"; +      eio_readahead (last_fd, 0, 64, res_cb) +        ->data = "readahead"; +      event_loop (); + +      eio_close (last_fd, res_cb) +        ->data = "close"; +      eio_link ("eio-test-dir/eio-test-file", "eio-test-dir/eio-test-file-2", res_cb) +        ->data = "link"; +      event_loop (); + +      eio_rename ("eio-test-dir/eio-test-file", "eio-test-dir/eio-test-file-renamed", res_cb) +        ->data = "rename"; +      event_loop (); + +      eio_unlink ("eio-test-dir/eio-fifo", res_cb) +        ->data = "unlink"; +      eio_unlink ("eio-test-dir/eio-symlink", res_cb) +        ->data = "unlink"; +      eio_unlink ("eio-test-dir/eio-test-file-2", res_cb) +        ->data = "unlink"; +      eio_unlink ("eio-test-dir/eio-test-file-renamed", res_cb) +        ->data = "unlink"; +      event_loop (); + +      eio_rmdir ("eio-test-dir", res_cb) +        ->data = "rmdir"; +      event_loop (); +    } +  while (0); + +  return 0; +} + @@ -44,10 +44,6 @@  #endif -# ifndef EIO_STRUCT_STAT -#  define EIO_STRUCT_STAT struct stat -# endif -  #if HAVE_SENDFILE  # if __linux  #  include <sys/sendfile.h> @@ -79,6 +75,7 @@    X_LOCK (wrklock);				\    self->dbuf = eio_buf = malloc (EIO_BUFSIZE);	\    X_UNLOCK (wrklock);				\ +  errno = ENOMEM;				\    if (!eio_buf)					\      return -1; @@ -97,12 +94,13 @@ static int tvdiff (struct timeval *tv1, struct timeval *tv2)         + ((tv2->tv_usec - tv1->tv_usec) >> 10);  } -static unsigned int started, idle, wanted; +static unsigned int started, idle, wanted = 4;  /* worker threads management */  static mutex_t wrklock = X_MUTEX_INIT; -typedef struct worker { +typedef struct worker +{    /* locked by wrklock */    struct worker *prev, *next; @@ -328,7 +326,7 @@ static void start_thread (void)    worker *wrk = calloc (1, sizeof (worker));    /*TODO*/ -  assert (("unable to allocate worker thread data", !wrk)); +  assert (("unable to allocate worker thread data", wrk));    X_LOCK (wrklock); @@ -487,8 +485,8 @@ int eio_poll (void)  /* work around various missing functions */  #if !HAVE_PREADWRITE -# define pread  aio_pread -# define pwrite aio_pwrite +# define pread  eio__pread +# define pwrite eio__pwrite  /*   * make our pread/pwrite safe against themselves, but not against @@ -497,7 +495,8 @@ int eio_poll (void)   */  static mutex_t preadwritelock = X_MUTEX_INIT; -static ssize_t pread (int fd, void *buf, size_t count, off_t offset) +static ssize_t +eio__pread (int fd, void *buf, size_t count, off_t offset)  {    ssize_t res;    off_t ooffset; @@ -512,7 +511,8 @@ static ssize_t pread (int fd, void *buf, size_t count, off_t offset)    return res;  } -static ssize_t pwrite (int fd, void *buf, size_t count, off_t offset) +static ssize_t +eio__pwrite (int fd, void *buf, size_t count, off_t offset)  {    ssize_t res;    off_t ooffset; @@ -530,10 +530,11 @@ static ssize_t pwrite (int fd, void *buf, size_t count, off_t offset)  #ifndef HAVE_FUTIMES -# define utimes(path,times)  aio_utimes  (path, times) -# define futimes(fd,times)   aio_futimes (fd, times) +# define utimes(path,times)  eio__utimes  (path, times) +# define futimes(fd,times)   eio__futimes (fd, times) -static int aio_utimes (const char *filename, const struct timeval times[2]) +static int +eio__utimes (const char *filename, const struct timeval times[2])  {    if (times)      { @@ -548,7 +549,7 @@ static int aio_utimes (const char *filename, const struct timeval times[2])      return utime (filename, 0);  } -static int aio_futimes (int fd, const struct timeval tv[2]) +static int eio__futimes (int fd, const struct timeval tv[2])  {    errno = ENOSYS;    return -1; @@ -561,9 +562,10 @@ static int aio_futimes (int fd, const struct timeval tv[2])  #endif  #if !HAVE_READAHEAD -# define readahead(fd,offset,count) aio_readahead (fd, offset, count, self) +# define readahead(fd,offset,count) eio__readahead (fd, offset, count, self) -static ssize_t aio_readahead (int fd, off_t offset, size_t count, worker *self) +static ssize_t +eio__readahead (int fd, off_t offset, size_t count, worker *self)  {    size_t todo = count;    dBUF; @@ -584,11 +586,12 @@ static ssize_t aio_readahead (int fd, off_t offset, size_t count, worker *self)  #endif  #if !HAVE_READDIR_R -# define readdir_r aio_readdir_r +# define readdir_r eio__readdir_r  static mutex_t readdirlock = X_MUTEX_INIT; -static int readdir_r (DIR *dirp, EIO_STRUCT_DIRENT *ent, EIO_STRUCT_DIRENT **res) +static int +eio__readdir_r (DIR *dirp, EIO_STRUCT_DIRENT *ent, EIO_STRUCT_DIRENT **res)  {    EIO_STRUCT_DIRENT *e;    int errorno; @@ -614,7 +617,8 @@ static int readdir_r (DIR *dirp, EIO_STRUCT_DIRENT *ent, EIO_STRUCT_DIRENT **res  #endif  /* sendfile always needs emulation */ -static ssize_t sendfile_ (int ofd, int ifd, off_t offset, size_t count, worker *self) +static ssize_t +eio__sendfile (int ofd, int ifd, off_t offset, size_t count, worker *self)  {    ssize_t res; @@ -707,7 +711,8 @@ static ssize_t sendfile_ (int ofd, int ifd, off_t offset, size_t count, worker *  }  /* read a full directory */ -static void scandir_ (eio_req *req, worker *self) +static void +eio__scandir (eio_req *req, worker *self)  {    DIR *dirp;    union @@ -845,8 +850,8 @@ X_THREAD_PROC (eio_proc)                                              ? pwrite    (req->int1, req->ptr2, req->size, req->offs)                                              : write     (req->int1, req->ptr2, req->size); break; -            case EIO_READAHEAD: req->result = readahead (req->int1, req->offs, req->size); break; -            case EIO_SENDFILE:  req->result = sendfile_ (req->int1, req->int2, req->offs, req->size, self); break; +            case EIO_READAHEAD: req->result = readahead     (req->int1, req->offs, req->size); break; +            case EIO_SENDFILE:  req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size, self); break;              case EIO_STAT:      ALLOC (sizeof (EIO_STRUCT_STAT));                                  req->result = stat      (req->ptr1, (EIO_STRUCT_STAT *)req->ptr2); break; @@ -880,7 +885,7 @@ X_THREAD_PROC (eio_proc)              case EIO_FSYNC:     req->result = fsync     (req->int1); break;              case EIO_FDATASYNC: req->result = fdatasync (req->int1); break; -            case EIO_READDIR:   scandir_ (req, self); break; +            case EIO_READDIR:   eio__scandir (req, self); break;              case EIO_BUSY:  #ifdef _WIN32 @@ -923,6 +928,7 @@ X_THREAD_PROC (eio_proc)              case EIO_GROUP:              case EIO_NOP: +              req->result = 0;                break;              case EIO_QUIT: @@ -1045,528 +1051,210 @@ static void eio_api_destroy (eio_req *req)    if (!req)                                                     \      return 0;                                                   \                                                                  \ -  req->type = EIO_ ## rtype;                                    \ +  req->type = rtype;                                            \    req->pri = EIO_DEFAULT_PRI + EIO_PRI_BIAS;                    \    req->finish = cb;						\    req->destroy = eio_api_destroy;  #define SEND eio_submit (req); return req -#define PATH (void)0 +#define PATH							\ +  req->flags |= EIO_FLAG_PTR1_FREE;				\ +  req->ptr1 = strdup (path);					\ +  if (!req->ptr1)						\ +    {								\ +      eio_api_destroy (req);					\ +      return 0;							\ +    } + +eio_req *eio_nop (eio_cb cb) +{ +  REQ (EIO_NOP); SEND; +} + +eio_req *eio_busy (double delay, eio_cb cb) +{ +  REQ (EIO_BUSY); req->nv1 = delay; SEND; +} + +eio_req *eio_sync (eio_cb cb) +{ +  REQ (EIO_SYNC); SEND; +}  eio_req *eio_fsync (int fd, eio_cb cb)  { -  REQ (FSYNC); req->int1 = fd; SEND; +  REQ (EIO_FSYNC); req->int1 = fd; SEND;  }  eio_req *eio_fdatasync (int fd, eio_cb cb)  { -  REQ (FDATASYNC); req->int1 = fd; SEND; +  REQ (EIO_FDATASYNC); req->int1 = fd; SEND; +} + +eio_req *eio_close (int fd, eio_cb cb) +{ +  REQ (EIO_CLOSE); req->int1 = fd; SEND;  }  eio_req *eio_readahead (int fd, off_t offset, size_t length, eio_cb cb)  { -  REQ (READAHEAD); req->int1 = fd; req->offs = offset; req->size = length; SEND; +  REQ (EIO_READAHEAD); req->int1 = fd; req->offs = offset; req->size = length; SEND;  } -eio_req *eio_read (int fd, off_t offset, size_t length, void *data, eio_cb cb) +eio_req *eio_read (int fd, void *data, size_t length, off_t offset, eio_cb cb)  { -  REQ (READ); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = data; SEND; +  REQ (EIO_READ); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = data; SEND;  } -eio_req *eio_write (int fd, off_t offset, size_t length, void *data, eio_cb cb) +eio_req *eio_write (int fd, void *data, size_t length, off_t offset, eio_cb cb)  { -  REQ (WRITE); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = data; SEND; +  REQ (EIO_WRITE); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = data; SEND;  }  eio_req *eio_fstat (int fd, eio_cb cb)  { -  REQ (FSTAT); req->int1 = fd; SEND; +  REQ (EIO_FSTAT); req->int1 = fd; SEND;  }  eio_req *eio_futime (int fd, double atime, double mtime, eio_cb cb)  { -  REQ (FUTIME); req->int1 = fd; req->nv1 = atime; req->nv2 = mtime; SEND; +  REQ (EIO_FUTIME); req->int1 = fd; req->nv1 = atime; req->nv2 = mtime; SEND;  }  eio_req *eio_ftruncate (int fd, off_t offset, eio_cb cb)  { -  REQ (FTRUNCATE); req->int1 = fd; req->offs = offset; SEND; +  REQ (EIO_FTRUNCATE); req->int1 = fd; req->offs = offset; SEND;  }  eio_req *eio_fchmod (int fd, mode_t mode, eio_cb cb)  { -  REQ (FCHMOD); req->int1 = fd; req->int2 = (long)mode; SEND; +  REQ (EIO_FCHMOD); req->int1 = fd; req->int2 = (long)mode; SEND;  }  eio_req *eio_fchown (int fd, uid_t uid, gid_t gid, eio_cb cb)  { -  REQ (FCHOWN); req->int1 = fd; req->int2 = (long)uid; req->int3 = (long)gid; SEND; +  REQ (EIO_FCHOWN); req->int1 = fd; req->int2 = (long)uid; req->int3 = (long)gid; SEND;  }  eio_req *eio_dup2 (int fd, int fd2, eio_cb cb)  { -  REQ (DUP2); req->int1 = fd; req->int2 = fd2; SEND; +  REQ (EIO_DUP2); req->int1 = fd; req->int2 = fd2; SEND;  }  eio_req *eio_sendfile (int out_fd, int in_fd, off_t in_offset, size_t length, eio_cb cb)  { -  REQ (SENDFILE); req->int1 = out_fd; req->int2 = in_fd; req->offs = in_offset; req->size = length; SEND; +  REQ (EIO_SENDFILE); req->int1 = out_fd; req->int2 = in_fd; req->offs = in_offset; req->size = length; SEND;  }  eio_req *eio_open (const char *path, int flags, mode_t mode, eio_cb cb)  { -  REQ (OPEN); PATH; req->int1 = flags; req->int2 = (long)mode; SEND; -} - -eio_req *eio_readlink (const char *path, eio_cb cb) -{ -  REQ (READLINK); PATH; SEND; -} - -eio_req *eio_stat (const char *path, eio_cb cb) -{ -  REQ (STAT); PATH; SEND; -} - -eio_req *eio_lstat (const char *path, eio_cb cb) -{ -  REQ (LSTAT); PATH; SEND; +  REQ (EIO_OPEN); PATH; req->int1 = flags; req->int2 = (long)mode; SEND;  }  eio_req *eio_utime (const char *path, double atime, double mtime, eio_cb cb)  { -  REQ (UTIME); PATH; req->nv1 = atime; req->nv2 = mtime; SEND; +  REQ (EIO_UTIME); PATH; req->nv1 = atime; req->nv2 = mtime; SEND;  }  eio_req *eio_truncate (const char *path, off_t offset, eio_cb cb)  { -  REQ (TRUNCATE); PATH; req->offs = offset; SEND; +  REQ (EIO_TRUNCATE); PATH; req->offs = offset; SEND;  }  eio_req *eio_chown (const char *path, uid_t uid, gid_t gid, eio_cb cb)  { -  REQ (CHOWN); PATH; req->int2 = (long)uid; req->int3 = (long)gid; SEND; +  REQ (EIO_CHOWN); PATH; req->int2 = (long)uid; req->int3 = (long)gid; SEND;  }  eio_req *eio_chmod (const char *path, mode_t mode, eio_cb cb)  { -  REQ (CHMOD); PATH; req->int2 = (long)mode; SEND; +  REQ (EIO_CHMOD); PATH; req->int2 = (long)mode; SEND;  }  eio_req *eio_mkdir (const char *path, mode_t mode, eio_cb cb)  { -  REQ (MKDIR); PATH; req->int2 = (long)mode; SEND; -} - -eio_req *eio_unlink (const char *path, eio_cb cb) -{ -  REQ (UNLINK); PATH; SEND; -} - -eio_req *eio_rmdir (const char *path, eio_cb cb) -{ -  REQ (RMDIR); PATH; SEND; -} - -eio_req *eio_readdir (const char *path, eio_cb cb) -{ -  REQ (READDIR); PATH; SEND; -} - -eio_req *eio_mknod (const char *path, mode_t mode, dev_t dev, eio_cb cb) -{ -  REQ (MKNOD); PATH; req->int2 = (long)mode; req->int2 = (long)dev; SEND; -} - -eio_req *eio_busy (double delay, eio_cb cb) -{ -  REQ (BUSY); req->nv1 = delay; SEND; -} - -eio_req *eio_nop (eio_cb cb) -{ -  REQ (NOP); SEND; -} - -#undef REQ -#undef PATH -#undef SEND - -#if 0 - -void -aio_open (SV8 *pathname, int flags, int mode, SV *callback=&PL_sv_undef) -	PROTOTYPE: $$$;$ -	PPCODE: -{ -        dREQ; - -        req->type = EIO_OPEN; -        req->sv1  = newSVsv (pathname); -        req->ptr1 = SvPVbyte_nolen (req->sv1); -        req->int1 = flags; -        req->int2 = mode; - -        EIO_SEND; -} - -void -aio_fsync (SV *fh, SV *callback=&PL_sv_undef) -	PROTOTYPE: $;$ -        ALIAS: -           aio_fsync     = EIO_FSYNC -           aio_fdatasync = EIO_FDATASYNC -	PPCODE: -{ -        dREQ; - -        req->type = ix; -        req->sv1  = newSVsv (fh); -        req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); - -        EIO_SEND (req); -} - -void -aio_close (SV *fh, SV *callback=&PL_sv_undef) -	PROTOTYPE: $;$ -	PPCODE: -{ -        dREQ; - -        req->type = EIO_CLOSE; -        req->sv1  = newSVsv (fh); -        req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); - -        EIO_SEND (req); -} - -void -aio_read (SV *fh, SV *offset, SV *length, SV8 *data, IV dataoffset, SV *callback=&PL_sv_undef) -        ALIAS: -           aio_read  = EIO_READ -           aio_write = EIO_WRITE -	PROTOTYPE: $$$$$;$ -        PPCODE: -{ -        STRLEN svlen; -        char *svptr = SvPVbyte (data, svlen); -        UV len = SvUV (length); - -        SvUPGRADE (data, SVt_PV); -        SvPOK_on (data); - -        if (dataoffset < 0) -          dataoffset += svlen; - -        if (dataoffset < 0 || dataoffset > svlen) -          croak ("dataoffset outside of data scalar"); - -        if (ix == EIO_WRITE) -          { -            /* write: check length and adjust. */ -            if (!SvOK (length) || len + dataoffset > svlen) -              len = svlen - dataoffset; -          } -        else -          { -            /* read: grow scalar as necessary */ -            svptr = SvGROW (data, len + dataoffset + 1); -          } - -        if (len < 0) -          croak ("length must not be negative"); - -        { -          dREQ; - -          req->type = ix; -          req->sv1  = newSVsv (fh); -          req->int1 = PerlIO_fileno (ix == EIO_READ ? IoIFP (sv_2io (fh)) -                                                    : IoOFP (sv_2io (fh))); -          req->offs = SvOK (offset) ? SvVAL64 (offset) : -1; -          req->size = len; -          req->sv2  = SvREFCNT_inc (data); -          req->ptr2 = (char *)svptr + dataoffset; -          req->stroffset = dataoffset; - -          if (!SvREADONLY (data)) -            { -              SvREADONLY_on (data); -              req->flags |= FLAG_SV2_RO_OFF; -            } - -          EIO_SEND; -        } +  REQ (EIO_MKDIR); PATH; req->int2 = (long)mode; SEND;  } -void -aio_readlink (SV8 *path, SV *callback=&PL_sv_undef) -	PROTOTYPE: $$;$ -        PPCODE: +static eio_req * +eio__1path (int type, const char *path, eio_cb cb)  { -	SV *data; -        dREQ; - -        data = newSV (NAME_MAX); -        SvPOK_on (data); - -        req->type = EIO_READLINK; -        req->sv1  = newSVsv (path); -        req->ptr1 = SvPVbyte_nolen (req->sv1); -        req->sv2  = data; -        req->ptr2 = SvPVbyte_nolen (data); - -        EIO_SEND; +  REQ (type); PATH; SEND;  } -void -aio_sendfile (SV *out_fh, SV *in_fh, SV *in_offset, UV length, SV *callback=&PL_sv_undef) -	PROTOTYPE: $$$$;$ -        PPCODE: +eio_req *eio_readlink (const char *path, eio_cb cb)  { -	dREQ; - -        req->type = EIO_SENDFILE; -        req->sv1  = newSVsv (out_fh); -        req->int1 = PerlIO_fileno (IoIFP (sv_2io (out_fh))); -        req->sv2  = newSVsv (in_fh); -        req->int2 = PerlIO_fileno (IoIFP (sv_2io (in_fh))); -        req->offs = SvVAL64 (in_offset); -        req->size = length; - -        EIO_SEND; +  return eio__1path (EIO_READLINK, path, cb);  } -void -aio_readahead (SV *fh, SV *offset, IV length, SV *callback=&PL_sv_undef) -	PROTOTYPE: $$$;$ -        PPCODE: +eio_req *eio_stat (const char *path, eio_cb cb)  { -	dREQ; - -        req->type = EIO_READAHEAD; -        req->sv1  = newSVsv (fh); -        req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); -        req->offs = SvVAL64 (offset); -        req->size = length; - -        EIO_SEND; +  return eio__1path (EIO_STAT, path, cb);  } -void -aio_stat (SV8 *fh_or_path, SV *callback=&PL_sv_undef) -        ALIAS: -           aio_stat  = EIO_STAT -           aio_lstat = EIO_LSTAT -	PPCODE: +eio_req *eio_lstat (const char *path, eio_cb cb)  { -	dREQ; - -        req->ptr2 = malloc (sizeof (EIO_STRUCT_STAT)); -        if (!req->ptr2) -          { -            req_destroy (req); -            croak ("out of memory during aio_stat statdata allocation"); -          } - -        req->flags |= FLAG_PTR2_FREE; -        req->sv1 = newSVsv (fh_or_path); - -        if (SvPOK (fh_or_path)) -          { -            req->type = ix; -            req->ptr1 = SvPVbyte_nolen (req->sv1); -          } -        else -          { -            req->type = EIO_FSTAT; -            req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); -          } - -        EIO_SEND; +  return eio__1path (EIO_LSTAT, path, cb);  } -void -aio_utime (SV8 *fh_or_path, SV *atime, SV *mtime, SV *callback=&PL_sv_undef) -	PPCODE: +eio_req *eio_unlink (const char *path, eio_cb cb)  { -	dREQ; - -        req->nv1 = SvOK (atime) ? SvNV (atime) : -1.; -        req->nv2 = SvOK (mtime) ? SvNV (mtime) : -1.; -        req->sv1 = newSVsv (fh_or_path); - -        if (SvPOK (fh_or_path)) -          { -            req->type = EIO_UTIME; -            req->ptr1 = SvPVbyte_nolen (req->sv1); -          } -        else -          { -            req->type = EIO_FUTIME; -            req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); -          } - -        EIO_SEND; +  return eio__1path (EIO_UNLINK, path, cb);  } -void -aio_truncate (SV8 *fh_or_path, SV *offset, SV *callback=&PL_sv_undef) -	PPCODE: +eio_req *eio_rmdir (const char *path, eio_cb cb)  { -	dREQ; - -        req->sv1  = newSVsv (fh_or_path); -        req->offs = SvOK (offset) ? SvVAL64 (offset) : -1; - -        if (SvPOK (fh_or_path)) -          { -            req->type = EIO_TRUNCATE; -            req->ptr1 = SvPVbyte_nolen (req->sv1); -          } -        else -          { -            req->type = EIO_FTRUNCATE; -            req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); -          } - -        EIO_SEND; +  return eio__1path (EIO_RMDIR, path, cb);  } -void -aio_chmod (SV8 *fh_or_path, int mode, SV *callback=&PL_sv_undef) -	ALIAS: -        aio_chmod  = EIO_CHMOD -        aio_fchmod = EIO_FCHMOD -        aio_mkdir  = EIO_MKDIR -	PPCODE: +eio_req *eio_readdir (const char *path, eio_cb cb)  { -	dREQ; - -        req->type = type; -        req->int2 = mode; -        req->sv1  = newSVsv (fh_or_path); - -        if (ix == EIO_FCHMOD) -          req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); -        else -          req->ptr1 = SvPVbyte_nolen (req->sv1); - -        EIO_SEND; +  return eio__1path (EIO_READDIR, path, cb);  } -void -aio_chown (SV8 *fh_or_path, SV *uid, SV *gid, SV *callback=&PL_sv_undef) -	PPCODE: +eio_req *eio_mknod (const char *path, mode_t mode, dev_t dev, eio_cb cb)  { -	dREQ; - -        req->int2 = SvOK (uid) ? SvIV (uid) : -1; -        req->int3 = SvOK (gid) ? SvIV (gid) : -1; -        req->sv1  = newSVsv (fh_or_path); - -        if (SvPOK (fh_or_path)) -          { -            req->type = EIO_CHOWN; -            req->ptr1 = SvPVbyte_nolen (req->sv1); -          } -        else -          { -            req->type = EIO_FCHOWN; -            req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); -          } - -        EIO_SEND; +  REQ (EIO_MKNOD); PATH; req->int2 = (long)mode; req->int2 = (long)dev; SEND;  } -void -aio_unlink (SV8 *pathname, SV *callback=&PL_sv_undef) -        ALIAS: -           aio_unlink  = EIO_UNLINK -           aio_rmdir   = EIO_RMDIR -           aio_readdir = EIO_READDIR -	PPCODE: +static eio_req * +eio__2path (int type, const char *path, const char *new_path, eio_cb cb)  { -	dREQ; -	 -        req->type = ix; -	req->sv1  = newSVsv (pathname); -	req->ptr1 = SvPVbyte_nolen (req->sv1); +  REQ (type); PATH; -	EIO_SEND; -} +  req->flags |= EIO_FLAG_PTR2_FREE; +  req->ptr2 = strdup (new_path); +  if (!req->ptr2) +    { +      eio_api_destroy (req); +      return 0; +    } -void -aio_link (SV8 *oldpath, SV8 *newpath, SV *callback=&PL_sv_undef) -        ALIAS: -           aio_link    = EIO_LINK -           aio_symlink = EIO_SYMLINK -           aio_rename  = EIO_RENAME -	PPCODE: -{ -	dREQ; -	 -        req->type = ix; -	req->sv1  = newSVsv (oldpath); -	req->ptr1 = SvPVbyte_nolen (req->sv1); -	req->sv2  = newSVsv (newpath); -	req->ptr2 = SvPVbyte_nolen (req->sv2); -	 -	EIO_SEND; +  SEND;  } -void -aio_mknod (SV8 *pathname, int mode, UV dev, SV *callback=&PL_sv_undef) -	PPCODE: +eio_req *eio_link (const char *path, const char *new_path, eio_cb cb)  { -	dREQ; -	 -        req->type = EIO_MKNOD; -	req->sv1  = newSVsv (pathname); -	req->ptr1 = SvPVbyte_nolen (req->sv1); -        req->int2 = (mode_t)mode; -        req->offs = dev; -	 -	EIO_SEND; +  return eio__2path (EIO_LINK, path, new_path, cb);  } -void -aio_busy (double delay, SV *callback=&PL_sv_undef) -	PPCODE: +eio_req *eio_symlink (const char *path, const char *new_path, eio_cb cb)  { -	dREQ; - -        req->type = EIO_BUSY; -        req->nv1  = delay < 0. ? 0. : delay; - -	EIO_SEND; +  return eio__2path (EIO_SYMLINK, path, new_path, cb);  } -void -aio_group (SV *callback=&PL_sv_undef) -	PROTOTYPE: ;$ -        PPCODE: +eio_req *eio_rename (const char *path, const char *new_path, eio_cb cb)  { -	dREQ; - -        req->type = EIO_GROUP; - -        req_send (req); -        XPUSHs (req_sv (req, AIO_GRP_KLASS)); +  return eio__2path (EIO_RENAME, path, new_path, cb);  } -void -aio_nop (SV *callback=&PL_sv_undef) -	ALIAS: -           aio_nop  = EIO_NOP -           aio_sync = EIO_SYNC -	PPCODE: -{ -	dREQ; +#undef REQ +#undef PATH +#undef SEND -#endif +/*****************************************************************************/ +/* grp functions */  void eio_grp_feed (eio_req *grp, void (*feed)(eio_req *req), int limit)  { @@ -1599,4 +1287,18 @@ void eio_grp_add (eio_req *grp, eio_req *req)    grp->grp_first = req;  } +/*****************************************************************************/ +/* misc garbage */ + +ssize_t eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count) +{ +  worker wrk; + +  wrk.dbuf = 0; + +  eio__sendfile (ofd, ifd, offset, count, &wrk); + +  if (wrk.dbuf) +    free (wrk.dbuf); +} @@ -12,6 +12,10 @@ typedef int (*eio_cb)(eio_req *req);  # define EIO_COMMON void *data  #endif +#ifndef EIO_STRUCT_STAT +# define EIO_STRUCT_STAT struct stat +#endif +  enum {    EIO_QUIT,    EIO_OPEN, EIO_CLOSE, EIO_DUP2, @@ -110,11 +114,15 @@ unsigned int eio_nthreads (void); /* number of worker threads in use currently *  /*****************************************************************************/  /* high-level request API */ +eio_req *eio_nop       (eio_cb cb); /* does nothing except go through the whole process */ +eio_req *eio_busy      (eio_tstamp delay, eio_cb cb); /* ties a thread for this long, simulating busyness */ +eio_req *eio_sync      (eio_cb cb);  eio_req *eio_fsync     (int fd, eio_cb cb);  eio_req *eio_fdatasync (int fd, eio_cb cb); +eio_req *eio_close     (int fd, eio_cb cb);  eio_req *eio_readahead (int fd, off_t offset, size_t length, eio_cb cb); -eio_req *eio_read      (int fd, off_t offset, size_t length, void *data, eio_cb cb); -eio_req *eio_write     (int fd, off_t offset, size_t length, void *data, eio_cb cb); +eio_req *eio_read      (int fd, void *data, size_t length, off_t offset, eio_cb cb); +eio_req *eio_write     (int fd, void *data, size_t length, off_t offset, eio_cb cb);  eio_req *eio_fstat     (int fd, eio_cb cb); /* stat buffer=ptr2 allocated dynamically */  eio_req *eio_futime    (int fd, eio_tstamp atime, eio_tstamp mtime, eio_cb cb);  eio_req *eio_ftruncate (int fd, off_t offset, eio_cb cb); @@ -123,20 +131,21 @@ eio_req *eio_fchown    (int fd, uid_t uid, gid_t gid, eio_cb cb);  eio_req *eio_dup2      (int fd, int fd2, eio_cb cb);  eio_req *eio_sendfile  (int out_fd, int in_fd, off_t in_offset, size_t length, eio_cb cb);  eio_req *eio_open      (const char *path, int flags, mode_t mode, eio_cb cb); -eio_req *eio_readlink  (const char *path, eio_cb cb); /* result=ptr2 allocated dynamically */ -eio_req *eio_stat      (const char *path, eio_cb cb); /* stat buffer=ptr2 allocated dynamically */ -eio_req *eio_lstat     (const char *path, eio_cb cb); /* stat buffer=ptr2 allocated dynamically */  eio_req *eio_utime     (const char *path, eio_tstamp atime, eio_tstamp mtime, eio_cb cb);  eio_req *eio_truncate  (const char *path, off_t offset, eio_cb cb);  eio_req *eio_chown     (const char *path, uid_t uid, gid_t gid, eio_cb cb);  eio_req *eio_chmod     (const char *path, mode_t mode, eio_cb cb);  eio_req *eio_mkdir     (const char *path, mode_t mode, eio_cb cb); -eio_req *eio_unlink    (const char *path, eio_cb cb); -eio_req *eio_rmdir     (const char *path, eio_cb cb);  eio_req *eio_readdir   (const char *path, eio_cb cb); /* result=ptr2 allocated dynamically */ +eio_req *eio_rmdir     (const char *path, eio_cb cb); +eio_req *eio_unlink    (const char *path, eio_cb cb); +eio_req *eio_readlink  (const char *path, eio_cb cb); /* result=ptr2 allocated dynamically */ +eio_req *eio_stat      (const char *path, eio_cb cb); /* stat buffer=ptr2 allocated dynamically */ +eio_req *eio_lstat     (const char *path, eio_cb cb); /* stat buffer=ptr2 allocated dynamically */  eio_req *eio_mknod     (const char *path, mode_t mode, dev_t dev, eio_cb cb); -eio_req *eio_busy      (eio_tstamp delay, eio_cb cb); /* ties a thread for this long, simulating busyness */ -eio_req *eio_nop       (eio_cb cb); /* does nothing except go through the whole process */ +eio_req *eio_link      (const char *path, const char *new_path, eio_cb cb); +eio_req *eio_symlink   (const char *path, const char *new_path, eio_cb cb); +eio_req *eio_rename    (const char *path, const char *new_path, eio_cb cb);  /* for groups */  eio_req *eio_grp       (eio_cb cb); @@ -145,6 +154,20 @@ void eio_grp_limit     (eio_req *grp, int limit);  void eio_grp_add       (eio_req *grp, eio_req *req);  void eio_grp_cancel    (eio_req *grp); /* cancels all sub requests but not the group */ +/* cancel a request as soon fast as possible */ +void eio_cancel (eio_req *req); +/* destroy a request that has never been submitted */ +void eio_destroy (eio_req *req); + +/* true if the request was cancelled, useful in the invoke callback */ +#define EIO_CANCELLED(req) ((req)->flags & EIO_FLAG_CANCELLED) + +#define EIO_RESULT(req)    ((req)->result) +/* returns a pointer to the result buffer allocated by eio */ +#define EIO_BUF(req)       ((req)->ptr2) +#define EIO_STAT_BUF(req)  ((EIO_STRUCT_STAT *)EIO_BUF(req)) +#define EIO_PATH(req)      ((char *)(req)->ptr1) +  /*****************************************************************************/  /* low-level request API */ @@ -155,20 +178,13 @@ void eio_grp_cancel    (eio_req *grp); /* cancels all sub requests but not the g    (req)->finish  = (finish_cb);		\    (req)->destroy = (destroy_cb) -/* true if the request was cancelled, useful in the invoke callback */ -#define EIO_CANCELLED(req) ((req)->flags & EIO_FLAG_CANCELLED) -  /* submit a request for execution */  void eio_submit (eio_req *req); -/* cancel a request as soon fast as possible */ -void eio_cancel (eio_req *req); -/* destroy a request that has never been submitted */ -void eio_destroy (eio_req *req);  /*****************************************************************************/  /* convinience functions */ -/*ssize_t eio_sendfile (int ofd, int ifd, off_t offset, size_t count)*/ +ssize_t eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count);  #endif @@ -25,10 +25,9 @@ AC_CACHE_CHECK(for readahead, ac_cv_readahead, [AC_LINK_IFELSE([  int main(void)  {     int fd = 0; -   off64_t offset = 1;     size_t count = 2;     ssize_t res; -   res = readahead (fd, offset, count); +   res = readahead (fd, 0, count);     return 0;  }  ],ac_cv_readahead=yes,ac_cv_readahead=no)]) | 
