Libaio asynchronous I/O test code

Source: Internet
Author: User

Need Libaio libaio-devel bag, go to http://rpm.pbone.net/index.php3.

This is imitate Libaio-oracle writes, which good person goes to do a test, sends out the result, best can compare with glibc in the same environment

If there is something wrong with the code, please point out

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <libaio.h>

#define IOCB_CMD_READ 0
#define Iocb_cmd_write 1
#define IOCB_CMD_NOP 2
#define IOCB_CMD_CANCEL 3
#define IOCB_CMD_FSYNC 4
#define IOCB_CMD_FDSYNC 5
#define Iocb_cmd_running 6
#define Iocb_cmd_done 7


#define MAX_EVENTS 512
#define MAX_AIO_REAP Max_events


#define AIO_DATA Data
#define DATA_FROM_REQ (R) ((void *) (R))
#define REQ_FROM_DATA (d) ((Aiorequest *) (d))
#define MAX_IO_QUEUE 1024

#define AIOCB aiocb64
#define Aio_read AIO_READ64
#define Aio_write Aio_write64
#define AIO_ERROR Aio_error64
#define Aio_return Aio_return64
#define Aio_suspend AIO_SUSPEND64

struct AIOCB64 {
int aio_fildes;  /* File Desriptor. */
Short Aio_lio_opcode;  /* Operation to be performed. */
Short Aio_reqprio;  /* Request priority offset. */
void *aio_buf;  /* Location of buffer. */
size_t Aio_nbytes;  /* Length of transfer. */

int aio_offset;  /* File offset. */


/* These are internal to the KERNEL/LIBC. */

Long __aio_key; Kernel sets this to-1 if completed
Otherwise >= 0 (the request#)
void * __AIO_DATA; Pointer to is returned in event ' s data
int __error_code;

};


Enum
{
Lio_read,
#define Lio_read Lio_read
Lio_write,
#define Lio_write Lio_write
Lio_nop,
#define LIO_NOP Lio_nop
Lio_poll,
#define Lio_poll Lio_poll
};


Enum
{
Aio_canceled,
#define Aio_canceled aio_canceled
Aio_notcanceled,
#define Aio_notcanceled aio_notcanceled
Aio_alldone
#define Aio_alldone Aio_alldone
};

Enum
{
Lio_wait,
#define LIO_WAIT lio_wait
Lio_nowait
#define LIO_NOWAIT lio_nowait
};

typedef struct _AIOREQUEST aiorequest;


Enum
{
aior_unused = 0,/* Unused control block * *
Aior_in_progress = 0xbeef,/* in PROGRESS I/O *
Aior_complete = 0xdead,/* Completed I/O
};


struct _aiorequest
{
struct IOCB IOCB; /* Control blocks sent to kernel * *
struct AIOCB64 *AIOCB; /* User ' s control block * *
};

Static io_context_t Aio_context;


static int _aio_rw (int op, struct aiocb64 * aiocbp);


int Aio_init ()
{

if (Io_queue_init (Max_io_queue, & (Aio_context))
return-1;

return (0);

}


int aio_read64 (struct aiocb64 *aiocbp)
{

int RC;

if (AIOCBP = NULL)
{
errno = einval;
Return (-1);
}

rc = _AIO_RW (Lio_read, AIOCBP);

Return (RC > 1? 0:-1);
}

int aio_write64 (struct aiocb64 *aiocbp)
{

int RC;
struct AIOCB64 *aiocbs[] = {NULL};
if (AIOCBP = NULL)
{
errno = einval;
Return (-1);
}

Aiocbs[0] = AIOCBP;

rc = _AIO_RW (Lio_write, AIOCBP);

Return (RC > 1? 0:-1);

}


Static long aior_get_events (struct timespec *timeout)
{
struct Io_event events[max_events];
int i;
LONG ret;
Aiorequest *req;

/* For no compat defines in Libaio.h * *
#ifdef Old_libaio
ret = io_getevents (Aio_context, max_events, EVENTS, timeout);
#else
ret = Io_getevents (Aio_context, 1, max_events, EVENTS, timeout);
#endif/* Old_libaio * *

if (Ret < 0)
return (ret);
else if (ret = 0)
return (0);

for (i = 0; i < ret; i++)
{
req = Req_from_data (events[i].data);
Req->aiocb->__error_code = Events[i].res;
if (Req->aiocb->__aio_key!= aior_in_progress)
{
printf ("AIOR_GET_EVENTS:AIOCB at%p has __aio_key%ld!/n", REQ->AIOCB, Req->aiocb->__aio_key);
Continue
}
Req->aiocb->__aio_key = Aior_complete;

printf ("Aior_get_events:collected AIOCB at%p/n", REQ->AIOCB);

}

return (ret);
}


int aio_error64 (struct aiocb64 *aiocbp)
{


int ret;
struct Timespec to = {0, 0};

if (AIOCBP = NULL)
{
errno = einval;
Return (-1);
}

if (Aiocbp->__aio_key = = Aior_complete)
{

Aiorequest *req = Req_from_data (Aiocbp->__aio_data);
if (NULL!= req)
{
Aiocbp->__aio_data = NULL;
Free (req);
}

if (Aiocbp->__error_code < 0)
Return (-(Aiocbp->__error_code));
Else
return (0);
}


/* Do we have an invalid __aio_key? */
if (Aiocbp->__aio_key!= aior_in_progress)
{
errno = einval;
Return (-1);
}

ret = aior_get_events (&to);
if (Ret < 0)
{
errno =-ret;
Return (-1);
}

/*
* Aior_complete_free really shouldn ' t happen here, but it
* doesn ' t hurt.
*/
if (Aiocbp->__aio_key = = Aior_complete)
{
printf ("AIO_ERROR:AIOCB at%p complete/n", AIOCBP);
Aiorequest *req = Req_from_data (Aiocbp->__aio_data);

if (NULL!= req)
{
Aiocbp->__aio_data = NULL;
Free (req);
}

if (Aiocbp->__error_code < 0)
Return (-(Aiocbp->__error_code));
Else
return (0);
}


return (einprogress);

}

int Aio_return64 (struct aiocb64 *aiocbp)
{

Return Aio_error64 (AIOCBP);
}

int aio_suspend64 (/*const*/struct aiocb64 * const list[], int nent,
const struct TIMESPEC *timeout)
{
struct Timespec mod_timeout;
Aiorequest * REQ;
int ret = 0;
int done = 0, I;

/* Get round constness * *
if (timeout)
memcpy (&mod_timeout, timeout, sizeof (mod_timeout));

while (done = = 0)
{
for (i = 0; i < nent; i++)
{
if ((List[i]!= NULL) && ((List[i]->__aio_key = = Aior_complete))
{
ret = 0;
Done = 1;

req = Req_from_data (list[i]->__aio_data);

if (NULL!= req)
{
List[i]->__aio_data = NULL;
Free (req);
}

Break
}

}

if (done = = 0)
{
/*
* This this relative timeout be currently not
* Adjusted. This means the around the loop
* A full timeout is incurred. Hopefully the kernel would
* Soon adjust the timeout when it returns. Otherwise,
* Aio_suspend () and Aio_reap () 'll have to do
* Gettimeofday () tricks to make it work right.
*/
ret = aior_get_events (timeout &mod_timeout:null);
if (ret =-etimedout) | | (ret = 0))
{
errno = Eagain;
ret =-1;
Done = 1;
}

}


}

return (ret);


}

static int _aio_rw (int op, struct aiocb64 * PAIOCB)
{


Aiorequest *req;

struct IOCB **iocbpp;

int I, ret;

int retrycount = 0;

if (PAIOCB = NULL)
Return-einval;

Req = (Aiorequest *) malloc (sizeof (aiorequest) + sizeof (struct IOCB *));

if (req = NULL)
Return-eagain;
Else
memset (req, 0, (sizeof (aiorequest) + sizeof (struct IOCB *)));

IOCBPP = (struct IOCB * *) (req + 1);

REQ->AIOCB = PAIOCB;

Paiocb->__aio_data = req;

Paiocb->__aio_key = aior_in_progress;

Iocbpp[0] = & (REQ->IOCB);

Switch (OP)
{

Case Lio_read:
Io_prep_pread (& (REQ->IOCB), Paiocb->aio_fildes, Paiocb->aio_buf, Paiocb->aio_nbytes, paiocb-> Aio_offset);
Break


Case Lio_write:
Io_prep_pwrite (& (REQ->IOCB), Paiocb->aio_fildes, Paiocb->aio_buf, Paiocb->aio_nbytes, paiocb-> Aio_offset);
Break


Default
Return-einval;


}

Req->iocb.aio_data = Data_from_req (req);

ret = Io_submit (Aio_context, 1, IOCBPP);

if (-eagain = ret)
{
ret = Io_submit (Aio_context, 1, IOCBPP);
}

if (Ret < 0)
{
errno =-ret;
ret =-1;
}

return ret;
}

const int data_len = 8192;
const int data_size = 50000;

Char bufferao[8192] __attribute__ ((aligned (4096)));


void Testlibaio ()
{
    struct timeval start;
    struct Timeval end;
    int ret;
   
   
    int i = 0;

int dwflags = O_RDWR | O_largefile | O_direct | O_sync | O_creat |  O_EXCL; //| O_noatime

dwflags = O_rdwr | O_largefile | O_sync | O_creat | O_EXCL;

int fd = open ("Libaio_write.dat", dwflags);

if (fd<0)
{
Perror ("Open error:");
Return
}

if (Ftruncate64 (FD, Data_len * data_size))
{
Perror ("Ftruncate64 error:");
Return
}

Aio_init ();

Gettimeofday (&start, NULL);



for (; i<= data_size; i++)
{
struct AIOCB Staio;

memset (Bufferao, i%128, Data_len);

memset (&staio, 0, sizeof (Staio));
Staio.aio_buf = Bufferao;
Staio.aio_nbytes = Data_len;
Staio.aio_offset = i * data_len;
Staio.aio_fildes = FD;

ret = Aio_write (&staio);

if (Ret < 0)
{
Perror ("Libaio_write error:");
Return
}

struct AIOCB *cblist[1] = {&staio};

ret = Aio_error (&staio);

if (ret = 0) {

Already completed

}
else if (ret = = einprogress) {
if (aio_suspend (/*const*/struct AIOCB *const*) cblist, 1, NULL)
{
Perror ("Libaio_suspend error:");
Return
}
}
else {
Perror ("Libaio_error error:");
Return
}
/*
if (Aio_return (&staio)!= Data_len)
{
Perror ("Libaio_return error:");
Return
}
*/
}

Gettimeofday (&end, NULL);

Close (FD);

printf ("/nlibaio o_direct Second:%d microsec:%d/n", End.tv_sec-start.tv_sec, end.tv_usec-start.tv_usec);
}


int main ()
{
Testlibaio ();
return 1;
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.